基于滚动条件创建止损列:空单15%止损回测实现
实现空单15%止损回测的Pandas优化方案
不用逐行循环,我们可以利用Pandas的分组、矢量化操作高效实现这个逻辑,步骤如下:
- 标记交易分组:将
Entry Signal转为布尔值,通过累加生成每个交易周期的分组ID,再向前填充确保同一周期内的行属于同一组。 - 获取每组入场价:对每个分组提取入场行的价格(即分组内第一行的
Price),广播到组内所有行。 - 识别止损触发点:计算每行价格相对入场价的涨幅,找到每个分组中第一个触发涨幅超过15%的位置,标记为
Exit,其余位置设为NaN。
代码实现
首先构造示例DataFrame:
import pandas as pd data = { 'Date': ['2024-01-18', '2024-01-19', '2024-01-22', '2024-01-23', '2024-01-24', '2024-03-07', '2024-03-08', '2024-03-11'], 'Price': [3595.0, 3280.0, 3505.0, 3945.0, 4075.0, 10270.0, 8120.0, 14020.0], 'Entry Signal': [pd.NA, 'Entry', pd.NA, pd.NA, pd.NA, 'Entry', pd.NA, pd.NA] } df = pd.DataFrame(data) df['Date'] = pd.to_datetime(df['Date'])
然后执行核心逻辑:
# 1. 创建交易分组ID:Entry出现时累加,向前填充分组 df['group_id'] = (df['Entry Signal'] == 'Entry').cumsum() # 无Entry的前期分组设为NA,避免干扰后续计算 df['group_id'] = df['group_id'].mask(df['group_id'] == 0, pd.NA).ffill() # 2. 获取每个分组的入场价,广播到组内所有行 df['entry_price'] = df.groupby('group_id')['Price'].transform('first') # 3. 计算价格相对入场价的涨幅,判断是否触发止损 df['price_return'] = (df['Price'] / df['entry_price']) - 1 df['is_trigger'] = df['price_return'] > 0.15 # 4. 每个分组仅标记第一个触发止损的位置 def mark_first_exit(group): first_trigger_idx = group[group['is_trigger']].index.min() if pd.notna(first_trigger_idx): group.loc[first_trigger_idx, 'Stop Loss'] = 'Exit' return group['Stop Loss'] df['Stop Loss'] = df.groupby('group_id', group_keys=False).apply(mark_first_exit) # 清理中间辅助列(可选) df = df.drop(columns=['group_id', 'entry_price', 'price_return', 'is_trigger'])
执行后得到的结果与示例完全一致:
Date Price Entry Signal Stop Loss 0 2024-01-18 3595.0 <NA> NaN 1 2024-01-19 3280.0 Entry NaN 2 2024-01-22 3505.0 <NA> NaN 3 2024-01-23 3945.0 <NA> Exit 4 2024-01-24 4075.0 <NA> NaN 5 2024-03-07 10270.0 Entry NaN 6 2024-03-08 8120.0 <NA> NaN 7 2024-03-11 14020.0 <NA> Exit
逻辑说明
- 分组ID:通过
cumsum()给每个Entry分配递增组号,ffill()让同一交易周期内的所有行共享组号,实现不同交易周期的隔离。 - 入场价广播:
transform('first')将分组内第一行(Entry行)的价格复制到组内所有行,无需循环查找。 - 止损触发标记:用
groupby().apply()遍历每个分组,仅标记第一个触发止损的位置,确保每个交易周期只平仓一次,之后等待下一个Entry信号。
这种方法完全基于Pandas的向量化和分组操作,效率远高于逐行循环,尤其适合大规模数据集。
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

