You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于滚动条件创建止损列:空单15%止损回测实现

实现空单15%止损回测的Pandas优化方案

不用逐行循环,我们可以利用Pandas的分组、矢量化操作高效实现这个逻辑,步骤如下:

  1. 标记交易分组:将Entry Signal转为布尔值,通过累加生成每个交易周期的分组ID,再向前填充确保同一周期内的行属于同一组。
  2. 获取每组入场价:对每个分组提取入场行的价格(即分组内第一行的Price),广播到组内所有行。
  3. 识别止损触发点:计算每行价格相对入场价的涨幅,找到每个分组中第一个触发涨幅超过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 20:51:18