4. 协整检验实战:Python实现Engle-Granger两步法、解读检验结果

协整检验,说白了就是验证两个价格序列之间是否存在长期稳定的关系。如果它们真的“手拉手”一起走,那价差就会围绕均值来回摆动——这正是我们做均值回归策略的基础。

我个人习惯用Engle-Granger两步法,因为它直观、好理解,而且代码写起来也顺手。咱们一步步来。

4.1 Engle-Granger两步法核心逻辑

这个方法分两步走:

  1. 第一步:用OLS回归估计协整系数
    把其中一个价格序列作为因变量,另一个作为自变量,跑一个线性回归。回归的残差,就是我们要的价差序列。
  2. 第二步:对残差做单位根检验
    如果残差是平稳的,那这两个序列就存在协整关系。说白了,就是它们之间的价差不会越跑越远。

嗯,这里要注意:第一步的回归里,截距项一定要带上。我在项目中遇到过有人忘了加截距,结果残差看起来平稳,实际上一跑回测就亏钱——因为价差均值根本不是零。

核心要点: 协整关系 ≠ 相关系数高。两个完全不相关的序列也可能协整,关键是看残差是否平稳。

4.2 Python代码实现

咱们用statsmodels库来实现。先导入必要的包:

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

假设我们有两个价格序列 price_aprice_b,长度都是500。第一步,跑OLS回归:

# 第一步:OLS回归
X = sm.add_constant(price_b)  # 加截距项
model = sm.OLS(price_a, X).fit()
residuals = model.resid  # 这就是价差序列

# 看看回归结果
print(model.summary())

第二步,对残差做ADF检验:

# 第二步:ADF检验
adf_result = adfuller(residuals, maxlag=1)
print(f'ADF统计量: {adf_result[0]:.4f}')
print(f'p值: {adf_result[1]:.4f}')
print(f'临界值: {adf_result[4]}')

你想想看,如果p值小于0.05,就说明残差是平稳的,两个序列存在协整关系。这时候我们就可以放心地做价差回归策略了。

我的小技巧: 我一般会把ADF检验的滞后阶数设成1到5都跑一遍,取p值最小的那个。因为不同滞后阶数下,检验结果可能不一样。选最严格的,心里踏实。

4.3 解读检验结果

跑完代码后,你会看到类似这样的输出:

ADF统计量: -3.4521
p值: 0.0087
临界值: {'1%': -3.443, '5%': -2.867, '10%': -2.570}

怎么解读?我一般看三个东西:

  • p值 < 0.05:拒绝原假设(序列非平稳),说明残差平稳,协整关系成立。
  • ADF统计量 < 临界值:比如-3.4521小于-3.443(1%临界值),说明在1%的显著性水平下都显著。
  • 临界值对比:如果统计量比1%临界值还小,那这个协整关系非常强,策略的胜率会更高。

我曾经遇到过一个案例,p值是0.06,刚好在临界点附近。当时我犹豫了一下,还是决定用这个组合做策略。结果回测下来,价差偶尔会“脱缰”,亏了好几笔。后来我学乖了——p值大于0.05的,直接放弃,别心存侥幸。

避坑指南: 我曾经在数据量不足100个样本点时跑协整检验,结果p值特别好看,但实盘一跑就崩。后来才知道,ADF检验在小样本下容易出假阳性。建议至少用200个以上的数据点。

4.4 完整流程封装

为了方便复用,我习惯把整个流程封装成一个函数:

def check_cointegration(price_x, price_y, alpha=0.05):
    """
    检查两个价格序列是否协整
    返回: (is_cointegrated, hedge_ratio, residuals, adf_pvalue)
    """
    # 第一步:OLS回归
    X = sm.add_constant(price_y)
    model = sm.OLS(price_x, X).fit()
    hedge_ratio = model.params[1]  # 对冲比率
    residuals = model.resid
    
    # 第二步:ADF检验
    adf_result = adfuller(residuals, maxlag=1)
    p_value = adf_result[1]
    
    is_cointegrated = p_value < alpha
    return is_cointegrated, hedge_ratio, residuals, p_value

# 使用示例
result = check_cointegration(price_a, price_b)
if result[0]:
    print(f'协整关系成立!对冲比率: {result[1]:.4f}, p值: {result[3]:.4f}')
else:
    print('不协整,换个组合试试')

这个函数返回四个东西:是否协整、对冲比率、残差序列、p值。对冲比率就是你在策略里做多1份A时,需要做空多少份B的那个系数。

4.5 知识体系总览

下面这张图把整个协整检验的流程串起来了,你一看就明白:

协整检验实战流程 输入:两个价格序列 第一步:OLS回归(带截距) price_a = α + β * price_b + ε 提取残差 ε(价差序列) 第二步:ADF单位根检验 H₀: 残差非平稳(不协整)

你看,整个流程其实就三个环节:输入价格 → OLS回归 → ADF检验。但每个环节都有坑,比如截距项、滞后阶数、样本量——这些细节决定了你的策略能不能赚钱。

好了,协整检验这块就聊到这儿。你回去拿两个股票试试,看看哪些组合能通过检验。记住,p值小于0.05是底线,但小于0.01才更让人放心。

一句话总结: 协整检验就是给价差回归策略“验明正身”——只有通过了,才值得你花时间去优化参数。

专注资料整理