0
$\begingroup$

Aim: Forecast VIX using GARCH(1,1)
Reason: I want to be able to forecast VIX on several horizons, in order to be able to forecast the SP500 index through linear regression.
Tools used: Python, arch_model from the arch library, YahooFinancials

I am building a model to be able to forecast future values for the SP500's Adjusted Closing Prices using VIX as the independent variable, as it has a (negative) correlation with the SP500. In order to do that, I need to first forecast VIX future values, and I've been thinking about using GARCH(1,1) to achieve that. However, I'm not quite sure if what I'm doing is correct. I would highly appreciate any input.

The following code is only for the GARCH(1,1) to forecast VIX. The linear regression to forecast the SP500's Adjusted Closing Prices isn't included here, as I'm still trying to figure out how to add the forecasted VIX to that model.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from rpy2.robjects.packages import importr
import rpy2.robjects as robjects
from rpy2.robjects import numpy2ri

pd.options.mode.chained_assignment = None
import yfinance as yf
from yahoofinancials import YahooFinancials
import pandas_datareader.data as wb

import datetime
import datetime as dt
from datetime import date
from datetime import timedelta

from arch import arch_model

#First we define the start and end dates
start_date = date(1990, 1, 1)
end_date =  date.today() - datetime.timedelta(days=1)

#We then import the data from YahooFinance's API
In [3]: VIX_df = yf.download('^VIX', start = start_date, end = end_date, interval = '1d')
Out[3]: [*********************100%***********************]  1 of 1 completed

#Then we get the log returns
In [4]: VIX_df['log_returns'] = np.log(VIX_df['Adj Close']) - np.log(VIX_df['Adj Close'].shift(1))
   ...: returns = VIX_df['log_returns'].dropna()
   ...: returns
Out[4]: Date
   ...: 1990-01-03    0.053640
   ...: 1990-01-04    0.055079
   ...: 1990-01-05    0.045266
   ...: 1990-01-08    0.007431
   ...: 1990-01-09    0.091444
   ...:                 ...   
   ...: 2022-06-09    0.085166
   ...: 2022-06-10    0.061684
   ...: 2022-06-13    0.203713
   ...: 2022-06-14   -0.039879
   ...: 2022-06-15   -0.098619
   ...: Name: log_returns, Length: 8177, dtype: float64

#The horizon is defined and the model is created
n_test = 30
model = arch_model(returns, mean='constant', vol='GARCH', p=1, q=1, dist='Normal', rescale=True)

#The model is fit
In [6]: split_date = dt.datetime(2021,12,31)
   ...: res = model.fit(update_freq=5, last_obs=split_date)
   ...: scale = res.scale
   ...: print(model_fit.summary())
Out[6]: Iteration:      5,   Func. Count:     41,   Neg. LLF: 7764.529955193779
Optimization terminated successfully.    (Exit mode 0)
            Current function value: 7764.463716026663
            Iterations: 9
            Function evaluations: 68
            Gradient evaluations: 9
                     Constant Mean - GARCH Model Results                      
==============================================================================
Dep. Variable:            log_returns   R-squared:                       0.000
Mean Model:             Constant Mean   Adj. R-squared:                  0.000
Vol Model:                      GARCH   Log-Likelihood:               -7909.06
Distribution:                  Normal   AIC:                           15826.1
Method:            Maximum Likelihood   BIC:                           15854.2
                                        No. Observations:                 8177
Date:                Fri, Jun 17 2022   Df Residuals:                     8176
Time:                        00:26:36   Df Model:                            1
                                  Mean Model                                  
==============================================================================
                  coef    std err          t      P>|t|       95.0% Conf. Int.
------------------------------------------------------------------------------
mu         -8.0763e-04  6.478e-03     -0.125      0.901 [-1.350e-02,1.189e-02]
                              Volatility Model                              
============================================================================
                 coef    std err          t      P>|t|      95.0% Conf. Int.
----------------------------------------------------------------------------
omega          0.0507  1.303e-02      3.891  9.980e-05 [2.517e-02,7.627e-02]
alpha[1]       0.1322  2.438e-02      5.423  5.876e-08   [8.442e-02,  0.180]
beta[1]        0.7583  4.677e-02     16.213  4.098e-59     [  0.667,  0.850]
============================================================================

Covariance estimator: robust

#Then we produce the forcast
In [7]: forecasts = res.forecast(horizon=n_test, start=split_date, reindex=False)
   ...: print(forecasts.variance.iloc[-n_test:])
