4. 信号生成逻辑:Z-score阈值与开平仓规则
好,咱们进入正题。前面几章我们把配对关系算出来了,价差序列也构造好了。现在的问题是——什么时候进场?什么时候离场?
说白了,信号生成就是给交易系统装上一双眼睛。让它能识别出「机会来了」和「该走了」这两个关键时刻。
我个人习惯用Z-score来做这个判断。为什么?因为它简单、直观,而且经过大量实盘验证,效果相当稳定。
4.1 Z-score:把价差变成标准分数
先回忆一下Z-score的定义:
Z = (当前价差 - 价差均值) / 价差标准差
嗯,其实就是把价差序列标准化。Z-score告诉你当前价差偏离均值多少个标准差。比如Z=2,意味着当前价差比均值高了两个标准差。
我在项目中遇到过一个问题:直接用原始价差设阈值,不同时间段的阈值完全不一样。牛市里价差波动大,熊市里波动小。用Z-score一标准化,所有问题都解决了。
核心思想:Z-score把不同时间段的价差拉到同一个尺度上比较。阈值设置变得通用且可复用。
4.2 阈值设置:开仓与平仓的触发条件
阈值怎么设?我一般用±2作为开仓阈值,±0.5作为平仓阈值。当然这不是死规矩,你可以根据品种波动性调整。
| 信号类型 | Z-score范围 | 操作 |
|---|---|---|
| 开多信号 | Z ≤ -2 | 买入弱势股,卖出强势股 |
| 开空信号 | Z ≥ 2 | 买入强势股,卖出弱势股 |
| 平多信号 | Z ≥ -0.5 | 平掉多头仓位 |
| 平空信号 | Z ≤ 0.5 | 平掉空头仓位 |
你想想看,为什么开仓阈值设得比平仓阈值大?因为我们要确保价差确实偏离到了极端位置,这时候回归的概率才高。而平仓时,价差只要回到均值附近就可以走了,没必要等到完全归零。
我的经验:如果交易频率太高,可以适当提高开仓阈值到±2.5。如果信号太少,就降低到±1.8。这需要根据回测结果动态调整。
4.3 开仓规则:什么时候进场
开仓规则其实就两条:
- Z-score突破阈值:比如Z从-1.5跌到-2.1,触发开多信号
- 确认信号:我个人习惯加一个确认条件——突破后至少维持一个周期,防止假突破
举个例子:
def generate_entry_signal(z_score, threshold=2.0):
"""
生成开仓信号
返回: 1=开多, -1=开空, 0=无信号
"""
if z_score <= -threshold:
return 1 # 开多:价差过低,预期回归
elif z_score >= threshold:
return -1 # 开空:价差过高,预期回归
else:
return 0
代码很简单对吧?但实际交易中,我还会加一个「冷却期」——开仓后至少等5个周期才能再次开仓。为什么?因为价差可能在阈值附近来回震荡,频繁开仓会亏死手续费。
注意:千万不要在Z-score刚突破阈值时就全仓杀入。我曾经吃过这个亏,价差突破后继续往极端方向跑,结果被套了好几天。建议分批建仓,或者等一个回调确认。
4.4 平仓规则:什么时候离场
平仓比开仓更重要。为什么?因为开仓决定你赚不赚钱,平仓决定你赚多少。
我常用的平仓规则有三种:
- 均值回归平仓:Z-score回到±0.5以内,说明价差已经回归
- 止损平仓:Z-score继续往极端方向跑,比如从2跑到3,说明配对关系可能失效了
- 时间平仓:持仓超过N个周期,强制平仓。防止死扛
def generate_exit_signal(z_score, position, stop_loss=3.0, mean_revert=0.5):
"""
生成平仓信号
position: 当前持仓方向 (1=多头, -1=空头, 0=空仓)
"""
if position == 1: # 持有多头
if z_score >= -mean_revert:
return 1 # 均值回归平仓
elif z_score <= -stop_loss:
return 1 # 止损平仓
elif position == -1: # 持有空头
if z_score <= mean_revert:
return -1 # 均值回归平仓
elif z_score >= stop_loss:
return -1 # 止损平仓
return 0 # 不平仓
嗯,这里要注意:止损阈值一定要比开仓阈值大。比如开仓用±2,止损用±3。留出足够的缓冲空间,避免被正常波动震出去。
4.5 完整的信号生成流程
把上面这些整合起来,就是一个完整的信号生成系统。我画了一张流程图,帮你理清逻辑:
4.6 实战中的避坑指南
最后分享几个我踩过的坑:
- 窗口期选择:计算Z-score用的滚动窗口不能太短也不能太长。太短(比如20期)信号太多,假信号也多。太长(比如200期)反应太慢。我一般用60期,也就是过去60个交易日的价差数据。
- 极端行情处理:2015年股灾时,很多配对关系瞬间崩溃。Z-score直接飙到10以上。这时候千万别按正常逻辑开仓,先暂停交易,等市场稳定再说。
- 手续费影响:高频交易的手续费是隐形杀手。我建议在回测时把手续费算进去,如果信号频率太高,适当降低阈值或者增加确认条件。
一个小技巧:可以在Z-score基础上加一个「动量过滤器」。比如只有当Z-score的绝对值在增加(即价差正在加速偏离)时才开仓。这样能过滤掉很多震荡行情中的假信号。
好了,信号生成逻辑就讲到这里。记住一句话:好的信号系统,开仓要谨慎,平仓要果断。下一章我们聊聊如何用Python实现这个系统的回测框架。
公众号:蓝海资料掘金营,微信deep3321