4. 套利信号生成:布林带法、Z-score法、固定阈值法、动态阈值法
信号生成,说白了就是回答一个问题:现在该不该进场?
我做跨期套利这些年,见过太多人把精力花在策略逻辑上,结果信号生成这块随便写个固定阈值就上线了。嗯,最后亏得挺惨。今天我把四种主流方法掰开揉碎讲清楚,每种方法我都踩过坑,希望能帮你少走弯路。
4.1 布林带法(Bollinger Bands)
布林带法是我个人最常用的方法之一。它基于一个朴素的想法:价差不会永远偏离均值。
核心公式很简单:
上轨 = 均值 + K × 标准差
中轨 = 均值
下轨 = 均值 - K × 标准差
当价差突破上轨,做空价差(卖近买远)。突破下轨,做多价差(买近卖远)。
参数怎么设?
我一般用20期窗口,K值取2。但这不是死的。我在项目中遇到过螺纹钢和热卷的套利,波动特别大,K值调到2.5才勉强不被假突破洗出去。
代码实现也不复杂:
def bollinger_signal(spread, window=20, k=2):
mean = spread.rolling(window).mean()
std = spread.rolling(window).std()
upper = mean + k * std
lower = mean - k * std
signal = 0
if spread.iloc[-1] > upper.iloc[-1]:
signal = -1 # 做空价差
elif spread.iloc[-1] < lower.iloc[-1]:
signal = 1 # 做多价差
return signal
4.2 Z-score法
Z-score法其实是布林带的标准化版本。它把价差转换成标准正态分布下的位置。
公式:
Z = (当前价差 - 均值) / 标准差
Z-score的好处是直观。|Z| > 2 就认为价差偏离过大,可以进场。|Z| < 0.5 就平仓。
为什么我喜欢Z-score?
因为它能跨品种比较。你想想看,螺纹钢和热卷的价差可能是50块,豆粕和菜粕的价差可能是200块。用布林带你得分别调参数,但Z-score统一用2倍标准差,省事多了。
def zscore_signal(spread, window=20, entry_threshold=2.0, exit_threshold=0.5):
mean = spread.rolling(window).mean()
std = spread.rolling(window).std()
z = (spread - mean) / std
current_z = z.iloc[-1]
if current_z > entry_threshold:
return -1 # 做空
elif current_z < -entry_threshold:
return 1 # 做多
elif abs(current_z) < exit_threshold:
return 0 # 平仓
return None # 持仓不变
4.3 固定阈值法
固定阈值法,说白了就是拍脑袋定两个数。比如价差超过100块就做空,低于-50块就做多。
这种方法简单粗暴,适合刚起步的时候用。但我建议别长期依赖它。
为什么?
市场在变。去年有效的阈值,今年可能完全失效。我记得2020年做甲醇和乙二醇套利,固定阈值设的80块,前半年赚得挺好。下半年波动率翻倍,80块天天被突破,来回止损亏了20%。
| 方法 | 优点 | 缺点 |
|---|---|---|
| 固定阈值 | 简单、执行快 | 不适应市场变化 |
| 布林带 | 自适应波动率 | 参数敏感 |
| Z-score | 跨品种可比 | 正态假设不牢 |
| 动态阈值 | 最灵活 | 实现复杂 |
4.4 动态阈值法
动态阈值法是我现在的主力方法。它根据市场状态实时调整阈值。
核心思路:
- 用滚动窗口计算均值和标准差
- 根据波动率大小动态调整K值
- 波动率大时放宽阈值,波动率小时收紧阈值
具体实现:
def dynamic_threshold(spread, window=20, base_k=2.0):
mean = spread.rolling(window).mean()
std = spread.rolling(window).std()
# 计算波动率变化
vol_ratio = std / std.rolling(window*2).mean()
# 动态调整K值
k = base_k * (1 + 0.5 * (vol_ratio - 1))
upper = mean + k * std
lower = mean - k * std
current = spread.iloc[-1]
if current > upper.iloc[-1]:
return -1
elif current < lower.iloc[-1]:
return 1
return 0
四种方法对比总结
我做个简单的对比,方便你选型:
- 刚入门:用固定阈值法,快速跑通流程
- 追求稳健:用布林带法,参数调好后很稳定
- 多品种交易:用Z-score法,统一标准省心
- 追求极致:用动态阈值法,适应各种市场环境
我个人建议,先从布林带或Z-score入手。跑顺了再升级到动态阈值。别一上来就搞复杂的,容易把自己绕晕。
嗯,信号生成这块就讲到这里。每种方法都有它的适用场景,关键是你得理解背后的逻辑,而不是死记硬背参数。下一节我们会聊到信号过滤和组合,到时候再细说。