在 Python 中正確應用 GARCH
**問題:**正確使用 GARCH(1,1)
**研究目的:**預測波動率/變異數。
使用的工具: Python
工具: SPX(特別調整的收盤價)
**參考資料:**關於 GARCH 模型的估計與 Nordea 股票價格的應用(Chao Li,2007)
**注意:**我檢查了幾乎所有討論 GARCH 的 Quant.SE 文章,但我沒有看到任何與我所要求的內容大致相同的文章。
描述:
當我遇到波動率預測的概念時,我正在對股票價格的歷史波動率進行個人研究。這自然引起了我的興趣。我登陸了上述參考資料。經過幾次閱讀後,我決定看看我對 GARCH(1,1) 應用的理解是否正確,以及在調查歷史波動率時是否可以深入了解如何使用它。
為此,我將使用 SPX 價格,以及 Python 中的
bt
、pandas
和arch
庫。我的初始程式步驟如下。
In [1]: import pandas as pd ...: import bt ...: import arch ...: In [2]: df = bt.get('SPX', start='1990-01-01') In [3]: df.head() Out[3]: spx Date 1990-01-02 359.69 1990-01-03 358.76 1990-01-04 355.67 1990-01-05 352.20 1990-01-08 353.79 In [4]: df['pct_change'] = df['spx'].pct_change().dropna() ...: df['stdev21'] = pd.rolling_std(df['pct_change'], 21) ...: df['hvol21'] = df['stdev21']*(252**0.5) # Annualize. ...: df['variance'] = df['hvol21']**2 ...: df = df.dropna() # Remove rows with blank cells. ...: df.head() Out[4]: spx pct_change stdev21 hvol21 variance Date 1990-03-02 335.54 0.008415 0.007304 0.115946 0.013443 1990-03-05 333.74 -0.005364 0.007425 0.117863 0.013892 1990-03-06 337.93 0.012555 0.007770 0.123344 0.015214 1990-03-07 336.95 -0.002900 0.007804 0.123889 0.015348 1990-03-08 340.27 0.009853 0.007855 0.124689 0.015547
以上很簡單。現在,我將使用Python 模組
GARCH
提供的函式arch
來獲取omega
、beta
和alpha
.In [5]: returns = df['pct_change'] * 100 ...: am = arch.arch_model(returns) ...: res = am.fit(iter=5) ...: res.params Iteration: 5, Func. Count: 39, Neg. LLF: 8447.41751792 Iteration: 10, Func. Count: 74, Neg. LLF: 8443.32521758 Optimization terminated successfully. (Exit mode 0) Current function value: 8443.31731767 Iterations: 12 Function evaluations: 86 Gradient evaluations: 12 Out[5]: mu 0.058224 omega 0.011511 alpha[1] 0.079411 beta[1] 0.911240 Name: params, dtype: float64
遵循公式 $ \sigma_t^2 = \omega + \alpha_1{a^2}{t-1} + \beta_1{\sigma^2}{t-1} $ ,我執行以下程式碼。
In [6]: df['C'] = res.params['omega'] ...: df['B'] = df['variance'] * res.params['beta[1]'] ...: df['A'] = (df['pct_change']**2) * res.params['alpha[1]'] ...: df['forecast_var'] = df.loc[:,'C':'A'].sum(axis=1) ...: df['forecast_vol'] = df['forecast_var']**0.5 ...: df.head() ...: Out[6]: spx pct_change stdev21 hvol21 variance C \ Date 1990-03-02 335.54 0.008415 0.007304 0.115946 0.013443 0.011511 1990-03-05 333.74 -0.005364 0.007425 0.117863 0.013892 0.011511 1990-03-06 337.93 0.012555 0.007770 0.123344 0.015214 0.011511 1990-03-07 336.95 -0.002900 0.007804 0.123889 0.015348 0.011511 1990-03-08 340.27 0.009853 0.007855 0.124689 0.015547 0.011511 B A forecast_var forecast_vol Date 1990-03-02 0.012250 0.000006 0.023767 0.154165 1990-03-05 0.012659 0.000002 0.024172 0.155474 1990-03-06 0.013863 0.000013 0.025387 0.159333 1990-03-07 0.013986 0.000001 0.025498 0.159681 1990-03-08 0.014167 0.000008 0.025686 0.160269
現在我得出一個預測的波動率值。我的問題如下:
- 在 codeblock
[5]
中,使用了:returns = df['pct_change'] * 100
. 我武斷地認為這是表面價值,因為這是我看到 GARCH 計算中使用的回報的方式。但是,在 的初始計算中variance
,我從來不需要將pct_change
列乘以 100。我是保留它還是應該將pct_change
列按原樣提供給函式?- 如果我按原樣將
pct_change
列提供給函式,則 、 和 的值會omega
變得beta
相當alpha
小,這會將forecast_var
和的forecast_vol
值降低一個數量級。顯然,精度的變化導致我的歷史波動率值和我的預測波動率值之間的比較有問題。我該如何解決這個問題?- 我應該完全使用不同的方法嗎?
請指出我可能遺漏的任何明顯錯誤或任何遺漏的邏輯
使用 *100 還是只使用 pct_change 都沒有關係,只要保持一致即可。然而,在實踐中,由於在 scipy/arch 中使用的基礎優化算法/預設容差中的基礎浮點數值不穩定性,以 % 表示的回報,即乘以 100,將有更好的機會在擬合期間收斂模型。
錯誤從In開始
$$ 6 $$. 擬合模型後,您可以在 res.conditional_volatility 處獲得預測條件波動率,您需要對其進行年化處理,即乘以 sqrt(252)。 請注意,在 GARCH 公式中,a(t-1) 是模型殘差,您可以在 res.residual 中找到它。它不是 pct_change**2。要從 pct_change 得出殘差,您必須在方程式中逆向工作。但這已經在 res.resid 中為您完成了
無論如何,In中的正確公式
$$ 6 $$對於 forecast_vol 應該是:
0.01 * np.sqrt(res.params['omega'] + res.params['alpha[1]'] * res.resid**2 + res.conditional_volatility**2 * res.params['beta[1]'])
^^ 在這裡,您正在預測下一天的瞬時波動。乘以 0.01 以處理較早的每日回報 (pct_change) 乘以 100
我希望這能澄清一些事情。