价差计算与标准化:从原始数据到交易信号
做配对交易,最核心的一步是什么?
我个人觉得,就是把两个股票的价格关系,变成一个可以量化、可以比较的数值。说白了,就是价差计算与标准化。这一步做不好,后面所有策略都是空中楼阁。
一、价差公式:配对交易的基础
先聊聊最基础的价差。我们通常说的价差,不是简单地把A股价格减去B股价格。为什么?因为两个股票的价格绝对值可能差很多,比如茅台和五粮液,直接相减没有意义。
我常用的价差公式有两种:
- 简单价差:Price_A - Price_B × hedge_ratio
- 对数价差:ln(Price_A) - ln(Price_B) × hedge_ratio
我个人更偏爱对数价差。原因很简单——对数处理后的数据更接近正态分布,而且能消除价格尺度的影响。我在2019年做美股ETF配对时,用对数价差比简单价差信号稳定了至少30%。
核心公式:
价差 = ln(P_A) - β × ln(P_B)
其中β是协整系数,也就是对冲比率
二、Z-Score计算:把价差变成标准分数
有了价差序列,接下来要做什么?标准化。
你想想看,价差的绝对值会随着时间变化,今天价差是0.5,明天可能是0.8,这能直接比较吗?不能。所以我们需要Z-Score。
Z-Score的计算公式很简单:
Z = (当前价差 - 价差均值) / 价差标准差
嗯,这里要注意:Z-Score告诉我们当前价差偏离均值多少个标准差。通常我们设定±2作为开仓阈值,±0.5作为平仓阈值。
我曾经犯过一个错误——直接用全部历史数据计算均值和标准差。结果呢?2015年股灾期间,价差剧烈波动,Z-Score完全失效。后来我才意识到,滚动窗口才是正确的做法。
我的经验:Z-Score阈值不要死板地用±2。对于波动率高的品种,可以放宽到±2.5;对于流动性差的品种,收紧到±1.5更安全。
三、滚动窗口参数设置:动态调整的艺术
滚动窗口,说白了就是用一个固定长度的滑动时间窗口,实时计算均值和标准差。窗口大小怎么选?这是门学问。
| 窗口大小 | 特点 | 适用场景 |
|---|---|---|
| 20个交易日 | 反应快,噪音多 | 短线高频配对 |
| 60个交易日 | 平衡型 | 大多数股票配对 |
| 120个交易日 | 稳定,反应慢 | 长期均值回归策略 |
我个人习惯用60个交易日作为默认值。为什么?因为3个月左右的数据既能捕捉到中期趋势,又不会对短期噪音过度敏感。
但这里有个坑——如果市场结构发生变化,比如股票分红、拆股,或者行业政策突变,滚动窗口需要重置。我曾经在2020年做能源股配对时,没注意到一家公司进行了重大资产重组,结果价差序列完全变了,窗口数据全是垃圾。
避坑指南:
- 窗口长度不要小于30个交易日,否则统计意义不足
- 遇到除权除息日,必须复权处理
- 每季度检查一次协整关系是否仍然成立
四、完整流程:从原始数据到交易信号
让我把整个流程串起来,画一张图你就明白了。
五、代码实现:Python实战
光说不练假把式。我给你看一段我实际项目中用的代码:
import numpy as np
import pandas as pd
from statsmodels.tsa.stattools import coint
def calculate_zscore(spread, window=60):
"""
计算滚动Z-Score
spread: 价差序列
window: 滚动窗口大小
"""
rolling_mean = spread.rolling(window=window).mean()
rolling_std = spread.rolling(window=window).std()
zscore = (spread - rolling_mean) / rolling_std
return zscore
def generate_signals(zscore, entry_threshold=2.0, exit_threshold=0.5):
"""
生成交易信号
返回: 1=做多价差, -1=做空价差, 0=平仓
"""
signals = pd.Series(index=zscore.index, data=0)
# 开仓条件
signals[zscore > entry_threshold] = -1 # 做空价差
signals[zscore < -entry_threshold] = 1 # 做多价差
# 平仓条件
signals[abs(zscore) < exit_threshold] = 0
return signals
避坑提醒:
我曾经在回测时直接用全部数据计算Z-Score,结果回测曲线漂亮得不行。实盘一跑,直接亏成狗。为什么?因为回测时用了未来数据!记住:滚动窗口必须只用历史数据,不能用未来数据计算均值和标准差。
六、参数调优:没有银弹
窗口大小、阈值设置,这些参数有没有最优值?
我的答案是:没有。不同品种、不同市场环境,最优参数都不一样。我一般这样做:
- 先用60日窗口+±2阈值作为基准
- 然后做参数扫描,看哪个组合的夏普比率最高
- 最后用样本外数据验证
嗯,这里要提醒一句:参数优化过度是很多新手容易犯的错。你想想看,如果回测时参数调得刚刚好,实盘时市场一变,可能就失效了。我一般会留20%的裕度,比如回测最优阈值是1.8,我实盘用2.0。
我的经验总结:
价差计算与标准化,说白了就是三个字——稳、准、活。稳:窗口要足够大,统计意义才强;准:Z-Score要实时更新,不能滞后;活:参数要动态调整,不能死板。
好了,这一章的内容就到这里。记住:没有完美的参数,只有不断迭代的策略。做量化交易,本质上就是在不确定性中寻找确定性。