Out[7]:                 h.01      h.02      h.03      h.04      h.05      h.06  \
Date                                                                     
2022-05-04  0.878434  0.831696  0.790164  0.753259  0.720464  0.691323   
2022-05-05  1.272253  1.181647  1.101133  1.029588  0.966013  0.909519   
2022-05-06  1.027305  0.963984  0.907716  0.857716  0.813286  0.773805   
2022-05-09  1.090585  1.020215  0.957684  0.902118  0.852742  0.808866   
2022-05-10  0.911314  0.860913  0.816127  0.776329  0.740965  0.709540   
2022-05-11  0.742402  0.710817  0.682750  0.657809  0.635647  0.615954   
2022-05-12  0.620353  0.602363  0.586378  0.572172  0.559549  0.548333   
2022-05-13  0.641197  0.620885  0.602836  0.586797  0.572545  0.559881   
2022-05-16  0.568479  0.556268  0.545417  0.535774  0.527206  0.519592   
2022-05-17  0.515429  0.509127  0.503527  0.498551  0.494129  0.490199   
2022-05-18  0.827829  0.786728  0.750205  0.717751  0.688912  0.663285   
2022-05-19  0.714628  0.686137  0.660819  0.638322  0.618330  0.600566   
2022-05-20  0.591563  0.576780  0.563644  0.551971  0.541599  0.532381   
2022-05-23  0.512542  0.506562  0.501247  0.496525  0.492329  0.488600   
2022-05-24  0.453644  0.454224  0.454740  0.455198  0.455605  0.455967   
2022-05-25  0.412472  0.417638  0.422229  0.426309  0.429934  0.433156   
2022-05-26  0.375723  0.384983  0.393211  0.400523  0.407021  0.412795   
2022-05-27  0.394275  0.401468  0.407861  0.413541  0.418588  0.423074   
2022-05-31  0.353645  0.365364  0.375778  0.385032  0.393255  0.400562   
2022-06-01  0.323358  0.338451  0.351863  0.363781  0.374371  0.383782   
2022-06-02  0.315089  0.331103  0.345334  0.357979  0.369216  0.379201   
2022-06-03  0.289474  0.308341  0.325107  0.340005  0.353244  0.365008   
2022-06-06  0.271703  0.292550  0.311075  0.327536  0.342164  0.355162   
2022-06-07  0.280641  0.300493  0.318133  0.333808  0.347737  0.360115   
2022-06-08  0.263383  0.285157  0.304506  0.321699  0.336977  0.350553   
2022-06-09  0.346689  0.359183  0.370286  0.380151  0.388918  0.396708   
2022-06-10  0.363898  0.374475  0.383874  0.392227  0.399648  0.406243   
2022-06-13  0.876871  0.830307  0.788930  0.752162  0.719490  0.690457   
2022-06-14  0.735047  0.704281  0.676943  0.652649  0.631062  0.611879   
2022-06-15  0.735374  0.704572  0.677201  0.652879  0.631266  0.612060   

                h.07      h.08      h.09      h.10  ...      h.21      h.22  \
