波動率

在 Python 中正確應用 GARCH

  • July 2, 2020

**問題:**正確使用 GARCH(1,1)

**研究目的:**預測波動率/變異數。

使用的工具: Python

工具: SPX(特別調整的收盤價)

**參考資料:**關於 GARCH 模型的估計與 Nordea 股票價格的應用(Chao Li,2007)

**注意:**我檢查了幾乎所有討論 GARCH 的 Quant.SE 文章,但我沒有看到任何與我所要求的內容大致相同的文章。

描述:

當我遇到波動率預測的概念時,我正在對股票價格的歷史波動率進行個人研究。這自然引起了我的興趣。我登陸了上述參考資料。經過幾次閱讀後,我決定看看我對 GARCH(1,1) 應用的理解是否正確,以及在調查歷史波動率時是否可以深入了解如何使用它。

為此,我將使用 SPX 價格,以及 Python 中的btpandasarch庫。

我的初始程式步驟如下。

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來獲取omegabetaalpha.

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

現在我得出一個預測的波動率值。我的問題如下:

  1. 在 codeblock[5]中,使用了:returns = df['pct_change'] * 100. 我武斷地認為這是表面價值,因為這是我看到 GARCH 計算中使用的回報的方式。但是,在 的初始計算中variance,我從來不需要將pct_change列乘以 100。我是保留它還是應該將pct_change列按原樣提供給函式?
  2. 如果我按原樣將pct_change列提供給函式,則 、 和 的值會omega變得beta相當alpha小,這會將forecast_var和的forecast_vol值降低一個數量級。顯然,精度的變化導致我的歷史波動率值和我的預測波動率值之間的比較有問題。我該如何解決這個問題?
  3. 我應該完全使用不同的方法嗎?

請指出我可能遺漏的任何明顯錯誤或任何遺漏的邏輯

使用 *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

我希望這能澄清一些事情。

引用自:https://quant.stackexchange.com/questions/16730