平稳性检验基础:单位根检验(ADF)的原理与Python实现

各位同学,今天我们来聊聊平稳性检验。说实话,我刚入行做量化交易那会儿,对「平稳性」这三个字完全没概念。直到有一次,我用两组完全不相关的价格序列跑回归,居然跑出了0.85的R²——当时我还以为自己发现了什么交易圣杯,结果被老交易员一句话点醒:「你这是在用两个醉汉的脚印做回归分析。」

嗯,这个比喻很形象。两个醉汉在街上乱晃,他们的轨迹可能看起来「相关」,但本质上毫无关系。这就是伪回归的典型场景。而平稳性检验,就是帮我们识别「醉汉」和「清醒的人」的关键工具。

什么是平稳性?

平稳性,说白了就是一个时间序列的统计性质不随时间变化。具体来说,如果序列的均值、方差、自协方差都是常数(不依赖于时间t),我们就说它是平稳的。

我习惯把平稳序列想象成一个「有记忆但不会漂移」的过程。比如白噪声,它是最简单的平稳序列——均值恒为0,方差恒定,不同时刻之间没有相关性。再比如一个围绕固定均值波动的价格序列,如果它的波动幅度基本稳定,那它也可能是平稳的。

但金融数据里,大部分原始价格序列都是非平稳的。你想想看,上证指数从1990年的100点涨到现在的3000多点,均值明显在变化,对吧?这就是典型的非平稳——它有趋势,有漂移。

核心要点: 平稳性是协整分析的前提。如果两个序列都是非平稳的,但它们的线性组合是平稳的,那它们就存在协整关系。这就是我们做配对交易的理论基础。

单位根:非平稳的「罪魁祸首」

为什么序列会非平稳?根源在于「单位根」。

我们来看一个简单的一阶自回归模型 AR(1):

y_t = ρ * y_{t-1} + ε_t

其中 ε_t 是白噪声。这个模型描述的是:当前值等于上一期值乘以系数ρ,再加上一个随机扰动。

关键来了:

  • 如果 |ρ| < 1:序列是平稳的。冲击会逐渐衰减,序列会回归均值。
  • 如果 ρ = 1:这就是单位根过程。冲击是永久性的,序列会随机游走,不会回归均值。
  • 如果 |ρ| > 1:序列是爆炸性的,这在金融中很少见。

所以,检验平稳性,本质上就是检验 ρ 是否等于 1。这就是单位根检验的核心思想。

我的经验: 在实际项目中,我见过很多新手直接把价格序列拿去跑回归,结果发现R²高得离谱,但实际交易策略却亏得一塌糊涂。原因就是没做单位根检验。记住:非平稳序列之间的高相关性,往往是虚假的。

ADF检验的原理

ADF检验(Augmented Dickey-Fuller Test)是最常用的单位根检验方法。它是在DF检验的基础上扩展而来的,主要解决了DF检验中残差自相关的问题。

ADF检验的回归方程是这样的:

Δy_t = α + β*t + γ*y_{t-1} + δ_1*Δy_{t-1} + δ_2*Δy_{t-2} + ... + δ_p*Δy_{t-p} + ε_t

其中:

  • Δy_t = y_t - y_{t-1},是一阶差分
  • α 是截距项(漂移项)
  • β*t 是时间趋势项
  • γ 是我们最关心的系数——如果 γ=0,说明存在单位根
  • δ_1 到 δ_p 是滞后差分项,用来消除残差的自相关

原假设 H₀:γ = 0(存在单位根,序列非平稳)
备择假设 H₁:γ < 0(序列平稳)

检验统计量是 γ 的t统计量。ADF检验会把这个统计量和临界值比较,来判断是否拒绝原假设。

p-value与统计量的关系

这里我要重点讲一下p-value和统计量的关系。很多初学者会搞混,我当年也踩过这个坑。

简单来说:

  • ADF统计量:计算出来的检验值,越小(越负)越好
  • p-value:在统计量对应的概率值,越小越能拒绝原假设
  • 临界值:不同显著性水平下的阈值(1%、5%、10%)

判断规则:

  • 如果 ADF统计量 < 临界值,且 p-value < 0.05:拒绝原假设,序列平稳
  • 如果 ADF统计量 > 临界值,且 p-value > 0.05:不能拒绝原假设,序列非平稳

举个例子:假设我们算出来的ADF统计量是 -3.5,1%临界值是 -3.43,5%临界值是 -2.86。那么 -3.5 < -3.43,说明在1%显著性水平下可以拒绝原假设,序列是平稳的。对应的p-value应该小于0.01。

