Python玩轉金融時間序列之ARCH與GARCH模型

01 引言

作為金融時間序列的專題推文,

【手把手教你】時間序列之日期處理主要介紹了使用Python處理時間序列的日期和統計分析;【Python量化基礎】時間序列的自相關性與平穩性主要介紹了時間序列的一些基礎概念,包括自相關性、偏自相關性、白噪聲和平穩性;而【手把手教你】使用Python玩轉金融時間序列模型主要介紹了AR、MA、ARMA和ARIMA模型的基本原理與Python的實現。從上一篇推文不難看出,使用ARMA等模型對股票收益率的時間序列建模效果不是很理想,主要在於忽略了時間序列的異方差和波動聚集特性。所謂波動性聚集,是指金融時間序列的波動具有大波動接著大波動,小波動接著小波動的特徵,即波峰和波谷具有連續性。ARCH和GARCH模型正是基於條件異方差和波動聚集的特性建模的。本次推文著重介紹 ARCH和GARCH模型的基本原理及其Python實現。

02 股票收益率時間序列特點

在介紹ARCH和GARCH模型之前,我們先來看看金融資產收益率的時間序列有哪些比較突出的特點。仍然以滬深300指數為例,考察其收益率時間的分佈和統計特性。下面的Python代碼與上一篇推文類似,包括導入需要用到的庫、定義畫圖函數和使用tushare獲取數據等。

import pandas as pd
import numpy as np
import statsmodels.tsa.api as smt
#tsa為Time Series analysis縮寫
import statsmodels.api as sm
import scipy.stats as scs
from arch import arch_model
#畫圖
import matplotlib.pyplot as plt
import matplotlib as mpl
%matplotlib inline
#正常顯示畫圖時出現的中文和負號
from pylab import mpl
mpl.rcParams['font.sans-serif']=['SimHei']
mpl.rcParams['axes.unicode_minus']=False
def ts_plot(data, lags=None,title=''):
if not isinstance(data, pd.Series):
data = pd.Series(data)
#matplotlib官方提供了五種不同的圖形風格,
#包括bmh、ggplot、dark_background、
#fivethirtyeight和grayscale
with plt.style.context('ggplot'):
fig = plt.figure(figsize=(10, 8))
layout = (3, 2)
ts_ax = plt.subplot2grid(layout, (0, 0))
acf_ax = plt.subplot2grid(layout, (1, 0))
pacf_ax = plt.subplot2grid(layout, (1, 1))
qq_ax = plt.subplot2grid(layout, (2, 0))
pp_ax = plt.subplot2grid(layout, (2, 1))
data.plot(ax=ts_ax)
ts_ax.set_title(title+'時序圖')
smt.graphics.plot_acf(data, lags=lags,
ax=acf_ax, alpha=0.5)
acf_ax.set_title('自相關係數')
smt.graphics.plot_pacf(data, lags=lags,
ax=pacf_ax, alpha=0.5)
pacf_ax.set_title('偏自相關係數')
sm.qqplot(data, line='s', ax=qq_ax)
qq_ax.set_title('QQ 圖')
scs.probplot(data, sparams=(data.mean(),
data.std()), plot=pp_ax)
pp_ax.set_title('PP 圖')
plt.tight_layout()
return

使用tushare獲取滬深300交易數據

import tushare as ts
token='輸入你的token'
pro=ts.pro_api(token)
df=pro.index_daily(ts_code='000300.SH')
df.index=pd.to_datetime(df.trade_date)
del df.index.name
df=df.sort_index()
df['ret']=np.log(df.close/df.close.shift(1))
#df.head()
ts_plot(df.ret.dropna(),lags=30,title='滬深300收益率')
Python玩轉金融時間序列之ARCH與GARCH模型

從上圖可以看出,滬深300指數收益率時間序列呈現出以下幾個現象,具有一定的普遍性。

  • 自相關性比較弱,但對其進行變換後,如取平方、絕對值等,則表現出很強的自相關性(見後文);
  • 收益率的條件方差(Conditional Variance)隨著時間而變化,即存在條件異方差的特徵。
  • 收益率序列的波動具有持續性,即存在波動集聚(Volatility Clustering)的現象。比如2007-2008、2015-2016、2019具有較大的波動性。
  • QQ圖顯示,收益率並不服從正態分佈,極端值較多,具有厚尾的現象。

03 ARCH模型

ARCH模型全稱是自迴歸條件異方差模型,Autoregressive Conditionally Heteroskedastic Models - ARCH(p),是Engle在1982年分析英國通貨膨脹率時提出的模型,主要用於刻畫波動率的統計特徵。

一般先假設收益率序列滿足某個經典時間序列模型(MA、AR或ARMA),以AR(1)模型為例:

Python玩轉金融時間序列之ARCH與GARCH模型

收益率yt的波動率(條件方差)可以使用殘差項的波動率進行刻畫:

Python玩轉金融時間序列之ARCH與GARCH模型

為了刻畫資產收益率的這種波動特性,可以令殘差項的條件方差與過去殘差項的平方相關。因此,ARCH(p)模型可以表示為:

Python玩轉金融時間序列之ARCH與GARCH模型