Date                                                ...                       
2022-05-04  0.665427  0.642417  0.621969  0.603799  ...  0.498392  0.493987   
2022-05-05  0.859318  0.814710  0.775070  0.739846  ...  0.535502  0.526964   
2022-05-06  0.738722  0.707546  0.679844  0.655227  ...  0.512420  0.506453   
2022-05-09  0.769877  0.735231  0.704445  0.677088  ...  0.518383  0.511752   
2022-05-10  0.681615  0.656801  0.634751  0.615158  ...  0.501490  0.496741   
2022-05-11  0.598454  0.582904  0.569085  0.556806  ...  0.485573  0.482597   
2022-05-12  0.538365  0.529508  0.521638  0.514644  ...  0.474072  0.472377   
2022-05-13  0.548627  0.538627  0.529741  0.521845  ...  0.476036  0.474122   
2022-05-16  0.512826  0.506814  0.501471  0.496724  ...  0.469184  0.468033   
2022-05-17  0.486708  0.483605  0.480848  0.478398  ...  0.464185  0.463591   
2022-05-18  0.640513  0.620277  0.602296  0.586318  ...  0.493623  0.489750   
2022-05-19  0.584780  0.570753  0.558288  0.547212  ...  0.482956  0.480271   
2022-05-20  0.524191  0.516913  0.510446  0.504699  ...  0.471359  0.469966   
2022-05-23  0.485286  0.482342  0.479725  0.477400  ...  0.463913  0.463349   
2022-05-24  0.456289  0.456574  0.456828  0.457054  ...  0.458363  0.458417   
2022-05-25  0.436018  0.438562  0.440822  0.442831  ...  0.454483  0.454970   
2022-05-26  0.417925  0.422484  0.426536  0.430136  ...  0.451020  0.451892   
2022-05-27  0.427059  0.430601  0.433748  0.436544  ...  0.452768  0.453446   
2022-05-31  0.407055  0.412825  0.417953  0.422509  ...  0.448939  0.450044   
2022-06-01  0.392144  0.399575  0.406178  0.412046  ...  0.446085  0.447508   
2022-06-02  0.388073  0.395958  0.402964  0.409189  ...  0.445306  0.446815   
2022-06-03  0.375462  0.384751  0.393006  0.400340  ...  0.442892  0.444670   
2022-06-06  0.366713  0.376977  0.386097  0.394202  ...  0.441218  0.443182   
2022-06-07  0.371113  0.380887  0.389572  0.397289  ...  0.442060  0.443931   
2022-06-08  0.362617  0.373337  0.382863  0.391328  ...  0.440434  0.442486   
2022-06-09  0.403631  0.409782  0.415248  0.420106  ...  0.448284  0.449461   
2022-06-10  0.412104  0.417311  0.421939  0.426051  ...  0.449906  0.450902   
2022-06-13  0.664658  0.641733  0.621362  0.603259  ...  0.498244  0.493856   
2022-06-14  0.594833  0.579686  0.566226  0.554266  ...  0.484880  0.481981   
2022-06-15  0.594994  0.579829  0.566353  0.554379  ...  0.484911  0.482008   

                h.23      h.24      h.25      h.26      h.27      h.28  \
Date                                                                     
2022-05-04  0.490074  0.486596  0.483506  0.480760  0.478319  0.476151   
2022-05-05  0.519377  0.512635  0.506644  0.501321  0.496590  0.492387   
2022-05-06  0.501151  0.496439  0.492252  0.488532  0.485226  0.482288   
2022-05-09  0.505859  0.500623  0.495971  0.491836  0.488162  0.484897   
2022-05-10  0.492520  0.488770  0.485438  0.482476  0.479845  0.477507   
2022-05-11  0.479952  0.477602  0.475513  0.473657  0.472008  0.470543   
2022-05-12  0.470870  0.469532  0.468342  0.467285  0.466346  0.465511   
2022-05-13  0.472421  0.470910  0.469567  0.468374  0.467313  0.466371   
2022-05-16  0.467010  0.466102  0.465294  0.464577  0.463939  0.463373   
2022-05-17  0.463063  0.462594  0.462178  0.461807  0.461478  0.461186   
2022-05-18  0.486308  0.483250  0.480532  0.478118  0.475972  0.474065   
2022-05-19  0.477885  0.475765  0.473881  0.472207  0.470720  0.469398   
2022-05-20  0.468728  0.467628  0.466651  0.465782  0.465010  0.464325   
2022-05-23  0.462848  0.462403  0.462008  0.461657  0.461344  0.461067   
2022-05-24  0.458466  0.458509  0.458547  0.458581  0.458612  0.458639   
2022-05-25  0.455402  0.455787  0.456128  0.456432  0.456702  0.456941   
2022-05-26  0.452668  0.453357  0.453969  0.454513  0.454997  0.455426   
2022-05-27  0.454048  0.454584  0.455059  0.455482  0.455857  0.456191   
2022-05-31  0.451025  0.451897  0.452672  0.453361  0.453972  0.454516   
2022-06-01  0.448771  0.449895  0.450892  0.451779  0.452567  0.453268   
2022-06-02  0.448156  0.449348  0.450407  0.451348  0.452184  0.452927   
2022-06-03  0.446250  0.447654  0.448902  0.450010  0.450995  0.451871   
2022-06-06  0.444928  0.446479  0.447858  0.449082  0.450171  0.451138   
2022-06-07  0.445593  0.447070  0.448383  0.449549  0.450585  0.451506   
2022-06-08  0.444309  0.445929  0.447369  0.448648  0.449785  0.450795   
2022-06-09  0.450507  0.451437  0.452263  0.452997  0.453650  0.454229   
2022-06-10  0.451788  0.452575  0.453274  0.453896  0.454448  0.454939   
2022-06-13  0.489957  0.486493  0.483414  0.480678  0.478247  0.476087   
2022-06-14  0.479405  0.477115  0.475081  0.473273  0.471667  0.470240   
2022-06-15  0.479429  0.477137  0.475100  0.473291  0.471682  0.470253   

                h.29      h.30  
