3. 协整检验入门:平稳性概念、ADF检验原理、如何判断两个品种是否适合做配对

好,咱们进入正题。前面聊了价差回归策略的基本思路,但有个核心问题没解决——你怎么知道两个品种的价差会回归?万一它俩越走越远,你越补仓越亏,那不就成接盘侠了?

嗯,这里就要引入一个关键概念:协整。说白了,协整就是两个不靠谱的东西,它们的差距却挺靠谱。我刚开始做配对交易时,就吃过这个亏——选了两个看起来走势很像的品种,结果价差一路狂奔,差点爆仓。后来才明白,光看走势像不行,得做协整检验。

3.1 平稳性:什么叫「稳」?

先聊平稳性。你想想看,一个时间序列,如果它的均值、方差、自相关结构都不随时间变化,那它就是平稳的。用大白话说:它的统计性质是稳定的

举个例子:白噪声序列就是平稳的。你今天测它的均值是0,明天测还是0,后天还是0。但股票价格呢?大多数股票价格是非平稳的——它可能今天在100块,明天涨到110,后天跌到90,均值一直在变。

我个人习惯把平稳性分成两种:

  • 严平稳:所有统计性质都不变。太严格了,现实中几乎不存在。
  • 弱平稳:均值、方差不变,自相关只与时间间隔有关。够用了。

那为什么配对交易需要平稳性?因为价差序列必须是平稳的,它才会围绕某个均值来回摆动。如果价差是非平稳的,那它可能一去不复返,你的策略就废了。

核心结论:配对交易的本质,就是找到两个非平稳的品种,它们的线性组合(价差)是平稳的。这个「线性组合平稳」就叫协整。

3.2 ADF检验原理:怎么判断平不平稳?

判断平稳性最常用的方法就是ADF检验(Augmented Dickey-Fuller Test)。名字听着唬人,其实原理不复杂。

先想想,一个序列如果非平稳,它通常有个单位根(Unit Root)。什么叫单位根?简单说就是序列的当前值很大程度上取决于上一期的值,而且这个依赖关系不会衰减。比如随机游走:y_t = y_{t-1} + ε_t,这就是典型的单位根过程。

ADF检验的核心思路就是:检验这个序列是否存在单位根

具体来说,它跑一个回归:

Δy_t = α + βt + γy_{t-1} + δ₁Δy_{t-1} + δ₂Δy_{t-2} + ... + ε_t

然后看γ这个系数。如果γ=0,说明存在单位根,序列非平稳。如果γ<0,说明没有单位根,序列平稳。

检验结果会给你一个p值。p值小于0.05,通常就认为序列是平稳的。大于0.05,就不能拒绝「存在单位根」的原假设。

避坑指南:我曾经遇到过p值刚好0.049的情况,差点就信了。后来多取了几天数据重新跑,p值变成了0.07。所以别太迷信0.05这个阈值,多取几个时间段验证一下更稳妥。

3.3 如何判断两个品种是否适合做配对?

好,现在到了关键环节。怎么判断两个品种能不能做配对?我一般走四步:

第一步:相关性初筛

先算一下两个品种的相关系数。我个人习惯要求相关系数绝对值在0.7以上。太低的话,后面协整检验大概率过不了。但注意,相关性高不代表协整,比如两个品种都跟大盘走,相关性很高,但价差可能不平稳。

第二步:单位根检验

分别对两个品种做ADF检验。如果两个都是平稳的,那直接做价差回归就行,不需要协整。但现实中,大多数金融时间序列都是非平稳的。如果两个都是非平稳的,那就可以进入下一步。

第三步:协整回归

用其中一个品种对另一个做线性回归:

y_t = α + βx_t + ε_t

这里的ε_t就是价差序列。然后对ε_t做ADF检验,看它是否平稳。

第四步:判断结果

如果ε_t的ADF检验p值小于0.05,说明价差平稳,两个品种协整,可以做配对交易。否则,换品种或者换参数再试。

注意:协整关系可能会随时间变化。我建议每3-6个月重新检验一次,别一套参数用到底。我曾经就吃过这个亏,一个策略跑了半年突然失效,一查发现协整关系早就断了。

3.4 实战代码:用Python做协整检验

光说不练假把式。下面是我常用的协整检验代码,你直接拿去用:

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

def check_cointegration(price1, price2):
    """
    检查两个价格序列是否协整
    """
    # 第一步:分别做ADF检验
    adf1 = adfuller(price1.dropna())
    adf2 = adfuller(price2.dropna())
    
    print(f"品种1 ADF检验 p值: {adf1[1]:.4f}")
    print(f"品种2 ADF检验 p值: {adf2[1]:.4f}")
    
    # 第二步:协整回归
    X = sm.add_constant(price1)
    model = sm.OLS(price2, X).fit()
    residuals = model.resid
    
    # 第三步:对残差做ADF检验
    adf_resid = adfuller(residuals.dropna())
    print(f"残差 ADF检验 p值: {adf_resid[1]:.4f}")
    
    # 第四步:判断
    if adf_resid[1] < 0.05:
        print("✅ 两个品种协整,适合做配对交易")
        return True, model.params
    else:
        print("❌ 两个品种不协整,换个组合试试")
        return False, None

# 使用示例
# check_cointegration(price_a, price_b)

小技巧:我习惯在跑协整检验前,先把两个价格序列标准化(减去均值除以标准差)。这样回归出来的系数更有可比性,而且能避免量纲差异带来的问题。

3.5 知识体系总览

说了这么多,我画了张图帮你理清思路。这张图把协整检验的整个流程串起来了:

协整检验知识体系 两个品种价格序列 第一步:相关性初筛(|r| > 0.7) 第二步:分别做ADF单位根检验 都非平稳 → 继续 有平稳的 → 不适合配对 第三步:协整回归,提取残差 第四步:残差ADF检验 p < 0.05 → 协整 p ≥ 0.05 → 不协整

这张图把整个流程串起来了。你从两个品种的价格序列开始,先做相关性初筛,然后分别做ADF检验,确认两个都是非平稳的之后,做协整回归提取残差,最后对残差做ADF检验。如果残差平稳,恭喜你,找到了一对可以交易的品种。

嗯,协整检验这块内容就这些。说白了就是一套标准流程,多跑几遍就熟了。我刚开始做的时候也经常搞混,后来写了个自动化脚本,每天跑一遍全市场的品种对,省了不少功夫。

专注资料整理