如何在Pandas DataFrame中移除重复交易信号,保留初始有效信号?
清理Pandas交易信号中的无效重复信号
针对交易策略回测中出现的两类无效重复信号(连续同方向信号、持仓状态下的同方向信号),可以通过跟踪持仓状态的方式过滤无效信号,只保留初始有效开/平仓信号。
样本数据构造
先复现测试数据集:
import pandas as pd # 构造带无效信号的样本数据 data = { 'datetime': ['2023-01-08 02:00', '2023-01-08 03:00', '2023-01-08 04:00', '2023-01-09 05:00', '2023-01-09 08:00', '2023-01-09 11:00', '2023-01-09 14:00', '2023-01-10 09:00'], 'position_long': [0, -1, -1, 1, 1, 1, -1, -1] } df = pd.DataFrame(data) df['datetime'] = pd.to_datetime(df['datetime']) df.set_index('datetime', inplace=True)
解决方案1:循环跟踪持仓状态(直观易理解)
通过遍历每一行信号,维护当前持仓状态,仅保留与持仓状态不同的非0信号:
current_position = 0 # 0代表空仓,1代表多仓,-1代表空仓 cleaned_signals = [] for _, row in df.iterrows(): signal = row['position_long'] # 仅当信号非0且与当前持仓方向不同时,保留信号并更新持仓 if signal != 0 and signal != current_position: cleaned_signals.append(signal) current_position = signal else: cleaned_signals.append(0) # 将清理后的信号添加到DataFrame df['cleaned_position_long'] = cleaned_signals
解决方案2:向量化实现(高效处理大数据集)
避免循环,用Pandas内置方法实现,适合处理大规模回测数据:
# 标记有效信号点:信号非0且与上一行信号不同 df['is_valid_signal'] = df['position_long'].ne(df['position_long'].shift()) & df['position_long'].ne(0) # 计算当前持仓状态:有效信号的累积和(每次有效信号都是方向切换,累积和即为当前持仓) df['current_position'] = df['position_long'].where(df['is_valid_signal'], 0).cumsum() # 提取清理后的信号:仅保留有效信号点的数值,其余设为0 df['cleaned_position_long_vec'] = df['position_long'].where(df['is_valid_signal'], 0)
期望输出
运行上述代码后,清理后的信号列会得到符合要求的结果:
position_long cleaned_position_long is_valid_signal current_position cleaned_position_long_vec datetime 2023-01-08 02:00 0 0 False 0 0 2023-01-08 03:00 -1 -1 True -1 -1 2023-01-08 04:00 -1 0 False -1 0 2023-01-09 05:00 1 1 True 1 1 2023-01-09 08:00 1 0 False 1 0 2023-01-09 11:00 1 0 False 1 0 2023-01-09 14:00 -1 -1 True -1 -1 2023-01-10 09:00 -1 0 False -1 0
两种方案的核心逻辑一致:仅保留改变当前持仓状态的非0信号,自动过滤连续同方向信号和持仓下的重复信号。
内容的提问来源于stack exchange,提问作者Chung Joshua
相关产品推荐
相关产品推荐

