4. 协整检验实战:Engle-Granger两步法、Johansen检验、Python代码实现协整检验
协整检验,说白了就是看看两个或多个价格序列,是不是在长期上「手拉手」一起走。
我刚开始做价差交易那会儿,总以为只要两个品种走势像,就能配对。结果亏了不少钱。后来才明白——走势像不代表有协整关系,可能是伪回归。嗯,这里要注意。
今天咱们就把协整检验的两种主流方法讲透:Engle-Granger两步法和Johansen检验。我会带上Python代码,直接跑给你看。
4.1 为什么需要协整检验?
先问个问题:两个时间序列,相关系数0.9,能不能做配对交易?
答案是不一定。相关系数高,可能只是巧合。比如两个完全不相关的随机游走,相关系数也可能很高。这就是伪回归。
协整检验要解决的就是这个问题。它检验的是:两个序列的线性组合,是不是平稳的。如果是,那它们就有长期均衡关系。价差偏离了,迟早会回来。
我个人习惯,做任何配对交易前,先跑协整检验。这一步省不了。
4.2 Engle-Granger两步法
这个方法很直观。说白了就是两步走:
- 第一步:估计长期关系。用OLS回归,把两个序列的关系找出来。
- 第二步:检验残差平稳性。对残差做单位根检验(ADF检验)。如果残差平稳,就说明有协整关系。
我在项目中遇到过一个问题:EG两步法对样本量敏感。样本太少,检验功效会下降。一般建议至少200个数据点。
4.2.1 第一步:OLS回归
假设我们有两个价格序列:y 和 x。回归方程是:
y_t = α + β * x_t + ε_t
这里的 ε_t 就是残差,代表价差。
4.2.2 第二步:ADF检验
对残差 ε_t 做ADF检验。如果p值小于0.05,就拒绝「有单位根」的原假设,说明残差平稳,协整关系成立。
4.2.3 Python代码实现
import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
# 模拟两个协整序列
np.random.seed(42)
n = 500
x = np.cumsum(np.random.randn(n))
y = 2 * x + np.random.randn(n) * 0.5 # 协整关系
# 第一步:OLS回归
X = sm.add_constant(x)
model = sm.OLS(y, X).fit()
residuals = model.resid
# 第二步:ADF检验残差
adf_result = adfuller(residuals, autolag='AIC')
print(f'ADF统计量: {adf_result[0]:.4f}')
print(f'p值: {adf_result[1]:.4f}')
if adf_result[1] < 0.05:
print('结论:残差平稳,存在协整关系')
else:
print('结论:残差不平稳,不存在协整关系')
跑完这段代码,你会看到p值很小,说明协整关系成立。嗯,模拟数据嘛,肯定成立的。
4.3 Johansen检验
EG两步法有个局限:只能检验两个序列,而且不能处理多个协整关系。Johansen检验就解决了这个问题。
Johansen检验基于向量自回归模型(VAR),可以同时检验多个序列之间是否存在协整关系,还能告诉你存在几个协整向量。
我个人觉得,做多品种配对时,Johansen检验是首选。比如你要做一篮子股票和ETF的价差,用Johansen就对了。
4.3.1 检验原理
Johansen检验有两种统计量:
- 迹统计量(Trace Statistic):检验协整秩(即协整关系的个数)
- 最大特征值统计量(Max Eigenvalue Statistic):检验单个协整关系是否存在
一般先看迹统计量,再看最大特征值。两者结论一致时,结果更可靠。
4.3.2 Python代码实现
from statsmodels.tsa.vector_ar.vecm import coint_johansen
# 准备数据:至少两个序列
data = pd.DataFrame({
'y': y,
'x': x
})
# Johansen检验
johansen_result = coint_johansen(data, det_order=0, k_ar_diff=1)
# 输出迹统计量
print('迹统计量:')
print(johansen_result.lr1)
print('临界值(90%, 95%, 99%):')
print(johansen_result.cvt)
# 输出最大特征值统计量
print('\n最大特征值统计量:')
print(johansen_result.lr2)
print('临界值(90%, 95%, 99%):')
print(johansen_result.cvm)
输出结果中,如果迹统计量大于临界值,就拒绝原假设。比如 lr1[0] > cvt[0][1],说明至少存在一个协整关系。
4.4 EG两步法 vs Johansen检验:怎么选?
| 对比维度 | Engle-Granger两步法 | Johansen检验 |
|---|---|---|
| 适用场景 | 两个序列 | 两个及以上序列 |
| 协整关系个数 | 只能检验是否存在 | 可以检验个数 |
| 计算复杂度 | 低,两步搞定 | 高,基于VAR |
| 样本量要求 | 至少200个点 | 至少300个点 |
| 对残差假设 | 残差需独立同分布 | 更宽松 |
你想想看,如果只是做两个品种的配对,EG两步法够用了。但如果你要做多品种组合,比如3个以上,那就得上Johansen。
4.5 实战中的避坑指南
我做了这么多年量化,协整检验踩过的坑不少。给你总结几个:
- 数据频率要一致:别拿日线和小时线混着检验,结果会乱套。
- 注意结构性断点:如果市场发生了重大变化(比如政策突变),协整关系可能断裂。我建议分段检验。
- 不要过度优化:有些人为了得到协整关系,反复调参数。这是数据挖掘,实盘会亏死你。
- 协整不等于因果关系:两个序列协整,不代表一个能预测另一个。只是说它们长期同步。
4.6 本章知识体系图
这张图把本章的核心逻辑串起来了。左边是EG两步法,右边是Johansen检验,底部是实战建议。你保存下来,以后做协整检验时对照着看。
好了,协整检验就讲到这里。代码都给你了,回去跑一跑,看看你的品种有没有协整关系。记住,检验通过只是第一步,后面还有参数估计、交易策略设计等着你。
公众号:蓝海资料掘金营,微信deep3321