3. 协整理论与检验
协整,这个词听起来挺唬人的。说白了,就是两个或多个看起来随机乱跑的时间序列,它们之间其实存在一种长期稳定的关系。我刚开始接触这个概念时,也觉得有点绕。你想想看,如果两个序列各自都是随机游走,那它们按理说应该各走各的才对。但现实中有很多这样的例子——比如沪深300和上证50,短期看各自波动,长期看却总往一块儿凑。
为什么会这样?因为它们背后有共同的经济力量在牵引。这就是协整的核心思想。
协整的数学定义
先给个严谨的定义。设 yt 和 xt 都是 I(1) 序列(一阶单整),如果存在一个系数 β,使得:
zt = yt - β·xt ~ I(0)
那么我们就说 yt 和 xt 是协整的。这里的 β 叫协整系数,zt 叫协整残差。
嗯,这里要注意:协整的前提是两个序列必须同阶单整。一个 I(1) 和一个 I(2) 是不可能协整的。我在项目中遇到过有人拿 I(1) 和 I(0) 去做协整检验,结果跑出来一堆假信号,亏了不少手续费。
核心要点:协整 ≠ 相关性。两个股票可能高度相关(比如同行业的茅台和五粮液),但不一定协整。协整强调的是长期均衡关系,短期可以偏离,但长期必须回归。
Engle-Granger 两步法
这是最经典的协整检验方法,1987年由 Engle 和 Granger 提出。我个人习惯叫它「EG两步法」,简单粗暴,适合入门。
第一步:估计协整关系
用 OLS 回归估计:
yt = α + β·xt + εt
得到残差序列 êt = yt - α̂ - β̂·xt
第二步:检验残差的平稳性
对残差 êt 做 ADF 检验。如果残差是平稳的,就说明存在协整关系。
这里有个坑——EG两步法的临界值不能用标准的 ADF 临界值。因为残差是从回归中估计出来的,不是真实的误差项。我曾经在这个问题上栽过跟头,用标准临界值判断出协整,结果实盘一跑就崩。后来查了文献才知道,要用 MacKinnon 专门为协整检验提供的临界值表。
避坑指南:EG两步法只能检验两个变量之间的协整关系。如果你有三个以上变量,别用这个方法。我曾经见过有人拿 EG 法去检验五只股票的协整关系,结果跑出来一堆伪结论。
Johansen 检验
EG两步法有个明显的局限——它只能处理一个协整关系。但现实中,多个变量之间可能存在多个协整关系。比如五只银行股,可能有两三个不同的长期均衡关系在同时起作用。
Johansen 检验就是来解决这个问题的。它基于 VAR 模型,通过特征根迹检验和最大特征值检验,来判断协整关系的个数。
我个人觉得,Johansen 检验比 EG 法更优雅。它不需要先指定哪个是因变量哪个是自变量,所有变量一视同仁。而且它能告诉你到底存在几个协整关系——是1个、2个还是更多。
不过,Johansen 检验对滞后阶数的选择比较敏感。我建议用 AIC 或 BIC 准则来选择滞后阶数,别拍脑袋定。
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| EG两步法 | 两个变量 | 简单直观,容易实现 | 只能处理一个协整关系,小样本偏差大 |
| Johansen检验 | 多个变量 | 能检测多个协整关系,不依赖变量顺序 | 对滞后阶数敏感,计算复杂 |
Python 中的协整检验实现
statsmodels 库提供了现成的工具。我平时最常用的是 coint() 函数,它直接封装了 EG两步法。
import statsmodels.api as sm
import numpy as np
# 模拟两个协整序列
np.random.seed(42)
n = 200
x = np.random.randn(n).cumsum() # I(1)
y = x * 0.8 + np.random.randn(n) * 0.5 # 协整关系
# EG两步法检验
coint_result = sm.tsa.stattools.coint(y, x)
print(f"ADF统计量: {coint_result[0]:.4f}")
print(f"p值: {coint_result[1]:.4f}")
print(f"临界值(1%, 5%, 10%): {coint_result[2]}")
# 判断是否协整
if coint_result[1] < 0.05:
print("存在协整关系(p < 0.05)")
else:
print("不存在协整关系")
对于 Johansen 检验,statsmodels 提供了 coint_johansen() 函数:
from statsmodels.tsa.vector_ar.vecm import coint_johansen
# 准备数据(多变量)
data = np.column_stack([y, x, np.random.randn(n).cumsum()])
# Johansen检验
johansen_result = coint_johansen(data, det_order=0, k_ar_diff=1)
print("特征值:", johansen_result.eig)
print("迹统计量:", johansen_result.lr1)
print("最大特征值统计量:", johansen_result.lr2)
print("95%临界值(迹):", johansen_result.cvt)
print("95%临界值(最大特征值):", johansen_result.cvm)
实用技巧:我一般会同时跑 EG 和 Johansen 两种检验。如果两者结论一致,那信心就足很多。如果矛盾,我会检查数据质量、滞后阶数选择,或者考虑是否存在结构性突变。
协整检验的完整流程
在实际项目中,我通常按这个步骤来:
- 单位根检验:确认所有变量都是 I(1) 序列
- 选择方法:两个变量用 EG,多个变量用 Johansen
- 确定滞后阶数:用 AIC/BIC 选择最优滞后
- 执行检验:跑代码,看 p 值和统计量
- 验证稳健性:换样本期、换参数,看结论是否稳定
最后一步特别重要。我见过太多人跑一次检验就以为找到了圣杯,结果换了个时间窗口结论就变了。协整关系是会随时间变化的,尤其是市场环境发生重大变化时。
下面这张图展示了协整检验的核心逻辑,从数据准备到最终决策的完整链路:
协整检验是统计套利的基石。没有它,所谓的配对交易就是空中楼阁。我建议你拿到数据后,先把协整检验跑通,再考虑后面的策略设计。这一步走扎实了,后面的路会顺很多。