避坑指南: 我曾经犯过一个错误——只看ADF统计量,不看p-value。有一次统计量是 -2.9,看起来挺小的,但对应的p-value是0.12,大于0.05。实际上不能拒绝原假设,序列是非平稳的。所以一定要两个指标一起看。

Python实现:从零开始写ADF检验

好了,理论讲完了,我们来动手写代码。我个人习惯先用statsmodels库,因为它封装得很好,但为了让大家理解原理,我们先手动实现一个简化版。

import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
import matplotlib.pyplot as plt

# 生成示例数据:平稳序列 vs 非平稳序列
np.random.seed(42)
n = 200

# 平稳序列:AR(1) with ρ=0.5
y_stationary = np.zeros(n)
for t in range(1, n):
    y_stationary[t] = 0.5 * y_stationary[t-1] + np.random.randn()

# 非平稳序列:随机游走 (ρ=1)
y_nonstationary = np.cumsum(np.random.randn(n))

# 可视化
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(y_stationary)
plt.title('平稳序列 (ρ=0.5)')
plt.subplot(1, 2, 2)
plt.plot(y_nonstationary)
plt.title('非平稳序列 (随机游走)')
plt.tight_layout()
plt.show()

接下来,我们用statsmodels的adfuller函数来做ADF检验:

# ADF检验函数
def adf_test(series, title=''):
    result = adfuller(series, autolag='AIC')
    print(f'=== {title} ===')
    print(f'ADF统计量: {result[0]:.4f}')
    print(f'p-value: {result[1]:.4f}')
    print(f'临界值:')
    for key, value in result[4].items():
        print(f'  {key}: {value:.4f}')
    print(f'结论: {"平稳" if result[1] < 0.05 else "非平稳"}')
    print()

# 检验平稳序列
adf_test(y_stationary, '平稳序列')

# 检验非平稳序列
adf_test(y_nonstationary, '非平稳序列')

输出结果大概是这样:

=== 平稳序列 ===
ADF统计量: -5.2341
p-value: 0.0000
临界值:
  1%: -3.4632
  5%: -2.8759
  10%: -2.5744
结论: 平稳

=== 非平稳序列 ===
ADF统计量: -1.2345
p-value: 0.6543
临界值:
  1%: -3.4632
  5%: -2.8759
  10%: -2.5744
结论: 非平稳

你看,平稳序列的ADF统计量是 -5.23,远小于1%临界值 -3.46,p-value接近0,所以拒绝原假设,序列平稳。而非平稳序列的ADF统计量是 -1.23,大于所有临界值,p-value是0.65,不能拒绝原假设,序列非平稳。

实际应用中的注意事项

在实际项目中,有几点我想特别提醒大家:

  1. 滞后阶数的选择:ADF检验需要选择滞后阶数p。statsmodels默认用AIC自动选择,但我建议你手动检查一下。如果滞后阶数太少,残差可能有自相关;如果太多,检验功效会下降。
  2. 趋势项的选择:ADF检验有三种形式——无截距无趋势、有截距无趋势、有截距有趋势。选择哪种?看数据特征。如果序列有明显的时间趋势,就选有趋势项;如果没有,就选只有截距项。
  3. 样本量的影响:样本量太小(比如少于50个),ADF检验的功效会很低,可能把平稳序列误判为非平稳。我一般要求至少100个数据点。
我的习惯: 在做协整分析之前,我会先对每个序列单独做ADF检验,确认它们都是I(1)过程(即一阶差分后平稳)。然后对残差再做一次ADF检验,看残差是否平稳。如果残差平稳,就说明存在协整关系。

知识体系图

下面我用一张SVG图来总结本章的核心逻辑:

ADF检验知识体系 时间序列数据 ADF检验:Δy_t = α + β*t + γ*y_{t-1} + Σδ_i*Δy_{t-i} + ε_t ADF统计量 + p-value + 临界值 判断规则 ADF统计量 < 临界值 且 p-value < 0.05 → 平稳 ADF统计量 > 临界值 或 p-value > 0.05 → 非平稳

这张图把ADF检验的流程梳理得很清楚:输入数据 → 构建回归方程 → 计算统计量和p-value → 根据规则判断平稳性。每一步都环环相扣,缺一不可。

小结

平稳性检验是协整分析的基石。ADF检验通过检验单位根是否存在,帮我们判断序列是否平稳。记住三个关键点:

  • ADF统计量越小(越负),越可能平稳
  • p-value越小,越能拒绝非平稳的原假设
  • 两个指标要结合着看,不能只看一个

下一章我们会深入协整检验的具体方法,到时候这些基础概念会反复用到。嗯,今天就到这里,大家回去可以拿自己的数据跑一跑ADF检验,看看哪些序列是平稳的,哪些不是。


专注资料整理