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检验里最让人头疼的地方。选少了,残差自相关没清干净,检验结果偏误。选多了,自由度损失大,检验功效下降。

我个人习惯用两种方法结合着来:

  1. AIC/BIC准则:遍历 p = 0 到某个最大值(比如 floor(12*(n/100)^(1/4))),选AIC或BIC最小的那个。
  2. 残差自相关检验:选完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检验核心逻辑流程图 输入时间序列 y_t 选择模型形式(无/截距/趋势) 选择滞后阶数 p(AIC/BIC) 执行ADF回归,计算统计量 统计量 < 临界值? 存在单位根(不平稳) 序列平稳 图例: 输入/输出 参数选择 计算过程 回归分析 判断节点

嗯,这张图把ADF检验的整个流程串起来了。从输入序列开始,到选择模型形式、选滞后阶数、执行回归,最后判断是否平稳。每一步都有讲究,别跳步。

个人经验:我一般会在回测框架里写一个ADF检验的封装函数,自动跑三种模型形式,自动选滞后阶数,然后输出一个「平稳/不平稳」的结论。这样每次做协整分析时,直接调用就行,省得每次都手动调参数。

好了,ADF检验的原理就聊到这儿。记住,检验只是工具,理解数据背后的经济含义才是关键。别为了通过检验而刻意调参数,那是在骗自己。