Descargo de responsabilidad: Publicado esto en stackoverflow pero quizás este sea el lugar adecuado para preguntar algo sobre GARCH
Estoy probando el paquete ARCH para pronosticar la varianza (desviación estándar) de dos series utilizando GARCH(1,1).
Esta es la primera parte de mi código
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)
Vuelve Ibovespa
La primera serie es el 1er Contrato Futuro del Índice Ibovespa, tiene una volatilidad observada anualizada muy cercana a la Previsión Garch.
El primer problema que he encontrado es que necesitas reescalar tu muestra por 100. Para ello, puede multiplicar su serie de retorno por 100 o establecer el parámetro rescale=True
en el arch_model
función.
¿Por qué es necesario hacer esto?
# 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()
Después de ajustar el modelo, pronostico la Varianza (sólo 5 pasos para ilustrar el problema), obtengo la Desviación Estándar y la anualizo. Obs: Como tuve que reescalar mi serie de retornos, divido mi pronóstico por 10000 (100**2, debido a la reescalada)
# 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
Y ese es el resultado de la previsión
vol_ibov_for
h.1 24.563208
h.2 24.543245
h.3 24.523969
h.4 24.505357
h.5 24.487385
Que está muy cerca del Vol. Observado 23.76
Este es un resultado que estaba esperando.
Retornos del IRFM
Al hacer exactamente el mismo proceso una serie menos volátil, obtuve un resultado realmente extraño.
# 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
Previsión de resultados:
vol_irfm_for
h.1 47.879679
h.2 49.322351
h.3 50.519282
h.4 51.517356
h.5 52.352894
Y esto es significativamente diferente de la Volatilidad Observada 5.39
¿Por qué ocurre esto? ¿Tal vez por el cambio de escala? ¿Tengo que hacer otro ajuste antes de la previsión?
Gracias