Date                            
2022-05-04  0.474224  0.472512  
2022-05-05  0.488651  0.485332  
2022-05-06  0.479678  0.477358  
2022-05-09  0.481996  0.479418  
2022-05-10  0.475429  0.473582  
2022-05-11  0.469241  0.468084  
2022-05-12  0.464770  0.464111  
2022-05-13  0.465533  0.464789  
2022-05-16  0.462869  0.462422  
2022-05-17  0.460926  0.460695  
2022-05-18  0.472370  0.470865  
2022-05-19  0.468223  0.467180  
2022-05-20  0.463715  0.463174  
2022-05-23  0.460820  0.460601  
2022-05-24  0.458663  0.458684  
2022-05-25  0.457154  0.457344  
2022-05-26  0.455808  0.456147  
2022-05-27  0.456488  0.456751  
2022-05-31  0.454999  0.455429  
2022-06-01  0.453890  0.454443  
2022-06-02  0.453587  0.454173  
2022-06-03  0.452648  0.453340  
2022-06-06  0.451997  0.452761  
2022-06-07  0.452325  0.453052  
2022-06-08  0.451693  0.452490  
2022-06-09  0.454744  0.455202  
2022-06-10  0.455375  0.455762  
2022-06-13  0.474167  0.472461  
2022-06-14  0.468971  0.467844  
2022-06-15  0.468983  0.467855  

[30 rows x 30 columns]

#Finally, we plot the forecast
In [8]: plt.rcParams["figure.figsize"] = 18, 5
   ...: plt.plot(forecasts.variance[-5:])
   ...: plt.show()

The end result is this plot: enter image description here

Which makes me wonder if I'm forecasting anything at all, because every so-called step-ahead is stacked on top of each date, rather than being forecasted as new data on new dates starting from the last date available. I know my code is quite faulty, and I feel like a headless chicken, because I have no idea what to fix. Furthermore, as I said before, I'm still trying to figure out how to use the output of this GARCH to forecast the Adjusted Closing Prices of the SP500, considering the output from GARCH is variance.

Any help is highly appreciated. Thanks in advance.

$\endgroup$
5
  • $\begingroup$ With regards to the code, setting the horizon $h$ to 30 in the arch package computes multistep recursive forecasts of the GARCH model (see here p. 449) for each day. This is why you get a $Date \times 30$ forecast matrix. Also when $h \rightarrow \infty$ the conditional forecast converges towards the unconditional variance of the GARCH process ($\frac{\omega}{1- \alpha - \beta}=0.463$ in your case). This is likely the reason why the forecast-values for $h=30$ are close to 0.46. $\endgroup$
    – Pleb
    Jun 17, 2022 at 8:44
  • $\begingroup$ Thank you @Pleb! I was wondering why variance seemed to converge at around 0.46X. That being said, I don't think my h is that large. Is there a way to fix it? $\endgroup$
    – GusC
    Jun 18, 2022 at 11:39
  • $\begingroup$ In my opinion your $h$ is quite large. Another way to forecast 30 days (1 month) ahead is simply to sparse sample your data to monthly data. Then $h=1$ will be the next monthly estimate. This, of course, has the downside of not using all available data. $\endgroup$
    – Pleb
    Jun 18, 2022 at 12:03
  • $\begingroup$ I see, what do you think would be a reasonable h? As for the forecast, I sadly need to work with daily data, particularly because the idea is to use the results from this model to be able to predict the SP500, which also has daily data. $\endgroup$
    – GusC
    Jun 18, 2022 at 15:11
  • $\begingroup$ If you don't need monthly forecasts, then set $h=1$ and work with 1-step ahead forecasts. This will also be more straightforward as the 1-step ahead forecast is "embedded" into the GARCH equation. While I don't have much expertise in forecasting the VIX index, I found two papers (one focuses on GARCH and another on the HAR model) that tries to forecast the VIX index. They are provided here and here and might give you some inspiration. In the GARCH paper, they compare their findings to the HAR model of the latter paper. $\endgroup$
    – Pleb
    Jun 18, 2022 at 17:26

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.