Skip to content
All library documents

Setting Up Rolling GARCH Volatility Forecasts in R

Article Quant Q&A · Author: KOB

Summary

The document presents a workflow for forecasting stock volatility with a GARCH(1,1) model through R’s rugarch package called from Python with rpy2. It calculates daily log returns, fits a Student-t model to returns scaled as percentages, reserves a final block of observations as out-of-sample data, and requests successive one-step forecasts. It then rescales the fitted and forecast standard deviations to annualized volatility for comparison with a rolling historical measure.

The author asks whether the reserved observations are truly excluded from estimation, because the resulting forecasts look unexpectedly strong during a period of high volatility. They also ask how to fit through the latest available observation and forecast future values. The document supplies code and describes a plotted comparison, but it contains no answer, diagnostic checks, or forecast evaluation beyond the author's visual concern. In particular, it does not establish whether the package’s out-sample and rolling forecast settings produce the intended information boundary, so that behavior needs checking against the package semantics before interpreting the plot.

Key ideas

  • The example fits a GARCH(1,1) model to scaled daily log returns using a Student-t distribution.
  • It requests rolling one-step forecasts over a held-out period and compares them with annualized realized volatility.
  • The author questions whether the held-out observations affect fitting and how to forecast beyond the latest observation.
  • The document gives no resolution or statistical evaluation of the apparent forecast performance.

Tags

Full text
# Rolling forecast using GARCH model


# Rolling forecast using GARCH model












EDIT

This is not a duplicate of my original question linked, since I have since overcome that problem and have posted an answer. Since solving the previous problem, I have run into the problem outlined here

I am attempting to perform a rolling forecast of the volatility of a given stock 30 days into the future (i.e. forecast time t+1, then use this forecast when forecasting t+2, and so on...)

I am doing so using R's `rugarch` package, which I have implemented in Python using the `rpy2` package. (I find the Python package poorly documented and more difficult to use. Most of these packages are alo far more mature in R).

Here is my code so far, where the model is fit to the whole time series of the stock's returns up to the final 30 days of data I have. I then perform (I think) a rolling forecast for the final 30 days of the unseen data I have.

```
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

ticker = 'AAPL'
forecast_horizon = 30

prices = utils.dw.get(filename=ticker, source='iex', iex_range='5y')
df = prices[['date', 'close']]

df['daily_returns'] = np.log(df['close']).diff()            # Daily log returns
df['monthly_std'] = df['daily_returns'].rolling(21).std()   # Standard deviation across trading month
df['annual_vol'] = df['monthly_std'] * np.sqrt(252)         # Convert monthly standard devation to annualized volatility
df = df.dropna().reset_index(drop=True)

# Initialize R GARCH model
rugarch = importr('rugarch')
garch_spec = rugarch.ugarchspec(
    mean_model=robjects.r('list(armaOrder = c(0,0))'),
    variance_model=robjects.r('list(garchOrder=c(1,1))'),
    distribution_model='std'
)

# Used to convert training set to R list for model input
numpy2ri.activate()

# Train R GARCH model on returns as %
garch_fitted = rugarch.ugarchfit(
    spec=garch_spec,
    data=df['daily_returns'].values * 100,
    out_sample=forecast_horizon
)

numpy2ri.deactivate()

# Model's fitted standard deviation values
# Revert previous multiplication by 100
# Convert to annualized volatility
fitted = 0.01 * np.sqrt(252) * np.array(garch_fitted.slots['fit'].rx2('sigma')).flatten()

# Forecast using R GACRH model
garch_forecast = rugarch.ugarchforecast(
    garch_fitted,
    n_ahead=1,
    n_roll=forecast_horizon - 1
)

# Model's forecasted standard deviation values
# Revert previous multiplication by 100
# Convert to annualized volatility
forecast = 0.01 * np.sqrt(252) * np.array(garch_forecast.slots['forecast'].rx2('sigmaFor')).flatten()

volatility = pd.DataFrame({
    'actual': df['annual_vol'].values,
    'model': np.append(fitted, forecast),
})

plt.plot(volatility['actual'][:-forecast_horizon], label='Train')
plt.plot(volatility['actual'][-forecast_horizon - 1:], label='Test')
plt.plot(volatility['model'][:-forecast_horizon], label='Fitted')
plt.plot(volatility['model'][-forecast_horizon - 1:], label='Forecasted')
plt.legend()
plt.show()
```

This code uses my own API to retrieve the daily prices, but this can be changed to your own price data to run the code.

For AAPL, this script results in the following plot of actual vs fitted/forecasted volatility:

This leads to the following 2 questions:

- This forecast on unseen data seems suspisciously impressive, especially given that Apple's recent volatility was so high in the test set - higher than anything the model was fitted to. Is this rolling forecast working the way I am expecting to? Or is the model actually seeing these final 30 days during fitting somehow?

- If this rolling forecast is working as I expect, how can I now fit the model to the entire time series of training data I have up to today, and then perform a rolling forecast 30 days into the future? I cannot find anything in the documentation or any examples online that does this. No matter how good the model is on this test of historical data I have performed, it is completely useless if it can't be use to make actual forecasts into the future.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.