halo 的技术博客

返回

先说结论:两条价格序列各自都是随机游走(单位根过程),教科书说”非平稳序列要先差分再建模”。但如果这两条序列是协整的——存在某个线性组合是平稳的——差分建模会把它们之间最值钱的信息直接扔掉:长期均衡关系。VECM(Vector Error Correction Model)的做法是在差分方程里加回一个误差修正项 α(y1,t1βy2,t1)\alpha \cdot (y_{1,t-1} - \beta y_{2,t-1}),让”偏离均衡多远”本身成为把价格拉回来的力。 合成协整对实测:Engle-Granger 两步法估出协整系数 1.232(真值 1.25),残差 ADF 统计量 −7.24 远超临界值;误差修正系数 α₁=−0.061、α₂=+0.062,方向相反、双双显著(|t|=3.8),价差半衰期 4.8 天。配对交易样本外 500 天:净费后 Sharpe 2.08,最大回撤 3.5%,全程只动手 19 次。但必须先泼冷水:合成数据里协整关系永不破裂,真实市场里它会死——而且死的时候不会提前打招呼。

协整对:各自游走,却被同一条随机趋势拴着

一、协整是什么:两个醉汉和一条狗绳#

经典比喻:两个醉汉各自随机游走,但他们之间拴着一条狗绳。任何一个人的位置都不可预测(单位根),但两人的距离是有界的、会回归的(平稳)。

数学上,若 y1,y2y_1, y_2 都是 I(1)(一阶单整,差分后平稳),且存在 β\beta 使得 y1βy2y_1 - \beta y_2 是 I(0)(平稳),则称两者协整。本文的合成数据把这个结构写得很明白:

import numpy as np
rng = np.random.default_rng(7)

T = 1250  # 约5年日频
w = np.cumsum(rng.standard_normal(T) * 0.012) + 4.0  # 共同随机趋势(狗绳的主人)
u1 = np.zeros(T); u2 = np.zeros(T)
for t in range(1, T):
    u1[t] = 0.92 * u1[t-1] + rng.standard_normal() * 0.010  # 各自的平稳偏离
    u2[t] = 0.85 * u2[t-1] + rng.standard_normal() * 0.012

lp1 = w + u1              # log价格1: 载荷 1.0
lp2 = 0.8 * w + u2 + 1.0  # log价格2: 载荷 0.8
python

两条 log 价格共享同一个随机趋势 ww,载荷分别是 1 和 0.8。于是 lp11.25lp2lp_1 - 1.25 \cdot lp_2ww 完全消掉,剩下的 u11.25u2u_1 - 1.25 u_2 是平稳的——协整向量是 (1,1.25)(1, -1.25)。这就是”统计套利”的物理基础:你交易的不是价格,是那条被拉长的狗绳。

二、Engle-Granger 两步法:先回归,再验尸#

第一步,用前 750 天(训练段)做水平回归:

split = 750
X = np.column_stack([np.ones(split), lp2[:split]])
alpha_hat, beta_hat = np.linalg.lstsq(X, lp1[:split], rcond=None)[0]
spread_in = lp1[:split] - (alpha_hat + beta_hat * lp2[:split])
# 结果: lp1 = -1.175 + 1.232 * lp2  (真值斜率 1.25)
python

第二步,检验残差是否平稳。这一步是生死线——任何两条趋势序列做回归都能得到高 R²,但只有残差平稳才是协整,否则就是伪回归。手写 ADF 检验:

def adf_stat(x, lags=1):
    dx = np.diff(x)
    xl = x[lags:-1]
    Xm = np.column_stack([np.ones(len(xl)), xl, dx[:-lags]])
    y = dx[lags:]
    b = np.linalg.lstsq(Xm, y, rcond=None)[0]
    resid = y - Xm @ b
    s2 = resid @ resid / (len(y) - Xm.shape[1])
    se = np.sqrt(s2 * np.linalg.inv(Xm.T @ Xm)[1, 1])
    return b[1] / se   # 单位根 t 统计量
python