其中,w是均值為0,方差為1的獨立同分布時間序列,

Python玩轉金融時間序列之ARCH與GARCH模型

,且滿足一定條件使得的無條件方差有限。ARCH(p)模型能夠很好地刻畫金融資產收益率序列的波動特性和厚尾現象,但是其本身並不能用來解釋金融資產收益率為何有這樣的特徵。關於ARCH模型的估計此處不詳細展開,感興趣的可以參見Ruey S. Tray的《金融時間序列分析》和計量經濟學教材。下面簡要介紹ARCH模型的建模步驟:

(1)檢驗收益率序列是否平穩,根據自相關性建立合適的均值方程,如ARMA模型,描述收益率如何隨時間變化,根據擬合的模型和實際值,得到殘差序列。

(2)對擬合的均值方程得到的殘差序列進行ARCH效應檢驗,即檢驗收益率圍繞均值的偏差是否時大時小。檢驗序列是否具有ARCH效應的方法有兩種:Ljung-Box檢驗和LM檢驗。

(3)若ARCH效應在統計上顯著,則需要再設定一個波動率模型來刻畫波動率的動態變化。

(4)對均值方差和波動率方差進行聯合估計,即假設實際數據服從前面設定的均值方差和波動率方差後,對均值方差和波動率方差中的參數進行估計,並得到估計的誤差。

(5)對擬合的模型進行檢驗。如果估計結果(殘差項)不滿足模型本身的假設,則模型的可用性較差。

下面使用Python模擬ARCH模型並對滬深300收益率的ARCH效應進行統計檢驗。

# 模擬ARCH時間序列
np.random.seed(2)
a0 = 2
a1 = .5
y = w = np.random.normal(size=1000)
Y = np.empty_like(y)
for t in range(1,len(y)):
Y[t] = w[t] * np.sqrt((a0 + a1*y[t-1]**2))
ts_plot(Y, lags=30,title='模擬ARCH')
Python玩轉金融時間序列之ARCH與GARCH模型

def ret_plot(ts, title=''):
ts1=ts**2
ts2=np.abs(ts)
with plt.style.context('ggplot'):

fig = plt.figure(figsize=(12, 6))
layout = (2, 1)
ts1_ax = plt.subplot2grid(layout, (0, 0), colspan=2)
ts2_ax = plt.subplot2grid(layout, (1, 0))
ts1.plot(ax=ts1_ax)
ts1_ax.set_title(title+'日收益率平方')
ts2.plot(ax=ts2_ax)
ts2_ax.set_title(title+'日收益率絕對值')
plt.tight_layout()
return
ret_plot(df.ret.dropna(), title='滬深300')
Python玩轉金融時間序列之ARCH與GARCH模型

從滬深300的日收益平方和絕對值走勢圖可以看出,存在較明顯的波動聚集的現象,初步可以判斷出滬深300日收益序列存在ARCH效應。下面使用Ljung-Box統計量對收益率平方的自相關性進行統計檢驗。計算Q統計量和LB統計量都是用python中statsmodels模塊acorr_ljungbox方法. 默認情況下, acorr_ljungbox只計算LB統計量, 只有當參數boxpierce=True時, 才會輸出Q統計量。由LB白噪聲檢驗可以看出,Q統計量的p值都在0.05以下, 表明原假設成立的概率極小, 可以拒絕滬深300收益率的平方是白噪音序列的原假設,說明原序列(滬深300收益率)存在ARCH效應。

def whitenoise_test(ts):
'''計算box pierce 和 box ljung統計量'''
from statsmodels.stats.diagnostic import acorr_ljungbox
q,p=acorr_ljungbox(ts)
with plt.style.context('ggplot'):
fig = plt.figure(figsize=(10, 4))
axes = fig.subplots(1,2)
axes[0].plot(q, label='Q統計量')
axes[0].set_ylabel('Q')
axes[1].plot(p, label='p值')
axes[1].set_ylabel('P')
axes[0].legend()
axes[1].legend()
plt.tight_layout()
return
ret=df.ret.dropna()
whitenoise_test(ret**2)
Python玩轉金融時間序列之ARCH與GARCH模型

04 GARCH模型

GARCH模型是Bollerslev在1986年提出來的,全稱為廣義自迴歸條件異方差模型,Generalized Autoregressive Conditionally Heteroskedastic Models - GARCH(p,q),是ARCH模型的擴展。GARCH模型認為時間序列每個時間點變量的波動率是最近p個時間點殘差平方的線性組合,與最近q個時間點變量波動率的線性組合加起來得到。即GARCH模型的條件方差不僅是滯後殘差平方的線性函數,還是滯後條件方差的線性函數,因而GARCH模型適合在計算量不大時,方便地描述高階的ARCH過程,具有更大的適用性。

Python玩轉金融時間序列之ARCH與GARCH模型

其中,

Python玩轉金融時間序列之ARCH與GARCH模型

為白噪音,

Python玩轉金融時間序列之ARCH與GARCH模型

