As far as I understand, forecasting stock price volatility should be more achievable than forecasting absolute prices or returns. It seems as though GARCH models are the traditional and most widely used for forecasting volatility. I have attempted to implement a GARCH model to make a multistep ahead volatility forecast in Python:
import utils
import numpy as np
import arch
import matplotlib.pyplot as plt
ticker = 'AAPL'
forecast_horizon = 30
# RETRIEVE 5 YEAR IEX TRADING PRICES THROUGH CUSTOM API
prices = utils.dw.get(ticker, source='iex', iex_range='5y')
df = prices[['date', 'close']]
# RETURNS
# df['returns'] = np.log(df['close']).diff()
df['returns'] = df['close'].pct_change()
df.dropna(inplace=True)
df.reset_index(inplace=True, drop=True)
# FIT GARCH
garch = arch.arch_model(df['returns'][:-forecast_horizon])
fitted_garch = garch.fit(disp=False)
print(fitted_garch.summary())
# FUTURE FORECAST
forecast = fitted_garch.forecast(horizon=forecast_horizon).residual_variance.values[-1]
# CALCULATE ACTUAL VOLATILITY
df['monthly_stddev'] = df['returns'].rolling(21).std()
df.dropna(inplace=True)
df.reset_index(inplace=True, drop=True)
df['volatility'] = df['monthly_stddev'] * np.sqrt(252)
df.drop('monthly_stddev', axis=1, inplace=True)
# PLOT ACTUAL VS FORECASTED VOLATILITY
plt.plot(df['volatility'][-forecast_horizon:].reset_index(drop=True), label='Actual')
plt.plot(forecast, label='Forecast')
plt.legend()
plt.show()
The results are not very good at all, but I think it is mainly down to my misunderstanding of how the GARCH model works, and what it outputs.
My questions are:
Given that we input returns into the GARCH model, what is the output of its forecast (
fitted_model.forecast().variance
/fitted_model.forecast().residual_variance
? Can this output be interpreted directly as the volatility forecast? Or does some transformation need to be applied to this forecast to obtain the volatility values?Is there any way to retrieve the GARCH model's fitted values on the training set? I would like to not only plot the model's forecast for the out-of-sample test set of the final 30 days, but also plot the learnt values for the entire training set to get an idea of how well the model learnt the training data.
Is my calculation from actual returns to actual volatility correct for comparing it to the GARCH model's volatility forecast to determine how accurate the model's forecast is?
Is it suitable to use only GARCH(1, 1) here? Should I be trying other values for p and q? I saw somewhere where auto_arima was used to determine p and q, and these were then set in the GARCH model.