协整残差的 ADF = −7.24,远超 Engle-Granger 5% 临界值 −3.34(注意:EG 残差检验的临界值比普通 ADF 更严,因为 β 是估出来的),干脆利落地拒绝”无协整”。

对照组是本文最想让你记住的图:两条独立的带漂移随机游走互相回归,R² 高达 0.62——看起来”高度相关”——但残差 ADF 只有 −1.60,根本不平稳。

高 R² 不等于协整 + 误差修正系数

左图绿线(真协整残差)在零轴附近反复穿越,红线(伪回归残差)一去不回头。用相关系数或 R² 找配对,是配对交易散户亏钱的第一大原因:相关性度量的是短期共动,协整度量的是长期绑定,两者可以完全脱钩。

三、VECM:把偏离写成拉力#

确认协整后,第二步把动态写成误差修正形式:

Δy1,t=c1+α1(y1,t1α^β^y2,t1)误差修正项 ECT+γ11Δy1,t1+γ12Δy2,t1+ε1,t\Delta y_{1,t} = c_1 + \alpha_1 \underbrace{(y_{1,t-1} - \hat\alpha - \hat\beta y_{2,t-1})}_{\text{误差修正项 ECT}} + \gamma_{11}\Delta y_{1,t-1} + \gamma_{12}\Delta y_{2,t-1} + \varepsilon_{1,t}

Δy2\Delta y_2 方程同理。α 是调整速度:ECT 为正(资产1 相对贵了)时,α₁<0 会把 Δy1\Delta y_1 往下拽,α₂>0 会把 Δy2\Delta y_2 往上抬——两腿对向收敛。估计结果:

系数估计值t 统计量解读
α₁−0.0605−3.8资产1 每天修正偏离的 6%
α₂+0.0622+3.8资产2 反向修正 6.2%

两个 α 都显著且方向正确。这里有一个真实市场中非常有用的诊断:如果 α₁ 显著而 α₂ 不显著,说明收敛全靠资产1 完成,资产2 是”领导者”——配对交易时应该意识到你的均值回归敞口集中在跟随者那条腿上。价差 AR(1) 系数 0.866,对应半衰期 4.8 天:偏离一半的距离平均 5 天修复,这个数字直接决定策略的资金周转率和止损耐心。

用 statsmodels 的 Johansen 迹检验交叉验证:迹统计量 54.87 >> 5% 临界值 15.49(拒绝”0 个协整关系”),第二个统计量 2.11 < 3.84(接受”至多 1 个”)——恰好 1 条协整关系,标准化协整向量 (1, −1.24),与 EG 结果和真值一致。两变量用 EG 够了;三个以上变量必须上 Johansen,因为协整关系可能不止一条,EG 只能找到其中某一条的投影。

四、配对交易回测:z-score 开平仓状态机#

信号规则:价差 z-score(用训练段均值方差标准化)超过 ±2 开仓做收敛,回到 ±0.5 内平仓,突破 ±4 视为协整破裂止损。t 日确认信号,t+1 日成交:

mu_in, sd_in = spread_in.mean(), spread_in.std()   # 只用训练段统计量
z = (ect - mu_in) / sd_in

state = 0
for t in range(split, T - 1):
    if state == 0:
        if z[t] > 2.0:  state = -1   # 价差过高: 空1多2
        elif z[t] < -2.0: state = 1  # 价差过低: 多1空2
    else:
        if abs(z[t]) < 0.5: state = 0   # 收敛平仓
        elif abs(z[t]) > 4.0: state = 0 # 协整破裂止损
    pos[t + 1] = state   # t 确认, t+1 生效

spread_ret = pos[1:] * (r1 - beta_hat * r2) / (1 + beta_hat)  # 两腿名义额归一
python

样本外 500 天结果(单边 5bp 交易成本):

口径总收益Sharpe最大回撤动作次数
毛收益+31.9%2.223.2%19
净收益+29.4%2.083.5%19

样本外 500 天配对交易