,否則模型將是非平穩的。GARCH模型的估計與ARCH模型類似,具體推導過程參見計量經濟學相關書籍。在實際應用中,GARCH(1,1)和GARCH(2,1)一般可以滿足對自迴歸條件異方差的描述。下面使用Python對GARCH(1,1)模型進行模擬和估計。

Python中的ARCH包

先來看下arch包中arch_model函數各參數的含義以及模型設定方法。

arch.arch_model(y, x=None, mean='Constant', lags=0, vol='Garch', p=1, o=0, q=1, power=2.0, dist='Normal', hold_back=None)

各參數含義:

y : 因變量。

x : 外生變量,如果沒有外生變量則模型自動省略。

mean: 均值模型的名稱,可選: ‘Constant’, ‘Zero’, ‘ARX’ 以及 ‘HARX’。

lags:滯後階數。

vol :波動率模型,可選: ‘GARCH’ (默認), ‘ARCH’, ‘EGARCH’, ‘FIARCH’ 以及 ‘HARCH’。

p :– 對稱隨機數的滯後階,即扣除均值後的部分。

o :非對稱數據的滯後階。

q :波動率或對應變量的滯後階。

power:使用GARCH或相關模型的精度。

dist:誤差分佈,可選:正態分佈: ‘normal’, ‘gaussian’ (default);學生T分佈: ‘t’, ‘studentst’;偏態學生T分佈: ‘skewstudent’, ‘skewt’;通用誤差分佈: ‘ged’, ‘generalized error”。

hold_back:對同一樣本使用不同的滯後階來比較模型時使用該參數。

# 模擬GARCH(1, 1) 過程
np.random.seed(1)
a0 = 0.2
a1 = 0.5
b1 = 0.3
n = 10000
w = np.random.normal(size=n)
garch = np.zeros_like(w)
sigsq = np.zeros_like(w)
for i in range(1, n):
sigsq[i] = a0 + a1*(garch[i-1]**2) + b1*sigsq[i-1]
garch[i] = w[i] * np.sqrt(sigsq[i])
_ = ts_plot(garch, lags=30,title='模擬GARCH')
Python玩轉金融時間序列之ARCH與GARCH模型

#update_freq=0表示不輸出中間結果,只輸出最終結果

# 使用模擬的數據進行 GARCH(1, 1) 模型擬合
#arch_model默認建立GARCH(1,1)模型
am = arch_model(garch)
res = am.fit(update_freq=0)
print(res.summary())
Python玩轉金融時間序列之ARCH與GARCH模型

#擬合滬深300收益率數據
Y=ret*100.0
am = arch_model(Y,p=1, o=1, q=1, dist='StudentsT')
res = am.fit(update_freq=0)
#update_freq=0表示不輸出中間結果,只輸出最終結果

print(res.summary())
Python玩轉金融時間序列之ARCH與GARCH模型

res.resid.plot(figsize=(12,5))
plt.title('滬深300收益率擬合GARCH(1,1)殘差',size=15)
plt.show()
res.conditional_volatility.plot(figsize=(12,5),color='r')
plt.title('滬深300收益率條件方差',size=15)
plt.show()
Python玩轉金融時間序列之ARCH與GARCH模型

Python玩轉金融時間序列之ARCH與GARCH模型

05 結語

本文簡要介紹了ARCH和GARCH模型的基本原理和Python實現,關於其應用還有待進一步拓展和挖掘。ARCH和GARCH模型能夠較好的刻畫金融資產收益率的波動性聚集和厚尾現象,因此在量化投資上的應用主要表現在波動率的估計上,尤其是金融工程(期權波動率)和風險管理(VaR模型)的應用上。同時,我們也注意到,ARCH和GARCH模型在應用中也存在一定的侷限性和不足:首先,模型假定波動是對稱的,即過去的波動對現在條件方差的影響是相同的,但學術上的實證結果卻表明,當壞(好)消息發佈時,股票收益率的波動會增加(減小);其次,模型對參數的限制條件較強,尤其是高階模型,參數需要滿足的約束非常複雜。最後,模型並沒有提供關於波動率變化的更進一步解釋,而僅僅是擬合波動率變化的統計行為。針對現有模型的不足,學者們在GARCH模型的基礎上又提出了一系列模型,簡稱GARCH模型族,包括IGARCH、TGARCH、EGARCH等,更復雜的還有BEKK-GARCH、Coupla-GARCH等模型。當然,模型並非越複雜越好,特別地,學術上用到的複雜模型,在現實的量化投資中能用到的往往很少。

  1. Analysis of Financial Time Series(中文版《金融時間序列分析》第3版),作者:Ruey S. Tsay.
  2. statsmodels官方文檔。
  3. Time Series Analysis (TSA) in Python - Linear Models to GARCH.
  4. 蔡立耑.《量化投資以Python為工具》.電子工業出版社.2017.

關於Python金融量化

專注於分享Python在金融量化領域的應用。加入知識星球,可以免費獲取量化投資視頻資料、量化金融相關PDF資料、公眾號文章Python完整源碼、量化投資前沿分析框架,與博主直接交流、結識圈內朋友等。

Python玩轉金融時間序列之ARCH與GARCH模型

掃描關注Python金融量化,獲取更多幹貨


分享到:


相關文章: