4、协整理论入门:从直觉到检验

做跨市场套利,最核心的问题是什么?

说白了就是——两个价格序列,到底是不是「一家人」?

如果它们长期走在一起,偶尔分开但总会回来,那这就是我们赚钱的机会。这个「走在一起」的数学概念,就是协整。

4.1 协整的直观理解:一根绳上的蚂蚱

我刚开始接触量化时,对协整的理解特别绕。后来一个老交易员跟我说了句话,我一下就通了——「协整就是两个醉汉互相搀着走路」。

你想想看,两个醉汉单独走,都东倒西歪(非平稳)。但互相搀着,虽然也晃,可不会倒(平稳组合)。这就是协整的精髓。

核心定义:如果两个或多个非平稳时间序列的线性组合是平稳的,那它们就存在协整关系。

用公式表达:
yt - β·xt = εt,其中 εt 是平稳序列

我在做股指期货跨期套利时遇到过这么个事:IF主力合约和次主力合约,单独看都是随机游走(非平稳),但它们的价差序列却非常稳定。这就是典型的协整关系。

4.2 平稳性与单位根检验(ADF检验)

聊协整之前,必须先搞懂平稳性。为什么?因为协整的前提就是「单个非平稳,组合平稳」。

4.2.1 什么是平稳性?

平稳性分两种:

  • 严平稳:联合分布不随时间变化。太严格,实际中很少用。
  • 弱平稳:均值、方差恒定,协方差只与时间间隔有关。我们通常说的平稳,指的就是这个。

举个例子:白噪声是平稳的,随机游走不是平稳的。随机游走的方差会随时间越变越大,你想想看,这能稳吗?

4.2.2 单位根检验——ADF检验

判断一个序列是否平稳,最常用的方法就是单位根检验。ADF检验是其中的主力。

它的逻辑其实很简单:

  1. 假设序列存在单位根(非平稳)
  2. 如果检验统计量小于临界值,就拒绝原假设,认为序列平稳

我的经验: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检验) Engle-Granger两步法 (适用于两个序列) Johansen检验 (适用于多个序列) ① OLS回归估计协整系数 ② 检验残差平稳性 ① 构建VAR模型 ② 迹统计量/最大特征值检验 确认协整关系 → 构建价差策略

嗯,到这里协整理论的核心内容就讲完了。记住一句话:协整不是相关性,它比相关性更「硬核」——它描述的是长期均衡关系,而不是短期同步波动。

本章要点回顾:

  • 协整 = 非平稳序列的线性组合变成平稳
  • ADF检验是判断平稳性的基础工具
  • EG两步法适合两个序列,简单直观
  • Johansen检验适合多序列,功能更强大
  • 做协整前一定要先确认所有序列都是I(1)

我个人习惯在开始任何跨市场策略之前,先用Johansen检验扫一遍候选品种。虽然多花点时间,但能避免很多伪回归的坑。你想想看,如果连协整关系都不存在,那后面的套利策略不就是空中楼阁吗?

专注资料整理