几个值得注意的读法。第一,成本侵蚀很小(Sharpe 2.22→2.08),因为半衰期 4.8 天的价差对应低频交易——500 天只动手 19 次。协整策略天然是低换手策略,这是它和高频统计套利的本质区别。第二,净值曲线是典型的”楼梯形”:持仓期赚取收敛收益,空仓期走平。橙色持仓区间显示大部分时间其实在场外等待——配对交易的收益密度集中在偏离发生后的几天里,其余时间的耐心是策略的一部分。第三,回撤只有 3.5%,因为多空对冲消掉了共同趋势 ww 的方向性风险,剩下的敞口只有价差本身。

五、诚实的翻车与边界#

1. 合成数据里协整永不破裂,真实市场里它会死。 这是本文和现实之间最大的鸿沟。真实协整对的死法有很多种:招商银行/平安银行这类同行业对会因为基本面分化渐行渐远;可口可乐/百事的经典协整在 2000 年代逐渐失效;LTCM 的故事本质上就是”协整关系在你加满杠杆之后破裂”。z>4 止损能挡住急性破裂,挡不住缓慢漂移型破裂——价差从新的均衡水平看永远回不到旧均值,但 z-score 一直在 2~3 之间徘徊,让你反复开仓反复小亏。工程上的缓解是滚动重估 β 和滚动 ADF 监控:一旦残差平稳性检验开始失败,无条件退出。

2. EG 两步法把 β 的估计误差全部灌进价差。 第一步 OLS 估出的 β̂=1.232 不是真值 1.25,这 1.4% 的误差意味着你构造的”价差”里还残留着一小截没消干净的随机趋势 0.018wt0.018 \cdot w_t。样本内看不出来,样本外时间够长就会显形为价差的缓慢漂移。样本越短、两腿波动比越极端,这个问题越严重。Johansen 的极大似然估计在统计性质上更好,但也只是缓解不是根治。

3. 半衰期不是常数。 本实验的 AR 结构固定,所以 4.8 天的半衰期全程成立。真实价差的均值回归速度随市场状态剧烈变化——平静期 5 天,危机期可能 50 天(流动性撤退时没人来修复价差,2008 年和 2020 年 3 月的统计套利集体回撤都是这个机制)。用全样本估一个半衰期然后当常数用,是把策略的生死交给了最坏时期的资金承受力。

4. 本回测没有建模做空成本与保证金占用。 配对交易永远有一条空腿,A 股融券几乎不可行、港股部分标的券源紧张、美股 hard-to-borrow 名单的费率可以吃掉全部价差收益。落地时”能不能借到券、多少钱”往往比模型本身更决定成败。

六、什么时候该用 VECM#

适合: 有真实经济纽带的配对——同一公司的 A/H 股、股指期货与现货、同一产业链上下游商品(原油/汽油裂解价差)、ETF 与其成份篮子。这些对的协整有经济机制托底,不只是统计巧合。也适合宏观建模:消费与收入、汇率与利差这类理论上存在长期均衡的变量组。

不适合: 纯数据挖掘筛出来的配对——在 5000 只股票里两两做协整检验,5% 显著性水平下光靠运气就能”发现”60 多万对协整关系,其中绝大多数样本外即死。也不适合协整半衰期长于你的资金耐心的场景:半衰期 60 天的价差理论上也能做,但回撤深度和资金占用会让 Sharpe 毫无吸引力。

一句话总结:VECM 是少数把”长期均衡”这个经济学概念直接翻译成可交易信号的模型——误差修正项就是仓位方向,调整速度就是持仓周期,残差平稳性就是策略存活的体检指标。它的数学是七十年代的,但”先证明狗绳存在,再赌狗绳收紧”这个纪律,今天依然是统计套利的第一课。


本文实验代码基于 numpy 手写实现(EG 两步法 + ADF 检验 + 误差修正方程 + 状态机回测),Johansen 检验用 statsmodels 交叉验证,所有数字均为真实运行输出。文中回测为教学演示,不构成投资建议。

向量误差修正模型 VECM:把协整关系写成向长期均衡的拉力
https://blog.halo26812.eu.org/blog/vecm-cointegration
Author halo
Published at 2026年7月24日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