3. 单位根检验(上):ADF检验的原理与Python实现
各位同学,咱们今天聊聊单位根检验。说实话,这玩意儿是统计套利的入门砖,也是很多人容易翻车的地方。我当年刚做量化那会儿,就因为单位根检验没搞明白,回测跑得飞起,实盘亏得亲妈都不认识。嗯,今天咱们就把这块硬骨头啃下来。
3.1 为什么需要单位根检验?
先问个问题:你手上有两只股票的价格序列,直接算相关系数,发现高达0.95。是不是就能做配对交易了?
别急。我见过太多新手直接拿价格序列算相关性,然后兴冲冲地建仓。结果呢?两个随机游走的序列,相关系数也可能很高。这就是所谓的「伪回归」——看着相关,其实屁关系没有。
单位根检验,说白了就是检查你的时间序列是不是「随机游走」的。如果是,那它就没有均值回归的特性,不适合做配对交易。如果不是,恭喜你,找到了一个可以下手的标的。
3.2 ADF检验的原理
ADF检验,全称是Augmented Dickey-Fuller检验。名字挺唬人,其实逻辑很简单。
咱们先回忆一下,一个时间序列如果是随机游走的,它的表达式是这样的:
y_t = y_{t-1} + ε_t
这里的系数是1,所以叫「单位根」。ADF检验要做的,就是检验这个系数是不是真的等于1。
具体来说,ADF检验会跑这样一个回归:
Δy_t = α + βt + γy_{t-1} + δ₁Δy_{t-1} + ... + δₚΔy_{t-p} + ε_t
其中:
- Δy_t 是 y_t 的一阶差分
- α 是常数项
- βt 是时间趋势项
- γ 就是我们要检验的核心系数
- δ₁到δₚ 是滞后项的系数,用来消除自相关
原假设 H₀:γ = 0(存在单位根,序列非平稳)
备择假设 H₁:γ < 0(不存在单位根,序列平稳)
如果检验统计量小于临界值,就拒绝原假设,认为序列是平稳的。反之,就不能拒绝原假设,序列非平稳。
3.3 ADF检验的Python实现
好了,理论讲完了,咱们直接上代码。Python里实现ADF检验,最常用的就是statsmodels库。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller
import yfinance as yf
# 下载数据
ticker = 'AAPL'
data = yf.download(ticker, start='2020-01-01', end='2023-12-31')
price = data['Close']
# 执行ADF检验
result = adfuller(price, autolag='AIC')
print(f'ADF统计量: {result[0]:.4f}')
print(f'p值: {result[1]:.4f}')
print(f'临界值:')
for key, value in result[4].items():
print(f' {key}: {value:.4f}')
# 判断结果
if result[1] < 0.05:
print('拒绝原假设,序列平稳')
else:
print('不能拒绝原假设,序列非平稳')
这段代码跑完之后,你会看到类似这样的输出:
ADF统计量: -1.2345
p值: 0.6543
临界值:
1%: -3.4321
5%: -2.8623
10%: -2.5678
不能拒绝原假设,序列非平稳
嗯,意料之中。股票价格序列通常都是非平稳的。那咱们试试看差分后的序列:
# 对一阶差分做ADF检验
price_diff = price.diff().dropna()
result_diff = adfuller(price_diff, autolag='AIC')
print(f'差分后ADF统计量: {result_diff[0]:.4f}')
print(f'差分后p值: {result_diff[1]:.4f}')
if result_diff[1] < 0.05:
print('差分后序列平稳')
else:
print('差分后序列仍非平稳')
一般来说,金融时间序列一阶差分后就会变成平稳序列。这就是所谓的「一阶单整」,记作 I(1)。
3.4 滞后阶数的选择
ADF检验里有个参数叫「滞后阶数」,就是前面公式里的 p。这个参数怎么选?
statsmodels的adfuller函数默认用AIC准则自动选择最优滞后阶数。我个人习惯用autolag='AIC',但有时候也会对比一下BIC的结果。
# 手动指定滞后阶数
for lag in range(1, 6):
result = adfuller(price, maxlag=lag, autolag=None)
print(f'滞后阶数={lag}, p值={result[1]:.4f}')
你可能会发现,不同滞后阶数下,p值可能不一样。这时候怎么办?我的建议是:
- 如果所有滞后阶数下结果一致,那没问题
- 如果结果不一致,优先相信AIC选出来的结果
- 如果还是拿不准,用KPSS检验交叉验证一下
3.5 知识体系总览
为了让大家更直观地理解本章的知识结构,我画了一张图:
3.6 实战中的注意事项
最后,分享几个我在实战中踩过的坑:
- 数据长度问题: ADF检验对样本量敏感。我一般要求至少100个数据点,少于50个基本不可靠。
- 结构性断点: 如果序列在某个时间点发生了结构性变化(比如股灾、政策变化),ADF检验可能会失效。这时候可以考虑用Zivot-Andrews检验。
- 多重检验问题: 如果你同时检验100个序列,即使所有序列都是平稳的,也会有大约5个被误判为非平稳。记得做多重检验校正。
- 不要只看p值: p值小于0.05就说平稳?不一定。还要看ADF统计量是否小于临界值。有时候p值很小,但统计量其实没超过临界值,这种情况要警惕。
好了,ADF检验的原理和实现就讲到这里。记住,单位根检验是统计套利的第一步,但不是唯一的一步。下一节咱们会讲KPSS检验,两者结合使用效果更好。
公众号:蓝海数据掘金营,微信deep3321