时间序列分析之GARCH模型介绍与应用
- 前言
- 一:ARCH模型的相关性质
- 二:ARCH实验过程
- 三:GARCH模型的轮廓介绍
- 四:GARCH实验过程
- 五:总结
前言
在ARIMA模型中,我们一般假设干扰项的方差为常数,然而在很多情况下,时序波动的干扰项方差并不为常数。因此我们有必要刻画方差(波动率)这一特征来研究时序模型,本篇的(G)ARCH模型就是刻画随时间变化的方差模型。
岁月如云,匪我思存,写作不易,望路
过的朋友们点赞收藏加关注哈,在此表示感谢!
一:ARCH模型的相关性质
- 底层由来
我们还是从模型入手:
,
我们定义模型为:残差
这
均值为0,方差为1的独立同分布随机变量序列, 。假设 有界,则在信息流 的作用下,有
由条件方差公式:
得其条件方差为:
从公式(1)容易看出,满足模型的序列的波动与其过去
- 期望、方差与协方差
对于白噪声 序列,在假定期条件与方差不变的情况下,根据条件期望的期望就是它本身的性质,我们有
,
。
- 参数估计过程
- 估计一个模型,首先要确定好模型的阶数,可以根据定阶模型。但对于波动率阶数 的确定,我们要先检验序列 存在显著的效应,再根据偏自相关函数来确定 ,
- 定好阶后,为了估计模型参数,当 服从正态分布时,我们可以用最小二乘最大似然估计对模型参数进行估计。
- 建模过程(由于此模型前期工作跟ARMA模型的建立很相似,所以有些步骤将简述)
- 首先还是对序列进行平稳性和白噪声检验,
- 检验ARCH效应。
a:我们对建立的AR§模型进行残差平方分析,对残差平方进行白噪声检验,如果过了白噪声检验,那就进行ARCH(q)偏自相关函数定阶,否则不存在ARCH效应;
b:还有一种是基于LM公式检验,公式为:
,检验的原假设为:序列 无效应,即 ,备择假设为:序列 存在效应,即至少存在一个 - 建立好模型后,我们将预测数据并进行模型检验。
二:ARCH实验过程
建模过程中,将沿用上一篇文章的数据,根据上一篇文章数据内容,我们得出的如下,选择模型。
图1
根据残差公式,我们做出残差图和残差平方图如下。
from statsmodels.graphics.tsaplots import plot_acf,plot_pacf
from statsmodels.tsa.stattools import adfuller as ADF
from statsmodels.tsa.arima_model import ARIMA,ARMA
import statsmodels.api as sm
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import arch
yv = np.array([2800,2811,2832,2850,2880,2910,2960,3023,3039,3056,3138,3150,3198,3100,3029,2950,2989,3012,3050,3142,3252,3342,3365,3385,3340,3410,3443,3428,3554,3615,3646,3614,3574,3635,3738,3764,3788,3820,3840,3875,3900,3942,4000,4021,4055])
yv_serie = pd.Series(yv[:-10])
def testwhitenoise(data):
m = 10# 检验10个自相关系数
acf,q,p = sm.tsa.acf(data,nlags=m,qstat=True)
out = np.c_[range(1,m+1),acf[1:],q,p]
output = pd.DataFrame(out,columns=['lag','自相关系数','统计量Q值','p_values'])
output = output.set_index('lag')# 设置第一列索引名称,可省略重复索引列1
print(output)
def teststeady(data,count=0):
res_ADF = ADF(data)
print('ADF检验结果为:', res_ADF)
Pv = res_ADF[1]
if Pv > 0.05:
print('\033[1;31mP值:%s,原始序列不平稳,要进行差分!\033[0m' % round(Pv,5))
count = count + 1
print('\033[1;32m进行了%s阶差分后的结果如下\033[0m' % count)
data = data.diff(1).dropna()
teststeady(data,count)
else:
print('\033[1;34mP值:%s,原始序列平稳,继续建模\033[0m'% round(Pv,5))
return data
tsres = teststeady(yv_serie)
def confirm_p(data):
fig = plt.figure(figsize=(10,6))
train = teststeady(data)
ax1 = fig.add_subplot(111)
fig = plot_pacf(train, lags=10, ax=ax1)
plt.show() ###可视化定阶
def testARCH(data):
order = (10,0)
tempmodel = ARMA(data, order).fit(disp=-1)
at = data - tempmodel.fittedvalues
at2 = np.power(at,2)##残差平方和
fig = plt.figure(figsize=(8,6))
plt.subplot(211)
plt.plot(at,label='at')
plt.legend()
plt.subplot(212)
plt.plot(at2,label='at^2')
plt.legend()
plt.show()
testwhitenoise(at2)
confirm_p(at2)
testARCH(tsres)
图2:残差即残差平方图
再对残差平方图进行白噪声检验如下,
图3
从图3中,我们发现残差平方图是白噪声序列,不满足效应,但是为了展示模型的建模过程,我们还是继续建模,最后跟模型做对比,接下来对进行定阶。
图4
从图4的图我们发现,确实也没有合适的阶数,如果强行建立模型,我们设阶数 试一试,那么实际模型为!
def make_ARCHmodel(data,pst,lag):
tempmodel = arch.arch_model(data,mean='AR',lags=lag,vol='ARCH',p=3,dist='gaussian').fit(update_freq=0,disp='off')
##预测值的均值;如果AR模型是10阶,起步位置必须是第9(从0起算)位置以上开始;horizon:从第start+1数据开始,预测未来horizon期数据
pre = tempmodel.forecast(horizon=pst,start=lag-1,method='simulation').mean.iloc[lag-1]
print(pre)
init_value = yv[lag]
fig = plt.figure(figsize=(8, 6))
predicthorizon = pre.cumsum() ##差分还原
predicthorizon = init_value + predicthorizon
prelsall = yv[:lag + 1] + list(predicthorizon)##差分少一个数据并补充
# 作图
plt.plot(prelsall, label='样本预测值')
plt.plot(yv, label='原始值')
plt.legend()
plt.show()
l = 10
presteps = len(yv) - l - 1
preres = make_ARCHmodel(tsres,presteps,l)
图5
从上图5我们发现,当数据确实不符合效应时,如果强行建模,那确实适得其反,跟模型的效果相比差的很远,从图也能发现,预测结果相当不可靠,所以我们理解好建模思路和用对模型都非常重要,不能因为模型复杂而不适合来进行强行建模。
下图是上一篇文章均值模型ARIMA的建模结果,为了方便比较,这里列出!
ARIMA建模结果!
三:GARCH模型的轮廓介绍
- 原理简介
我们知道模型的波动率 仅与白噪声序列 的滞后项有关,则认为时间序列每个时间点变量的波动率是最近 个时间点残差平方的线性组合,再与最近
其中
,
且假定 满足一定条件使得 的条件方差随时间变化是有限的。(特别说明这里的 p 跟AR模型里面的 p不是一个值,
- 模型说明
模型跟模型非常类似,都是对于波动率进行新的建模分析,所以在模型搭建前,也是有必要进行数据平稳性、白噪声和效应检验的。但在中,我们发现此波动率会涉及 值,还有模型的 值(虽然是两个 ,但含义不同),所以的定阶跟有点类似。但的定阶一般是比较困难的,所以一般都是选择低阶模型如,。
四:GARCH实验过程
我们还是基于相同的数据集,由于此数据集已经验证不符合效应,那我们强行建立模型看看预测效果。
def make_GARCHmodel(data,pst,lag):
tempmodel = arch.arch_model(data, mean='AR', lags=lag, vol='GARCH', p=2, dist='gaussian').fit(update_freq=0,
disp='off')
print(tempmodel.summary())
pre = tempmodel.forecast(horizon=pst, start=lag - 1, method='simulation').mean.iloc[lag - 1]
print(pre)
init_value = yv[lag]
fig = plt.figure(figsize=(8, 6))
predicthorizon = pre.cumsum() ##差分还原
predicthorizon = init_value + predicthorizon
prelsall = yv[:lag + 1] + list(predicthorizon) ##差分少一个数据并补充
# 作图
plt.plot(prelsall, label='样本预测值')
plt.plot(yv, label='原始值')
plt.legend()
plt.show()
l = 10
presteps = len(yv) - l - 1
preres = make_GARCHmodel(tsres,presteps,l)
注:更大的作用是对波动率的预测,比如从上面的波动率模型和均值模型我们知道,当计算出来 (真实值和预测值做差), 等等后,那么
图6
从上图6我们发现,模型效果还是不如均值模型效果好,所以在本身数据不符合效应下,我们还是选择模型进行建模。这正好能体现不同数据用不同方法建模的道理!
五:总结
- 和准确的来说属于波动率模型,比如图6计算过程,
- 当只有存在效应时,我们可以建立波动率模型,否则可以多使用均值模型。