Python数据分析-时间序列分析(一) 平稳性检验和白噪声检验


导入包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
import statsmodels.api as sm

plt.rcParams['font.sans-serif'] = ['Times New Roman']
plt.rcParams['axes.unicode_minus'] = False

问题分析

  • No module named 'seaborn': 安装依赖包 !pip install seaborn
  • No module named 'statsmodels': 安装依赖包 !pip install statsmodels
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
from matplotlib.font_manager import FontProperties
kaiti = FontProperties("KaiTi", size=16)  # 楷体字体

1. 时间序列

1.1 读取数据

df = pd.read_csv('data/stock/600036.xls')
df.head()

outputs:

date\topen\thigh\tlow\tclose\tvol
0 2014/01/20\t6.01\t6.1\t5.92\t5.97\t27537862
1 2014/01/21\t6.04\t6.18\t5.98\t6.03\t25159216
2 2014/01/22\t6.06\t6.28\t5.98\t6.2\t50123656
3 2014/01/23\t6.17\t6.21\t5.99\t6.02\t38634112
4 2014/01/24\t5.98\t6.06\t5.89\t5.93\t52264196

csv文件中以\t作为分隔符,需要重新读入

df = pd.read_csv('data/stock/600036.xls',sep='\t')
df.head()

outputs:

date open high low close vol
0 2014/01/20 6.01 6.10 5.92 5.97 27537862
1 2014/01/21 6.04 6.18 5.98 6.03 25159216
2 2014/01/22 6.06 6.28 5.98 6.20 50123656
3 2014/01/23 6.17 6.21 5.99 6.02 38634112
4 2014/01/24 5.98 6.06 5.89 5.93 52264196
df.dtypes

outputs:

date      object
open     float64
high     float64
low      float64
close    float64
vol        int64
dtype: object

由以上结果可以看出,读取的日期为object类型,不是datetime64[ns]

1.2 绘图

# 绘图函数
def plot_df(df, x, y, title="", xlabel='日期', ylabel='股价', dpi=100):
    plt.figure(figsize=(16,5), dpi=dpi)
    plt.plot(x, y, color='red')
    plt.title(title, fontproperties=kaiti)
    plt.xlabel(xlabel, fontproperties=kaiti)
    plt.ylabel(ylabel, fontproperties=kaiti)
    plt.show()
plot_df(df, x=df.index, y=df.close, title='招商银行收盘价')

收盘价

1.3 绘制日期

df_drug = pd.read_csv('data/a10.csv', parse_dates=['date'], index_col='date')
plot_df(df_drug, x=df_drug.index, y=df_drug.value, title='澳大利亚1992-2008糖尿病药品月销售额',ylabel='销售额')

销售额

df_drug.index, df_drug.dtypes

outputs:

(DatetimeIndex(['1991-07-01', '1991-08-01', '1991-09-01', '1991-10-01',
                '1991-11-01', '1991-12-01', '1992-01-01', '1992-02-01',
                '1992-03-01', '1992-04-01',
                ...
                '2007-09-01', '2007-10-01', '2007-11-01', '2007-12-01',
                '2008-01-01', '2008-02-01', '2008-03-01', '2008-04-01',
                '2008-05-01', '2008-06-01'],
               dtype='datetime64[ns]', name='date', length=204, freq=None),
 value    float64
 dtype: object)

由上述结果可知,此时index为日期

2. 平稳性检验

from statsmodels.tsa.stattools import adfuller, kpss
# 读取数据
df = pd.read_csv('data/a10.csv', parse_dates=['date'])
plot_df(df, x=df.date, y=df.value, title='澳大利亚1992-2008糖尿病药品月销售额',ylabel='销售额')

销售额

2.1 ADF检验

ADF检验,也称为单位跟检验

ADF检验原理

要检验的对象是单位根。

对于一阶AR模型,即AR(1)的情况,其模型如下:

$r_t = \alpha_1r_{t-1} + w_t$

  • 如果$\alpha_1=1$,那么前一时刻的收益率对当下时刻的影响是100%的,不会减弱;那么就算是很远的某个时刻,当下对它的影响还是不会消除,所以方差受前面所有时刻的影响,是和t相关的,因此不平稳;
  • 如果$\alpha_1>1$,那么当前时刻的波动不仅受前面时刻的影响,还被放大了,所以肯定不平稳;
  • 只有当$\alpha_1<1$的时候,前面时刻的波动对当前时刻的影响会逐渐减小。此时的自协方差以及自相关系数是一个固定值。这种情况下,序列是平稳的。

对于高阶AR模型也是如此。对于AR(P)阶模型:

$r_t = \sum_{i=1}^{p}(\alpha_ir_{t-i} + w_t)$

如果$\alpha_1~\alpha_P$都小于1,那么这个序列是平稳的;如果存在某一个$\alpha_i>=1$,这个序列就不是平稳的。

要判断$\alpha_1~\alpha_P$是否都小于1,一般利用AR模型的特征方程,如下:

$1-\alpha_1x - \alpha_2x^2 - \alpha_3x^3 - … - \alpha_Px^P = 0$

这个方程有p个根。

检验AR序列是否平稳,就是检验是否存在某个根大于等于1。这个过程叫单位根检验

(如果序列平稳,就不存在单位根;否则,就会存在单位根。)

所以,ADF检验的原假设就是存在单位根,如果得到的显著性检验统计量小于三个置信度(10%,5%,1%),则对应有(90%,95,99%)的把握来拒绝原假设。

result = adfuller(df.value.values, autolag='AIC')
print('ADF Statistic:', result[0])
print('p-value:',result[1])
for key, value in result[4].items():
    print('Critial Values:',key, value)
ADF Statistic: 3.14518568930675
p-value: 1.0
Critial Values: 1% -3.465620397124192
Critial Values: 5% -2.8770397560752436
Critial Values: 10% -2.5750324547306476

分析以上结果:

t统计量为3.14518568930675

p值为1.0

t统计量同时大于1%、5%、10%,说明保留原假设,有单位根,序列不平稳。

2.2 KPSS检验

# KPSS Test
result = kpss(df.value.values, regression='c')
print('\nKPSS Statistic: %f' % result[0])
print('p-value: %f' % result[1])
for key, value in result[3].items():
    print('Critial Values:',key, value)
KPSS Statistic: 2.013126
p-value: 0.010000
Critial Values: 10% 0.347
Critial Values: 5% 0.463
Critial Values: 2.5% 0.574
Critial Values: 1% 0.739

分析以上结果:

统计量为2.013126

p值为0.01

统计量同时大于1%、2.5%、5%、10%,说明保留原假设,序列不平稳。

2.3 一阶差分

plot_df(df, x=df.date, y=df.value.diff(1), title='澳大利亚1992-2008糖尿病药品月销售额的一阶差分',ylabel='销售额')

一阶差分

# ADF Test
diff_value = df.value.diff(1)
result = adfuller(diff_value[1:].values, autolag='AIC')
print('ADF Statistic:', result[0])
print('p-value:',result[1])
for key, value in result[4].items():
    print('Critial Values:',key, value)
# KPSS Test
result = kpss(diff_value[1:].values, regression='c')
print('\nKPSS Statistic: %f' % result[0])
print('p-value: %f' % result[1])
for key, value in result[3].items():
    print('Critial Values:',key, value)
ADF Statistic: -2.495172147449788
p-value: 0.11665341686467584
Critial Values: 1% -3.465811691080702
Critial Values: 5% -2.877123351472649
Critial Values: 10% -2.5750770662586864

KPSS Statistic: 0.134106
p-value: 0.100000
Critial Values: 10% 0.347
Critial Values: 5% 0.463
Critial Values: 2.5% 0.574
Critial Values: 1% 0.739

此时ADF检验不平稳,KPSS检验平稳,则趋势平稳,即去除趋势后平稳

2.4 二阶差分

# ADF Test
diff_value = df.value.diff(1).diff(1)
result = adfuller(diff_value[2:].values, autolag='AIC')
print('ADF Statistic:', result[0])
print('p-value:',result[1])
for key, value in result[4].items():
    print('Critial Values:',key, value)
# KPSS Test
result = kpss(diff_value[2:].values, regression='c')
print('\nKPSS Statistic: %f' % result[0])
print('p-value: %f' % result[1])
for key, value in result[3].items():
    print('Critial Values:',key, value)
