简体   繁体   English

在 Python 中使用 GARCH 预测波动率 - Arch 包

[英]Forecasting Volatility using GARCH in Python - Arch Package

I'm testing ARCH package to forecast the Variance (Standard Deviation) of two series using GARCH(1,1).我正在测试 ARCH 包以使用 GARCH(1,1) 预测两个系列的方差(标准偏差)。

This is the first part of my code这是我的代码的第一部分

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 Ibovespa 返回

The first series is the 1st Future Contract of Ibovespa Index, has an observed annualized volatility really close to the Garch Forecast.第一个系列是 Ibovespa 指数的第一个期货合约,观察到的年化波动率非常接近 Garch 预测。

The first problem that I've found is that you need to rescale your sample by 100. To do this, you can multiply your return series by 100 or setting the parameter rescale=True in the arch_model function.我发现的第一个问题是您需要将样本重新缩放 100。为此,您可以将返回序列乘以 100 或在arch_model函数中设置参数arch_model rescale=True

Why is necessary to do this?为什么有必要这样做?

# 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()

After fitting the model I forecast the Variance (just 5 steps to illustrate the problem), get the Standard Deviation and annualize it.拟合模型后,我预测了方差(只需 5 个步骤来说明问题),得到标准差并将其年化。 Obs: Since I had to rescale my return series, I divide my forecast by 10000 (100**2, because of rescale) 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

And that's the forecast output这就是预测输出

vol_ibov_for
h.1    24.563208
h.2    24.543245
h.3    24.523969
h.4    24.505357
h.5    24.487385

Which is really close to Observed Vol 23.76这与 Observed Vol 23.76非常接近

This is a results that I was expecting.这是我期待的结果。

IRFM Returns IRFM 回报

When I do exactly the same process a less volatile series, I got a really weird result.当我对一个不那么不稳定的系列做完全相同的过程时,我得到了一个非常奇怪的结果。

# 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

Forecast output:预测输出:

vol_irfm_for
h.1    47.879679
h.2    49.322351
h.3    50.519282
h.4    51.517356
h.5    52.352894

And this is significantly different from the Observed Volatility 5.39这与观察到的波动率5.39明显不同

Why is this happening?为什么会这样? Maybe because of the rescaling?也许是因为重新缩放? Do I have to do another adjust before the forecast?在预测之前我是否必须再做一次调整?

Thanks谢谢

Found the answer.找到了答案。

The rescale=True is used when the model fails to converge to a result.当模型未能收敛到结果时使用rescale=True So rescale could be a solution for the problem.因此,重新缩放可能是该问题的解决方案。 If the model doesn't need rescale, even if the parameter is True , it will not do anything.如果模型不需要重新缩放,即使参数为True ,它也不会做任何事情。

Point of Attempion : If the rescale=True and, in fact, rescaled the series.尝试点:如果rescale rescale=True并且实际上重新调整了系列。 It's necessary to adjust the outputs.有必要调整输出。 In my question I was confused about how high my volatility was.在我的问题中,我对我的波动性有多高感到困惑。 That's because I was assuming that my rescale values was 100, which not necessarily is true.那是因为我假设我的重新调整值为 100,这不一定是真的。

The correct thing to do is to set the parameter as True and get the rescale value after that.正确的做法是将参数设置为 True 并在此之后获取重新缩放值。

To do this, just need to insert the following code:为此,只需要插入以下代码:

# IRFM
ret_irfm = returns['IRFM1M']
model_irfm = arch_model(ret_irfm, vol='Garch', p=1, o=0, q=1, dist='Normal', rescale=True, mean='Zero')
res_irfm = model_irfm.fit()
scale = res_irfm.scale  # New part of the code

# Forecast
forecasts_irfm = res_irfm.forecast(horizon=5)

# Getting Annualized Standard Deviation
# Garch Vol
# New part of the code: Divide variance by scale^2
vol_irfm_for = (forecasts_irfm.variance.iloc[-1] / np.power(scale, 2))**0.5 * np.sqrt(252) * 100 
# Observed Vol
vol_irfm = ret_irfm.std() * np.sqrt(252) * 100

Hope this help another users with the same problem.希望这可以帮助其他有同样问题的用户。 It's a really simple thing.这真的是一件很简单的事情。

Thanks.谢谢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM