4、协整理论入门:从直觉到检验
做跨市场套利,最核心的问题是什么?
说白了就是——两个价格序列,到底是不是「一家人」?
如果它们长期走在一起,偶尔分开但总会回来,那这就是我们赚钱的机会。这个「走在一起」的数学概念,就是协整。
4.1 协整的直观理解:一根绳上的蚂蚱
我刚开始接触量化时,对协整的理解特别绕。后来一个老交易员跟我说了句话,我一下就通了——「协整就是两个醉汉互相搀着走路」。
你想想看,两个醉汉单独走,都东倒西歪(非平稳)。但互相搀着,虽然也晃,可不会倒(平稳组合)。这就是协整的精髓。
核心定义:如果两个或多个非平稳时间序列的线性组合是平稳的,那它们就存在协整关系。
用公式表达:
yt - β·xt = εt,其中 εt 是平稳序列
我在做股指期货跨期套利时遇到过这么个事:IF主力合约和次主力合约,单独看都是随机游走(非平稳),但它们的价差序列却非常稳定。这就是典型的协整关系。
4.2 平稳性与单位根检验(ADF检验)
聊协整之前,必须先搞懂平稳性。为什么?因为协整的前提就是「单个非平稳,组合平稳」。
4.2.1 什么是平稳性?
平稳性分两种:
- 严平稳:联合分布不随时间变化。太严格,实际中很少用。
- 弱平稳:均值、方差恒定,协方差只与时间间隔有关。我们通常说的平稳,指的就是这个。
举个例子:白噪声是平稳的,随机游走不是平稳的。随机游走的方差会随时间越变越大,你想想看,这能稳吗?
4.2.2 单位根检验——ADF检验
判断一个序列是否平稳,最常用的方法就是单位根检验。ADF检验是其中的主力。
它的逻辑其实很简单:
- 假设序列存在单位根(非平稳)
- 如果检验统计量小于临界值,就拒绝原假设,认为序列平稳
我的经验:ADF检验的滞后阶数选择很关键。我习惯用AIC准则自动选阶,而不是固定一个值。曾经有一次我固定用5阶,结果把平稳序列判成了非平稳,白白浪费了半天时间。
Python里做ADF检验非常方便:
from statsmodels.tsa.stattools import adfuller
# 假设 price1 和 price2 是两个价格序列
result1 = adfuller(price1)
result2 = adfuller(price2)
print(f'price1 ADF统计量: {result1[0]:.4f}')
print(f'price1 p值: {result1[1]:.4f}')
print(f'price2 ADF统计量: {result2[0]:.4f}')
print(f'price2 p值: {result2[1]:.4f}')
# 如果p值大于0.05,说明序列非平稳
if result1[1] > 0.05:
print('price1 非平稳')
if result2[1] > 0.05:
print('price2 非平稳')
注意:ADF检验对结构突变不敏感。如果序列在中间发生了断点,ADF可能会误判。我建议配合KPSS检验一起使用,双保险。
4.3 Engle-Granger两步法
这是最经典的协整检验方法。名字听着高大上,其实就两步:
第一步:估计协整关系
用OLS回归估计协整系数:
import statsmodels.api as sm
# 假设 price1 和 price2 都是非平稳的
X = sm.add_constant(price2)
model = sm.OLS(price1, X)
results = model.fit()
beta = results.params[1] # 协整系数
spread = price1 - beta * price2 # 价差序列
第二步:检验残差的平稳性
对价差序列做ADF检验:
spread_result = adfuller(spread)
print(f'价差序列ADF统计量: {spread_result[0]:.4f}')
print(f'价差序列p值: {spread_result[1]:.4f}')
if spread_result[1] < 0.05:
print('存在协整关系!可以开始做套利了')
else:
print('没有协整关系,换个品种试试')
避坑指南:我曾经犯过一个低级错误——直接用原始价格做回归,没检查平稳性。结果回归的R²高达0.99,但残差是非平稳的,这就是典型的「伪回归」。记住:EG两步法的前提是两个序列都是I(1)(一阶单整)。
4.4 Johansen检验简介
EG两步法有个明显的局限——只能处理两个序列,而且只能找到一个协整关系。那如果有三个、四个品种呢?或者存在多个协整关系呢?
这时候就该Johansen检验上场了。
Johansen检验的核心思想
它基于向量自回归模型(VAR),通过特征值来判断协整关系的个数。输出两个统计量:
- 迹统计量(Trace Statistic):检验协整秩是否小于等于r
- 最大特征值统计量(Max Eigenvalue Statistic):检验协整秩是否等于r
Python实现也很直接:
from statsmodels.tsa.vector_ar.vecm import coint_johansen
# 假设我们有三个价格序列:price1, price2, price3
data = pd.DataFrame({
'p1': price1,
'p2': price2,
'p3': price3
})
# det_order=1 表示包含常数项,k_ar_diff=1 表示差分滞后阶数
johansen_result = coint_johansen(data, det_order=1, k_ar_diff=1)
print('迹统计量:', johansen_result.lr1)
print('迹统计量临界值(95%):', johansen_result.cvt[:, 1])
print('最大特征值统计量:', johansen_result.lr2)
print('最大特征值临界值(95%):', johansen_result.cvm[:, 1])
# 判断协整关系的个数
r = 0
for i in range(len(johansen_result.lr1)):
if johansen_result.lr1[i] > johansen_result.cvt[i, 1]:
r += 1
print(f'存在 {r} 个协整关系')
我的建议:做多品种协整时,先用Johansen检验看看有几个协整关系。如果只有一个,那用EG两步法也行。如果有多个,那必须用Johansen。我在做商品期货跨品种套利时,经常用Johansen检验来筛选品种组合。
4.5 本章知识体系
下面这张图总结了协整理论的核心逻辑:
嗯,到这里协整理论的核心内容就讲完了。记住一句话:协整不是相关性,它比相关性更「硬核」——它描述的是长期均衡关系,而不是短期同步波动。
本章要点回顾:
- 协整 = 非平稳序列的线性组合变成平稳
- ADF检验是判断平稳性的基础工具
- EG两步法适合两个序列,简单直观
- Johansen检验适合多序列,功能更强大
- 做协整前一定要先确认所有序列都是I(1)
我个人习惯在开始任何跨市场策略之前,先用Johansen检验扫一遍候选品种。虽然多花点时间,但能避免很多伪回归的坑。你想想看,如果连协整关系都不存在,那后面的套利策略不就是空中楼阁吗?