基于滚动条件生成配对交易信号列:回测实现技术问询
基于Z值的配对交易信号向量化生成方案
核心思路
不用逐行循环,而是利用pandas的布尔索引和累积状态追踪,实现无循环的信号生成。关键是在DataFrame中追踪当前持仓状态(空仓、多头、空头),确保同一时间只持有一笔头寸,平仓后才能开新仓。
分步实现
1. 定义条件掩码
先为所有入场、离场条件创建布尔掩码:
import pandas as pd # 假设你的DataFrame名为df,包含'z_score'列 df['long_entry'] = df['z_score'] < -2 # 多头入场条件:Z值小于-2 df['long_exit'] = df['z_score'] >= -0.1 # 多头离场条件:Z值大于等于-0.1 df['short_entry'] = df['z_score'] > 2 # 空头入场条件:Z值大于2 df['short_exit'] = df['z_score'] <= 0.1 # 空头离场条件:Z值小于等于0.1
2. 追踪持仓状态并生成信号
通过位移(shift)和累积求和(cumsum)来追踪持仓状态,避免循环:
# 初始化持仓状态序列:0=空仓,1=多头,-1=空头 position = pd.Series(0, index=df.index) # 筛选有效交易触发条件(必须满足当前持仓状态) long_entry_valid = (position.shift(1) == 0) & df['long_entry'] long_exit_valid = (position.shift(1) == 1) & df['long_exit'] short_entry_valid = (position.shift(1) == 0) & df['short_entry'] short_exit_valid = (position.shift(1) == -1) & df['short_exit'] # 计算持仓状态的变化量:多头入场+1,多头离场-1;空头入场-1,空头离场+1 position_changes = long_entry_valid.astype(int) - long_exit_valid.astype(int) - short_entry_valid.astype(int) + short_exit_valid.astype(int) # 累积求和得到实时持仓状态 position = position_changes.cumsum() # 生成最终信号列 df['signal'] = '' df.loc[long_entry_valid, 'signal'] = '多头入场' df.loc[long_exit_valid, 'signal'] = '多头离场' df.loc[short_entry_valid, 'signal'] = '空头入场' df.loc[short_exit_valid, 'signal'] = '空头离场'
3. 验证信号有效性
检查是否存在未平仓就开新仓的错误信号:
# 检查是否有连续入场信号(未平仓开新仓) invalid_signals = (df['signal'].shift(1).isin(['多头入场', '空头入场'])) & (df['signal'].isin(['多头入场', '空头入场'])) assert not invalid_signals.any(), "存在无效信号:未平仓即开新仓"
最终结果
signal列只会标注有效交易事件:'多头入场'、'多头离场'、'空头入场'、'空头离场',非交易时段为空字符串。
注意事项
- 确保DataFrame已按时间顺序排序,因为逻辑依赖于时序连续性。
- 该方案完全基于向量化操作,比循环实现效率更高,尤其适合大规模数据回测。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

