Я пытаюсь выполнить скользящий прогноз волатильности данной акции через 30 дней в будущем (т. Е. Прогнозируемое время t + 1, затем использовать этот прогноз при прогнозировании t + 2 и т. Д.)
Я делаю это, используя пакет R's rugarch
, который я реализовал в Python, используя пакет rpy2
.(Я считаю, что пакет Python плохо документирован и более сложен в использовании. Большинство этих пакетов намного более зрелы в R).
Вот мой код, который пока подходит для всей временной серии.из акций возвращается до последних 30 дней данных, которые у меня есть.Затем я выполняю (я думаю) скользящий прогноз на последние 30 дней невидимых данных, которые у меня есть.
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()
Этот код использует мой собственный API для получения дневных цен, но его можно изменить на вашсобственные данные цены для выполнения кода.
Для AAPL этот сценарий приводит к следующему графику фактической зависимости от установленной / прогнозируемой волатильности:
Это приводит к следующим 2 вопросам:
Этот прогноз по невидимым данным кажется подозрительно впечатляющим, особенно с учетом того, что недавняя волатильность Apple была настолько высокой в тестовом наборе - выше, чем что-либо другое.Модель была приспособлена для.Этот скользящий прогноз работает так, как я ожидаю?Или модель как-то видит эти последние 30 дней во время подгонки?
Если этот скользящий прогноз работает так, как я ожидаю, как теперь я могу подогнать модель под весь временной ряд обучения?У меня есть данные до сегодняшнего дня, а затем выполнить скользящий прогноз на 30 дней в будущее?Я не могу найти ничего в документации или каких-либо примерах онлайн, которые делают это.Независимо от того, насколько хороша модель для этого теста исторических данных, которые я выполнил, она совершенно бесполезна, если ее нельзя использовать для составления реальных прогнозов в будущее.