0
$\begingroup$

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:

enter image description here

This leads to the following 2 questions:

  1. 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?

  2. 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.

$\endgroup$
5
  • $\begingroup$ Possible duplicate of Is this the correct way to forecast stock price volatility using GARCH $\endgroup$ Jan 26 '19 at 10:37
  • 3
    $\begingroup$ That was my original question, which I have since found the solution to and am now faced with the problem outlined here. I will add an answer to my original question. $\endgroup$
    – KOB
    Jan 26 '19 at 10:38
  • $\begingroup$ you should merge the two posts because the second is just an extension of the first. $\endgroup$
    – develarist
    Apr 26 '20 at 21:27
  • $\begingroup$ One thing you need to take note (as you already mentioned): n.roll does not actually generate forecast into the future (as in dates after your latest observation was recorded). out.sample dictates the number of existing observations to be kept apart when we fit the model. The n.roll if specified, then would generate forecasts for these reserved observations, allowing you to compare the fitted value and forecast. To actually peek into the "future", we don't specify n.roll; rather, we use n.ahead and n.sim. They don't rely on previous data but the unconditional means of the model. $\endgroup$
    – stucash
    Jul 28 '20 at 7:03
  • $\begingroup$ check out rugarch author's example on the realGARCH model, a google search would take you there. $\endgroup$
    – stucash
    Jul 28 '20 at 7:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.