ADF Statistic: -10.292304706517312
p-value: 3.5439163585295715e-18
Critial Values: 1% -3.465811691080702
Critial Values: 5% -2.877123351472649
Critial Values: 10% -2.5750770662586864

KPSS Statistic: 0.162690
p-value: 0.100000
Critial Values: 10% 0.347
Critial Values: 5% 0.463
Critial Values: 2.5% 0.574
Critial Values: 1% 0.739

此时ADF检验和KPSS检验均为平稳

2.5 自相关图检验

平稳序列通常具有短期相关性。该性质用自相关系数来描述就是随着延迟期数的增加,平稳序列的自相关系数会很快地衰减向零

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# 读取数据
df = pd.read_csv('data/a10.csv', parse_dates=['date'], index_col="date")
plt.figure()
ax1 = plt.subplot2grid((2,2), (0,0))
ax2 = plt.subplot2grid((2,2), (0,1))
plot_acf(df.value, ax1)
plot_pacf(df.value, ax2)

自相关图

  • 对于自相关图蓝色区域为误差范围(Error Band),区域内的数据被认为是不显著的。上图中,1-15是显著的。
  • PACF只考虑特定周期的相关性,它给了我们很好的确定自相关周期的起点,上图中,比如1,2,3,12,13可作为自相关时间周期的备选。
plt.figure()
ax1 = plt.subplot2grid((2,2), (0,0))
ax2 = plt.subplot2grid((2,2), (0,1))
plot_acf(df.value.diff(1), ax1)
plot_pacf(df.value.diff(1), ax2)

自相关图

自相关系数衰减到了0

3. 纯随机性检验(白噪声检验)

from statsmodels.stats.diagnostic import acorr_ljungbox
# 读取数据
df = pd.read_csv('data/a10.csv', parse_dates=['date'])

3.1 标准正态分布白噪声

varepsilon_values_1 = np.random.randn(df.shape[0])
plt.figure(figsize=(10, 6))
plt.plot(varepsilon_values_1)
plt.show()

标准正态分布

白噪声序列的性质

1.纯随机性

各序列值之间没有任何相关关系,即为 “没有记忆”的序列。

2.方差齐性

根据马尔可夫定理,只有方差齐性假定成立时,用最小二乘法得到的未知参数估计值才是准确的、有效的。

3.2 白噪声检验

result = acorr_ljungbox(varepsilon_values_1, lags=20)  # 返回统计量和p值,lags为检验的延迟数
result

outputs:

lb_stat lb_pvalue
1 0.153627 0.695093
2 0.331413 0.847295
3 3.132339 0.371668
4 3.408137 0.491983
5 3.486530 0.625427
6 5.388970 0.494976
7 6.007531 0.538870
8 6.309364 0.612622
9 6.749453 0.663186
10 7.257745 0.700909
11 7.961411 0.716756
12 10.103270 0.606901
13 10.445171 0.657189
14 10.986957 0.687060
15 10.989072 0.753369
16 12.687205 0.695476
17 14.131766 0.657754
18 14.244514 0.713018
19 14.296445 0.766144
20 14.977978 0.777666

上述中第二列为p值,当p值中最小值大于等于0.05时,说明序列是随机的。

上述中第二列最小值为0.37,说明序列是随机的。

result = acorr_ljungbox(df.value, lags=20)  # 返回统计量和p值,lags为检验的延迟数
result

outputs:

lb_stat lb_pvalue
1 175.433787 4.813705e-40
2 339.417587 1.978826e-74
3 491.848576 2.787243e-106
4 640.295836 2.939213e-137
5 784.110251 3.167141e-167
6 918.690676 3.419747e-195
7 1048.308626 4.383473e-222
8 1171.998472 1.075302e-247
9 1291.089683 2.599520e-272
10 1411.387306 3.450320e-297
11 1531.057189 0.000000e+00
12 1664.327467 0.000000e+00
13 1776.570839 0.000000e+00
14 1878.886391 0.000000e+00
15 1973.993523 0.000000e+00
16 2064.957725 0.000000e+00
17 2152.320626 0.000000e+00
18 2234.123711 0.000000e+00
19 2311.147387 0.000000e+00
20 2383.748884 0.000000e+00

上述结果最小值为0,小于0.5,所以不是随机的。


文章作者: 易安
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 易安 !
评论
  目录