Я тестирую пакет ARCH для прогнозирования дисперсии (стандартного отклонения) двух серий с использованием GARCH (1,1).
Это первая часть моего кода
import pandas as pd
import numpy as np
from arch import arch_model
returns = pd.read_csv('ret_full.csv', index_col=0)
returns.index = pd.to_datetime(returns.index)
Ibovespa Returns
Первая серия - это 1-й фьючерсный контракт на индекс Ibovespa, с наблюдаемой годовой волатильностью, очень близкой к прогнозу Garch.
Первая проблема, которую я обнаружил, заключается в том, что вы необходимо изменить масштаб выборки на 100. Для этого вы можете умножить свой возвращаемый ряд на 100 или установить параметр rescale=True
в функции arch_model
.
Зачем это нужно делать?
# Ibov
ret_ibov = returns['IBOV_1st']
model_ibov = arch_model(ret_ibov, vol='Garch', p=1, o=0, q=1, dist='Normal', rescale=True)
res_ibov = model_ibov.fit()
После подбора модели я прогнозирую дисперсию (всего 5 шагов, чтобы проиллюстрировать проблему), получить стандартное отклонение и сделать это в годовом исчислении. Obs: Поскольку мне пришлось изменить масштаб моего ряда возврата, я делю свой прогноз на 10000 (100 ** 2, из-за изменения масштаба)
# Forecast
forecast_ibov = res_ibov.forecast(horizon=5)
# Getting Annualized Standard Deviation
# Garch Vol
vol_ibov_for = (forecast_ibov.variance.iloc[-1]/10000)**0.5 * np.sqrt(252) * 100
# Observed Vol
vol_ibov = ret_ibov.std() * np.sqrt(252) * 100
И это результат прогноза
vol_ibov_for
h.1 24.563208
h.2 24.543245
h.3 24.523969
h.4 24.505357
h.5 24.487385
Что действительно близко к Observed Vol 23.76
Это результаты, которые я ожидал.
IRFM Возвращает
Когда я делаю точно такой же процесс менее изменчивый ряд Я получил действительно странный результат.
# IRFM
ret_irfm = returns['IRFM1M']
model_irfm = arch_model(ret_irfm, vol='Garch', p=1, o=0, q=1, dist='Normal', rescale=True)
res_irfm = model_irfm.fit()
# Forecast
forecasts_irfm = res_irfm.forecast(horizon=5)
# Getting Annualized Standard Deviation
# Garch Vol
vol_irfm_for = (forecasts_irfm.variance.iloc[-1]/10000)**0.5 * np.sqrt(252) * 100
# Observed Vol
vol_irfm = ret_irfm.std() * np.sqrt(252) * 100
Прогноз на выходе:
vol_irfm_for
h.1 47.879679
h.2 49.322351
h.3 50.519282
h.4 51.517356
h.5 52.352894
И это значительно отличается от наблюдаемой волатильности 5.39
Почему это происходит? Может быть из-за масштабирования? Должен ли я сделать еще одну корректировку до прогноза?
Спасибо