价差计算与标准化:从原始数据到交易信号
做价差交易这么多年,我最大的体会是:价差本身不是信号,标准化的价差才是。今天咱们就聊聊这个核心环节——怎么把两个品种的价格变成可交易的信号。
一、价差的计算方法
价差,说白了就是两个相关品种的价格差。但这里有个坑——不是所有价差都直接用减法。
1. 简单价差(价格差)
最直观的方法:
价差 = 品种A价格 - 品种B价格
举个例子,我做过螺纹钢和热卷的配对交易:
价差 = RB2401 - HC2401
嗯,这里要注意:两个品种的合约单位必须一致。螺纹钢和热卷都是10吨/手,直接减没问题。但如果你做的是股指期货和ETF,就得先换算成同一量纲。
2. 对数价差(比率价差)
我个人更常用的是对数价差:
价差 = ln(品种A价格) - ln(品种B价格)
为什么用对数?两个原因:
- 消除量纲影响——价格高的品种不会天然占主导
- 近似收益率——对数差≈收益率差,统计性质更好
我在做股指期货期现套利时,就吃过简单价差的亏。当时IF和IC价格差好几千,简单价差波动大得吓人,换成对数价差后,信号立马清晰了。
3. 回归残差(统计套利)
如果两个品种的相关性不是1:1,比如铜和铝,那就得用回归:
价差 = 品种A价格 - (α + β × 品种B价格)
这里的β是协整系数,α是截距。我建议用滚动窗口估计,窗口长度一般选60-120个交易日。
核心原则:价差计算没有银弹。简单价差适合同品种跨期,对数价差适合跨品种,回归残差适合相关性不稳定的组合。
二、Z-Score标准化
价差算出来了,但你能直接用它做交易吗?不能。为什么?因为价差的均值和标准差会漂移。
Z-Score就是解决这个问题的:
Z = (当前价差 - 价差均值) / 价差标准差
标准化后的Z值,告诉你当前价差偏离均值多少个标准差。这玩意儿才是真正的交易信号。
1. 滚动窗口计算
我习惯用滚动窗口,而不是全样本:
def calc_zscore(spread, window=60):
mean = spread.rolling(window).mean()
std = spread.rolling(window).std()
zscore = (spread - mean) / std
return zscore
窗口选多大?我踩过坑:
- 太短(<20):信号太敏感,假突破多
- 太长(>120):反应迟钝,错过机会
- 我常用的:30-60个交易日,具体看品种波动特性
2. 阈值设定
Z-Score出来了,怎么用?设定阈值:
| Z值范围 | 信号含义 | 操作建议 |
|---|---|---|
| Z > 2.0 | 价差过高 | 做空价差(卖A买B) |
| Z < -2.0 | 价差过低 | 做多价差(买A卖B) |
| |Z| < 0.5 | 价差正常 | 观望或平仓 |
我的经验:阈值别死板用2.0。波动大的品种用2.5,波动小的用1.8。我一般先跑回测,看哪个阈值夏普比率最高。
三、价差通道构建
通道,就是把Z-Score可视化。说白了,就是画几条线告诉你什么时候该动手。
1. 布林带通道
最经典的通道:
上轨 = 均值 + K × 标准差
中轨 = 均值
下轨 = 均值 - K × 标准差
K值我一般取2.0-2.5。你想想看,如果价差突破上轨,说明偏离太远,大概率会回归。
2. 百分比通道
有时候布林带不够直观,我改用百分比:
百分位 = (当前价差 - 历史最低) / (历史最高 - 历史最低)
百分位在0-1之间,超过0.9算高位,低于0.1算低位。这个方法的好处是——不受极端值影响。
3. 动态通道
市场在变,通道也得变。我做过一个自适应通道:
# 用ATR动态调整通道宽度
atr = 计算ATR(价差, 14)
上轨 = 均值 + atr × 倍数
下轨 = 均值 - atr × 倍数
波动大的时候通道自动变宽,减少假信号。波动小的时候通道收窄,抓住机会。
避坑指南:我曾经在2020年3月用固定通道做原油跨期套利,结果波动率暴增,通道完全失效。从那以后,我所有策略都加了波动率自适应机制。
四、实战中的注意事项
说了这么多,最后分享几个实战要点:
- 数据频率要匹配——别用日线算价差,用分钟线交易,那肯定出问题
- 注意跳空缺口——隔夜跳空会导致价差突变,我一般开盘后等15分钟再算
- 定期重估参数——协整关系会变,我每月重新跑一次协整检验
- 别过度优化——窗口和阈值调来调去,最后过拟合了,实盘一塌糊涂
价差计算和标准化,说白了就是给原始数据「洗澡」。洗得干净,信号才可靠。我见过太多人直接拿原始价差做交易,结果被趋势行情打得鼻青脸肿。
记住一句话:标准化的价差才是信号,原始价差只是噪音。
公众号:蓝海资料掘金营,微信deep3321