3、ADF检验原理:数学原理、滞后阶数选择、临界值与P值
协整分析里,ADF检验是绕不开的一关。说白了,它就是帮我们判断一个时间序列是不是「平稳」的。如果序列不平稳,后面做协整回归就容易闹出「伪回归」的笑话——两个毫无关系的序列,回归出来R²还挺高,你敢信?
我刚开始做量化的时候,就吃过这个亏。当时拿沪深300和某只个股做回归,结果漂亮得不行,结果一查,俩序列都是随机游走...嗯,从那以后,我再也不敢跳过ADF检验了。
3.1 ADF检验的数学原理
ADF检验的全称是Augmented Dickey-Fuller检验。它是在DF检验基础上加了「滞后项」的改进版。
先看DF检验的原型。假设我们有一个时间序列 yt,最简单的自回归模型是:
y_t = ρ * y_{t-1} + ε_t
如果 ρ = 1,说明序列有单位根,不平稳。如果 |ρ| < 1,序列平稳。DF检验就是检验 H₀: ρ = 1 这个原假设。
但实际数据哪有这么简单?残差项 εt 往往存在自相关。这时候DF检验就不准了。ADF检验的改进在于——在回归方程里加入差分项的滞后值,来消除残差的自相关。
ADF检验的回归方程长这样:
Δy_t = α + β*t + γ*y_{t-1} + δ₁*Δy_{t-1} + δ₂*Δy_{t-2} + ... + δₚ*Δy_{t-p} + ε_t
其中:
- Δyt = yt - yt-1,一阶差分
- α 是截距项(漂移项)
- β*t 是时间趋势项
- γ 是我们要检验的核心系数,γ = ρ - 1
- δ₁ 到 δₚ 是滞后差分项的系数,用来吸收残差的自相关
原假设 H₀: γ = 0(存在单位根,不平稳)
备择假设 H₁: γ < 0(序列平稳)
核心要点:ADF检验本质上是在回归方程里「打扫干净」残差的自相关,然后再检验单位根。滞后阶数 p 选得对不对,直接影响检验结果。
3.2 滞后阶数选择——这个坑我踩过
滞后阶数 p 怎么选?说实话,这是ADF检验里最让人头疼的地方。选少了,残差自相关没清干净,检验结果偏误。选多了,自由度损失大,检验功效下降。
我个人习惯用两种方法结合着来:
- AIC/BIC准则:遍历 p = 0 到某个最大值(比如 floor(12*(n/100)^(1/4))),选AIC或BIC最小的那个。
- 残差自相关检验:选完p之后,检查残差是否还有显著的自相关。如果有,增加p。
我曾经在回测一个配对交易策略时,偷懒用了默认的滞后阶数,结果ADF检验说序列平稳,我兴冲冲地建了仓位。后来发现是伪平稳——滞后阶数选少了,残差里藏着自相关没被发现。那次亏了大概3%的净值,教训深刻。
实际代码里,我一般这么写:
import statsmodels.tsa.stattools as ts
# 方法1:自动选阶(默认使用AIC)
result = ts.adfuller(series, autolag='AIC')
# 方法2:手动指定最大滞后阶数
result = ts.adfuller(series, maxlag=12, autolag='AIC')
# 方法3:自己写循环选最优阶
import pandas as pd
from statsmodels.regression.linear_model import OLS
from statsmodels.tools import add_constant
def select_lag(series, max_lag=12):
best_aic = float('inf')
best_lag = 0
for p in range(1, max_lag+1):
# 构造回归数据
y = series.diff().dropna()
x = series.shift(1).dropna()
for i in range(1, p+1):
x = pd.concat([x, series.diff().shift(i)], axis=1)
x = add_constant(x)
model = OLS(y, x).fit()
if model.aic < best_aic:
best_aic = model.aic
best_lag = p
return best_lag
我的建议:对于日频数据,滞后阶数通常在5-15之间。周频数据3-8。别超过 floor(12*(n/100)^(1/4)),否则过拟合风险大。
3.3 临界值与P值——到底怎么看结果?
ADF检验输出三个关键数字:检验统计量、临界值、P值。很多人只看P值,其实不够。
检验统计量就是回归方程里 γ 的t统计量。如果这个值小于某个显著性水平下的临界值,就拒绝原假设,认为序列平稳。
举个例子:
# 假设我们得到这样的结果
ADF Statistic: -3.45
Critical Values:
1%: -3.50
5%: -2.89
10%: -2.58
p-value: 0.042
怎么看?
- 统计量 -3.45 大于 1% 临界值 -3.50 → 在1%水平不能拒绝原假设
- 统计量 -3.45 小于 5% 临界值 -2.89 → 在5%水平拒绝原假设
- P值 0.042 < 0.05 → 在5%水平显著
所以结论是:在5%显著性水平下,序列平稳。但在1%水平下不平稳。
注意:ADF检验的临界值不是标准t分布,而是Dickey-Fuller分布。别拿t分布表去查,会出大问题。statsmodels已经帮我们算好了,直接用就行。
这里有个细节——ADF检验有三种形式:
| 模型形式 | 回归方程包含 | 适用场景 |
|---|---|---|
| 无截距无趋势 | 只有 γ*yt-1 | 序列均值明显为0 |
| 有截距无趋势 | α + γ*yt-1 | 序列围绕非零均值波动 |
| 有截距有趋势 | α + β*t + γ*yt-1 | 序列有明显的时间趋势 |
怎么选?我一般先画个图看看序列长什么样。如果序列看起来有上升或下降趋势,就用带趋势的模型。如果只是围绕某个均值波动,用带截距的就行。
你想想看,如果序列本身有趋势,你却用了不带趋势的模型,那检验结果很容易误判为「有单位根」。反过来,如果序列没趋势,你硬加个趋势项,检验功效会下降。
实际项目中,我习惯三种形式都跑一遍,然后对比结果。如果三种形式结论一致,那基本稳了。如果不一致,就得仔细看看序列的特征了。
实战口诀:
- P值 < 0.05 → 大概率平稳(但别只看P值)
- 统计量 < 临界值 → 拒绝单位根假设
- 两者结合看,更稳妥
- 三种模型形式都跑一遍,避免误判
最后说一句,ADF检验不是万能的。它对结构性断点很敏感,如果序列中间发生了政策变化或市场结构变化,ADF检验可能误判。这时候可以考虑用Zivot-Andrews检验或者Perron检验做补充。不过那是后话了,先把ADF吃透再说。
嗯,这张图把ADF检验的整个流程串起来了。从输入序列开始,到选择模型形式、选滞后阶数、执行回归,最后判断是否平稳。每一步都有讲究,别跳步。
个人经验:我一般会在回测框架里写一个ADF检验的封装函数,自动跑三种模型形式,自动选滞后阶数,然后输出一个「平稳/不平稳」的结论。这样每次做协整分析时,直接调用就行,省得每次都手动调参数。
好了,ADF检验的原理就聊到这儿。记住,检验只是工具,理解数据背后的经济含义才是关键。别为了通过检验而刻意调参数,那是在骗自己。