Python Pandas:向量化方式清洗金融买卖交易信号
最优向量化实现方案
要实现符合要求的交易信号过滤,完全可以用Pandas的向量化操作完成,全程无需循环,效率拉满,步骤如下:
核心逻辑拆解
- 先处理冲突信号:同一行同时出现买入和卖出信号时,直接将两者置为0(这种信号本身矛盾,无实际交易意义)
- 计算实时持仓状态:通过信号的累积变化推导持仓(空仓=0,持仓=1)
- 过滤无效重复信号:根据持仓状态,持仓时屏蔽后续买入信号,空仓时屏蔽后续卖出信号
完整代码实现
import pandas as pd # 原始数据 df = pd.DataFrame( { "buy_signal": [1, 1, 1, 1, 0, 0, 1, 1, 1, 0], "sell_signal": [0, 0, 1, 1, 1, 0, 0, 0, 1, 0], } ) # 1. 复制数据并处理同时存在买卖信号的冲突行 df_clean = df.copy() conflict_mask = (df_clean['buy_signal'] == 1) & (df_clean['sell_signal'] == 1) df_clean.loc[conflict_mask, ['buy_signal', 'sell_signal']] = 0 # 2. 计算持仓状态:买入+1,卖出-1,累积后限制在0-1区间(保证只有空仓/持仓两种状态) position = (df_clean['buy_signal'] - df_clean['sell_signal']).cumsum().clip(0, 1) # 3. 根据前一期持仓状态过滤无效信号: # 前一期持仓时,当前买入信号无效;前一期空仓时,当前卖出信号无效 df_clean['buy_signal'] = df_clean['buy_signal'].where(position.shift(fill_value=0) == 0, 0) df_clean['sell_signal'] = df_clean['sell_signal'].where(position.shift(fill_value=0) == 1, 0) print(df_clean)
代码说明
- 冲突信号处理:用布尔掩码定位同时有买卖信号的行,直接批量赋值为0
- 持仓计算:通过
buy_signal - sell_signal得到每一行的持仓变化,cumsum()累积得到持仓波动,clip(0,1)确保持仓状态只能是0或1(避免出现负数持仓或多次买入导致的持仓大于1) - 信号过滤:用
position.shift(fill_value=0)获取上一期的持仓状态,结合where方法批量将无效信号置为0,fill_value=0保证第一行的初始持仓为空仓
运行后输出结果完全符合期望:
buy_signal sell_signal 0 1 0 1 0 0 2 0 1 3 0 0 4 0 0 5 0 0 6 1 0 7 0 0 8 0 1 9 0 0
内容的提问来源于stack exchange,提问作者Chris Cappel
相关产品推荐
相关产品推荐

