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

Pandas循环计算问题:基于前一行调整交易仓位控制风险

交易策略回测中依赖前序结果的Pandas递推计算解决方案

问题背景

在交易策略回测场景中,需要对Pandas DataFrame中的仓位进行动态调整:当计算出的risk超过max_risk时,调整Trade size,且后续行的计算必须使用上一行更新后的Trade size。普通向量化列操作无法处理这种递推依赖,导致当前代码计算结果不准确。

初始数据

Trade OpenTrade numberTrade sizestopcloseriskmax risk
TRUE1100%8010020.00%20%
1100%8012033.33%20%
1100%8014042.86%20%
1100%8016050.00%20%

期望结果

Trade OpenTrade numberTrade sizestopcloseriskmax riskReduction booleanReduction
TRUE1100%8010020.00%20%FALSE0%
1100%8012033.33%20%TRUE40%
160%8014025.71%20%TRUE22%
146.8%8016023.40%20%TRUE15%

当前错误代码

d = {'Trade Open': [True, False, False, False,], 'Trade number': [1]*4, 'Trade_size': [100]*4, 'close':[100,120,140,160],'stop': [80]*4, 'max_risk': [20]*4}

df = pd.DataFrame(data=d)
df['risk'] = (df.close - df.stop)/ df.close * df.Trade_size
df['reduction_boolean'] = df.risk > df.max_risk
df['reduction'] = 0 
df.loc[df['reduction_boolean'], 'reduction'] = 1 - (df.max_risk / df.risk)

df.loc[df['reduction_boolean'].shift() == True, 'Trade_size'] = df.Trade_size * (1-df.reduction.shift())
df

解决方案

由于Trade size的更新依赖上一行的计算结果,必须采用分组逐行迭代的方式处理,确保每一步的仓位调整都能传递到下一行。代码如下:

import pandas as pd

# 初始化数据
d = {
    'Trade Open': [True, False, False, False],
    'Trade number': [1]*4,
    'Trade_size': [100]*4,
    'close': [100, 120, 140, 160],
    'stop': [80]*4,
    'max_risk': [20]*4
}
df = pd.DataFrame(data=d)

# 初始化新增列
df['risk'] = 0.0
df['reduction_boolean'] = False
df['reduction'] = 0.0

# 按交易编号分组,逐组处理递推计算
for trade_num, group in df.groupby('Trade number'):
    indices = group.index
    # 初始化当前交易的仓位大小(取第一行初始值)
    current_size = df.loc[indices[0], 'Trade_size']
    
    for i in indices:
        # 计算当前risk
        risk_val = (df.loc[i, 'close'] - df.loc[i, 'stop']) / df.loc[i, 'close'] * current_size
        df.loc[i, 'risk'] = round(risk_val, 2)
        
        # 判断是否需要调仓
        if risk_val > df.loc[i, 'max_risk']:
            df.loc[i, 'reduction_boolean'] = True
            # 计算调仓比例
            reduction_val = 1 - (df.loc[i, 'max_risk'] / risk_val)
            df.loc[i, 'reduction'] = round(reduction_val * 100, 1)
            # 更新下一行要用的仓位
            current_size = current_size * (1 - reduction_val)
        else:
            df.loc[i, 'reduction_boolean'] = False
            df.loc[i, 'reduction'] = 0.0
            # 无调仓,保持当前仓位
            current_size = df.loc[i, 'Trade_size']
    
    # 将调整后的仓位写回DataFrame
    # 第一行保持初始值,后续行用上一行调整后的值
    df.loc[indices[0], 'Trade_size'] = 100
    for idx in range(1, len(indices)):
        prev_idx = indices[idx-1]
        df.loc[indices[idx], 'Trade_size'] = round(df.loc[prev_idx, 'Trade_size'] * (1 - df.loc[prev_idx, 'reduction']/100), 1)

# 格式化百分比显示
df['Trade_size'] = df['Trade_size'].astype(str) + '%'
df['risk'] = df['risk'].astype(str) + '%'
df['max_risk'] = df['max_risk'].astype(str) + '%'
df['reduction'] = df['reduction'].astype(str) + '%'

print(df)

代码说明

  1. 分组处理:按Trade number分组,确保每个独立交易的计算逻辑互不干扰;
  2. 递推变量维护:用current_size保存上一行调整后的仓位,逐行传递更新;
  3. 逐行计算:依次计算risk、判断调仓条件、更新仓位和相关列;
  4. 格式调整:最后将数值转为百分比格式,与期望结果一致。

内容的提问来源于stack exchange,提问作者James Cabourne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 19:24:56