時間序列平穩性檢驗方法,可分為三類:
-
圖形分析方法
-
簡單統計方法
-
假設檢驗方法
一、圖形分析方法
可視化數據
可視化數據即繪制時間序列的折線圖,看曲線是否圍繞某一數值上下波動(判斷均值是否穩定),看曲線上下波動幅度變化大不大(判斷方差是否穩定),看曲線不同時間段波動的頻率[~緊湊程度]變化大不大(判斷協方差是否穩定),以此來判斷時間序列是否是平穩的。
以下繪制幾張圖,大家來直觀判斷一下哪些是平穩的,哪些是非平穩的。
import numpy as np
import pandas as pd
import akshare as ak
from matplotlib import pyplot as pltnp.random.seed(123)# -------------- 準備數據 --------------
# 白噪聲
white_noise = np.random.standard_normal(size=1000)# 隨機游走
x = np.random.standard_normal(size=1000)
random_walk = np.cumsum(x)# GDP
df = ak.macro_china_gdp()
df = df.set_index('季度')
df.index = pd.to_datetime(df.index)
gdp = df['國內生產總值-絕對值'][::-1].astype('float')# GDP DIFF
gdp_diff = gdp.diff(4).dropna()# -------------- 繪制圖形 --------------
fig, ax = plt.subplots(2, 2)ax[0][0].plot(white_noise)
ax[0][0].set_title('white_noise')
ax[0][1].plot(random_walk)
ax[0][1].set_title('random_walk')ax[1][0].plot(gdp)
ax[1][0].set_title('gdp')
ax[1][1].plot(gdp_diff)
ax[1][1].set_title('gdp_diff')plt.show()
?a. 白噪聲,曲線圍繞0值上下波動,波動幅度前后、上下一致,為平穩序列。
b. 隨機游走,曲線無確定趨勢,均值、方差波動較大,非平穩序列。
c. GDP數據趨勢上升,均值隨時間增加,非平穩序列。
d. GDP季節差分后數據,曲線大致在一條水平線上上下波動,波動幅度前后變化較小,可認為是平穩的。
可視化統計特征
可視化統計特征,是指繪制時間序列的自相關圖和偏自相關圖,根據自相關圖的表現來判斷序列是否平穩。
自相關,也叫序列相關,是一個信號與自身不同時間點的相關度,或者說與自身的延遲拷貝--或滯后--的相關性,是延遲的函數。不同滯后期得到的自相關系數,叫自相關圖。
(這里有一個默認假設,即序列是平穩的,平穩序列的自相關性只和時間間隔k有關,不隨時間t的變化而變化,因而可以稱自相關函數是延遲(k)的函數)
平穩序列通常具有短期相關性,對于平穩的時間序列,自相關系數往往會迅速退化到零(滯后期越短相關性越高,滯后期為0時,相關性為1);而對于非平穩的數據,退化會發生得更慢,或存在先減后增或者周期性的波動等變動。
import statsmodels.api as sm
X = [2,3,4,3,8,7]
print(sm.tsa.stattools.acf(X, nlags=1, adjusted=True))
> [1, 0.3559322]
其中第一個元素為滯后期為0時的自相關性,第二個元素為滯后期為1時的自相關性
根據ACF求出滯后k自相關系數時,實際上得到并不是X(t)與X(t-k)之間單純的相關關系。
因為X(t)同時還會受到中間k-1個隨機變量X(t-1)、X(t-2)、……、X(t-k+1)的影響,而這k-1個隨機變量又都和X(t-k)具有相關關系,所以自相關系數里面實際摻雜了其他變量對X(t)與X(t-k)的影響。
在剔除了中間k-1個隨機變量X(t-1)、X(t-2)、……、X(t-k+1)的干擾之后,X(t-k)對X(t)影響的相關程度,叫偏自相關系數。不同滯后期得到的偏自相關系數,叫偏自相關圖。(偏自相關系數計算較復雜,后期再來具體介紹)
?下面我們就來看看幾個實戰案例(上圖中的數據再來看一下它們的自相關圖和偏自相關圖):
# 數據生成過程在第一個代碼塊中
from statsmodels.graphics.tsaplots import plot_acf, plot_pacffig, ax = plt.subplots(4, 2)
fig.subplots_adjust(hspace=0.5)plot_acf(white_noise, ax=ax[0][0])
ax[0][0].set_title('ACF(white_noise)')
plot_pacf(white_noise, ax=ax[0][1])
ax[0][1].set_title('PACF(white_noise)')plot_acf(random_walk, ax=ax[1][0])
ax[1][0].set_title('ACF(random_walk)')
plot_pacf(random_walk, ax=ax[1][1])
ax[1][1].set_title('PACF(random_walk)')plot_acf(gdp, ax=ax[2][0])
ax[2][0].set_title('ACF(gdp)')
plot_pacf(gdp, ax=ax[2][1])
ax[2][1].set_title('PACF(gdp)')plot_acf(gdp_diff, ax=ax[3][0])
ax[3][0].set_title('ACF(gdp_diff)')
plot_pacf(gdp_diff, ax=ax[3][1])
ax[3][1].set_title('PACF(gdp_diff)')plt.show()
?
?(1) 白噪聲的自相關系數很快就衰減到0附近,是明顯的平穩序列。滯后期為0時自相關系數和偏自相關系數其實就是序列自己和自己的相關性,故為1;滯后期為1時,自相關系數為0,表示白噪聲無自相關性。
(2) 隨機游走,自相關系數下降非常緩慢,故為非平穩序列;另從偏自相關系數中可以看到隨機游走只和前一項有關。
(3) GDP數據的自相關圖中也可以看到存在一定的周期性,滯后4、8、12等自相關系數較大下降較慢,差分后下降多一些起到一定效果,認為差分后序列是平穩的。同可視化數據一樣,直觀判斷帶有較強主觀性,但能讓我們對數據有更直觀的認識。
二、簡單統計方法
計算統計量的方法只是作為一個補充,了解即可。寬平穩中有兩個條件是均值不變和方差不變,可視化數據中我們可以直觀看出來,其實還可以具體計算一下看看。
很有意思的邏輯,直接將序列前后拆分成2個序列,分別計算這2個序列的均值、方差,對比看是否差異明顯。(其實很多時序異常檢驗也是基于這種思想,前后分布一致則無異常,否則存在異常或突變)
我們來算白噪聲和隨機游走序列不同時間段的均值、方差:
import numpy as npnp.random.seed(123)white_noise = np.random.standard_normal(size=1000)x = np.random.standard_normal(size=1000)
random_walk = np.cumsum(x)def describe(X):split = int(len(X) / 2)X1, X2 = X[0:split], X[split:]mean1, mean2 = X1.mean(), X2.mean()var1, var2 = X1.var(), X2.var()print('mean1=%f, mean2=%f' % (mean1, mean2))print('variance1=%f, variance2=%f' % (var1, var2))print('white noise sample')
describe(white_noise)print('random walk sample')
describe(random_walk)
white noise sample:
mean1=-0.038644, mean2=-0.040484
variance1=1.006416, variance2=0.996734
random walk sample:
mean1=5.506570, mean2=8.490356
variance1=53.911003, variance2=126.866920
白噪聲序列均值和方差略有不同,但大致在同一水平線上;
隨機游走序列的均值和方差差異就比較大,因此為非平穩序列。
三、假設檢驗方法
平穩性的假設檢驗方法當前主流為單位根檢驗,檢驗序列中是否存在單位根,若存在,則為非平穩序列,不存在則為平穩序列。
在介紹檢驗方法之前,有必要了解一些相關補充知識,這樣對后面的檢驗方法理解上就會更清晰一些。
什么是單位根
import numpy as np
from matplotlib import pyplot as pltnp.random.seed(123)def simulate(beta):y = np.random.standard_normal(size=1000)for i in range(1, len(y)):y[i] = beta * y[i - 1] + y[i]return yplt.figure(figsize=(20, 4))
for i, beta in enumerate([0.9, 1.0, 1.1]):plt.subplot(1, 3, i+1)plt.plot(simulate(beta))plt.title('beta: {}'.format(beta))
plt.show()
?????????????????????????????????????????????????????????????????????????檢驗方法
DF檢驗
ADF檢驗(Augmented Dickey-Fuller Testing)是最常用的單位根檢驗方法之一,通過檢驗序列是否存在單位根來判斷序列是否是平穩的。ADF檢驗是DF檢驗的增強版,在介紹ADF之前,我們先來看一下DF檢驗。
迪基(Dickey)和弗勒(Fuller)1979年基于非平穩序列的基本特征將其大致歸為三類并提出DF檢驗:
(1) 當序列基本走勢呈現無規則上升或下降并反復時,將其歸為無漂移項自回歸過程;
(2) 當序列基本走勢呈現明顯的隨時間遞增或遞減且趨勢并不太陡峭時,將其歸為帶漂移項自回歸過程;
(3) 當序列基本走勢隨時間快速遞增時,則將其歸為帶趨勢項回歸過程。
若檢驗統計量大于臨界值(p值大于顯著性水平?),不能拒絕原假設,序列是非平穩的;
若檢驗統計量小于臨界值(p值小于顯著性水平?),拒絕原假設,認為序列是平穩的。
ADF檢驗
DF的檢驗公式為一階自回歸過程,為了能適用于高階自回歸過程的平穩性檢驗,迪基等1984年對DF檢驗進行了一定的修正,引入了更高階的滯后項,ADF的檢驗回歸式修正為:
?
import numpy as np
from matplotlib import pyplot as pltnp.random.seed(123)y = np.random.standard_normal(size=100)
for i in range(1, len(y)):y[i] = 1 + 0.1*i + y[i]plt.figure(figsize=(12, 6))
plt.plot(y)
plt.show()
?檢驗是否平穩:
from arch.unitroot import ADF
adf = ADF(y)
# print(adf.pvalue)
print(adf.summary().as_text())adf = ADF(y)
adf.trend = 'ct'
print(adf.summary().as_text())
?說明:
arch包中ADF檢驗可指定trend為
'n'(不含截距項和時間趨勢項)
'c'(含截距項)
'ct'(含截距項和時間趨勢項)
'ctt'(含截距項和時間趨勢項和二次型時間趨勢項)
分別對應不同平穩類型的檢驗。(滯后期lags默認為AIC最小)
以上第一個文本輸出中,不指定trend默認為檢驗是否含截距項平穩,顯著性水平p=0.836>0.05,不拒絕原假設,非平穩;
以上第二個文本輸出中,指定trend為檢驗是否含截距項和時間趨勢項平穩,顯著性水平p=0.000<0.05,拒絕原假設,故為趨勢項平穩。
我們再來看看GDP季節差分前后數據是否為平穩的:
# 數據在第一個代碼塊中
from arch.unitroot import ADF
adf = ADF(gdp)
print(adf.summary().as_text())adf = ADF(gdp_diff)
print(adf.summary().as_text())
?可以看到差分前p值為0.998>0.05,不能拒絕原假設,數據非平穩;差分后p值為0.003<0.05,故在5%的顯著性水平下可拒絕原假設,差分后的數據是平穩的。
# 數據在第一個代碼塊中
from arch.unitroot import ADF
adf = ADF(gdp)
adf.trend = 'ct'
print(adf.summary().as_text())
?指定檢驗平穩類型為含截距項和時間趨勢項平穩,p值為0.693>0.05,同樣不能拒絕原假設,故差分前亦非趨勢平穩。
PP檢驗
Phillips和Perron(1988) 提出一種非參數檢驗方法,主要是為了解決殘差項中潛在的序列相關和異方差問題,其檢驗統計量的漸進分布和臨界值與 ADF檢驗相同。同樣出現較早,假設條件一樣,用法相似,可作為ADF檢驗的補充。
同樣構造一個趨勢平穩序列,看下PP檢驗結果:
import numpy as np
from arch.unitroot import PhillipsPerronnp.random.seed(123)y = np.random.standard_normal(size=100)
for i in range(1, len(y)):y[i] = 1 + 0.1*i + y[i]pp = PhillipsPerron(y)
print(pp.summary().as_text())pp = PhillipsPerron(y)
pp.trend = 'ct'
print(pp.summary().as_text())
?不指定trend為默認檢驗是否為帶截距項的平穩過程,檢驗結果p值為0.055>0.05,對應檢驗統計量為-2.825大于5%顯著性水平下的臨界值-2.89,所以5%顯著性水平下不拒絕原假設,為非平穩序列;但是檢驗統計量小于10%顯著性水平下的臨界值-2.58,故在10%的顯著性水平下可拒絕原假設,認為是平穩序列。
指定trend=‘ct’為檢驗是否為帶截距項和時間趨勢項的平穩過程,檢驗結果p值為0.000<0.05,故為趨勢平穩;其實檢驗統計量為-10.009小于1%顯著性水平下的臨界值-4.05,所以即便在1%顯著性水平下也是平穩的。
基于以上檢驗結果,可以判定序列是趨勢平穩的。
DF-GLS檢驗
DF-GLS檢驗,是Elliott, Rothenberg, and ?Stock 1996年提出的一種單位根檢驗方法,全稱Dickey-Fuller Test with GLS Detredding,即“使用廣義最小二乘法去除趨勢的檢驗”,是目前最有功效的單位根檢驗。
DF-GLS檢驗利用廣義最小二乘法,首先對要檢驗的數據進行一次“準差分”,然后利用準差分的數據對原序列進行去除趨勢處理,再利用ADF檢驗的模型形式對去除趨勢后的數據進行單位根檢驗,但此時ADF檢驗模型中不再包含常數項或者時間趨勢變量。
同樣構造一個趨勢平穩序列看下檢驗效果:
import numpy as np
from arch.unitroot import DFGLSnp.random.seed(123)y = np.random.standard_normal(size=100)
for i in range(1, len(y)):y[i] = 1 + 0.1*i + y[i]dfgls = DFGLS(y)
print(dfgls.summary().as_text())dfgls = DFGLS(y)
dfgls.trend = 'ct'
print(dfgls.summary().as_text())
?
?不指定trend情況下不能拒絕原假設,非平穩;指定trend='ct'時p值小于0.05,拒絕原假設,帶截距項和時間趨勢平穩。
再來構造一個含單位根的非平穩序列看一下檢驗結果:
import numpy as np
from arch.unitroot import DFGLSnp.random.seed(123)y = np.random.standard_normal(size=100)
for i in range(1, len(y)):y[i] = 0.1 + y[i-1] + y[i]dfgls = DFGLS(y)
print(dfgls.summary().as_text())dfgls = DFGLS(y)
dfgls.trend = 'ct'
print(dfgls.summary().as_text())
?p值一個為0.645,一個為0.347,均大于0.05/0.1。指不指定檢驗類型,均未能通過檢驗,故該序列為非平穩序列。(DF-GLS檢驗trend只能指定為'c'或者'ct')
KPSS檢驗
另一個著名的單位根存在的檢驗是Kwiatkowski, Phillips, and Shin 1992年提出的KPSS檢驗。與以上三種檢驗方法相比,最大的不同點就是它的原假設是平穩序列或趨勢平穩序列,而備擇假設是存在單位根。
-
原假設:序列不存在單位根(時間序列是平穩的或趨勢平穩的)
-
備擇假設:序列存在單位根(時間序列是非平穩的)
-
import numpy as np from arch.unitroot import KPSSnp.random.seed(123)y = np.random.standard_normal(size=100) for i in range(1, len(y)):y[i] = 0.1 + y[i-1] + y[i]kpss = KPSS(y) print(kpss.summary().as_text())kpss = KPSS(y) kpss.trend = 'ct' print(kpss.summary().as_text())
?注意KPSS檢驗中原假設為不存在單位根。默認檢驗趨勢類型下p值為0.000,拒絕原假設,存在單位根,序列非平穩。指定trend='ct'后,p值0.115>0.05,不拒絕原假設,認為序列趨勢平穩,檢驗錯誤。以上幾種檢驗中均不能100%保證檢驗正確,PP檢驗可認為是ADF檢驗的補充,KPSS檢驗同樣也可和其他檢驗一同使用,當均認為是平穩或趨勢平穩時方判定為平穩。
除以上檢驗方法外,還有Zivot-Andrews檢驗、Variance Ratio檢驗等檢驗方法。
以上代碼實現中使用的是Python中的arch包,另外還有一個常用的包statsmodels中也實現了單位根檢驗方法,結果是一樣的。
鄭重感謝Python數據科學
本人接下來進行金融統計,需要轉向python,需要教程,此公眾號對我用處極大。?