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

Python交易策略回测for循环实现异常:求助排查问题原因

交易策略回测代码错误排查与修正

问题描述

尝试编写基于ETH价格数据的交易回测算法,规则为:

  • 初始资金1000美元
  • 当Pct_Change <= -1.6819时,用全部资金买入资产
  • 当Pct_Change >= 1.4379时,卖出全部持仓
  • 要求严格按买入-卖出-买入-卖出交替执行

但执行代码后,dollars和units均变为全0的Series,不符合预期。

原代码

dollars = 1000
units = 0

def buy(dollars,unit_price):
    global units
    units=dollars/unit_price
    dollars = 0

def sell(units,unit_price):
    global dollars
    dollars=units*unit_price
    units=0

for pct_change in df['ETH-Pct-Change']:
    if pct_change <=-1.6819:
        buy(dollars,df['ETH-Close'])
    elif pct_change >= 1.4379:
        sell(units,df['ETH-Close'])
    else:
        pass

错误原因分析

1. 全局变量与函数参数命名冲突

函数buy和sell的参数名与全局变量dollars、units同名,导致函数内的赋值操作只修改了局部参数,而非全局变量。例如buy函数里的dollars = 0只是修改了函数内部的局部变量,全局的dollars并未被重置为0;反之sell函数里的units=0也只修改了局部参数,全局units未变化。

2. 传入整个Series而非单日期价格

循环中遍历的是pct_change单个值,但调用buy/sell时传入的是df['ETH-Close']整个Series,而非当前日期对应的价格。这会导致units和dollars被赋值为Series对象,而非单个数值,后续计算会出现向量运算错误,最终变成全0的Series。

3. 未控制交易交替逻辑

代码没有记录当前的持仓状态(持有现金/持有资产),可能出现连续买入(当dollars已经为0时)或连续卖出(当units已经为0时)的情况,最终导致数值被错误重置为0的Series。

修正后的代码

import pandas as pd

# 读取数据(请替换为你的数据加载方式)
df = pd.read_csv('eth.csv', parse_dates=['Date'], index_col='Date')

dollars = 1000.0
units = 0.0
is_holding = False  # 记录当前是否持仓,确保交替交易

for idx, row in df.iterrows():
    pct_change = row['ETH-Pct-Change']
    current_price = row['ETH-Close']
    
    # 满足买入条件且当前未持仓
    if pct_change <= -1.6819 and not is_holding:
        units = dollars / current_price
        dollars = 0.0
        is_holding = True
        print(f"{idx}: 买入 {units:.2f} 份,价格 {current_price:.2f}")
    
    # 满足卖出条件且当前持仓
    elif pct_change >= 1.4379 and is_holding:
        dollars = units * current_price
        units = 0.0
        is_holding = False
        print(f"{idx}: 卖出,价格 {current_price:.2f},当前资金 {dollars:.2f}")

# 输出最终结果
if is_holding:
    final_value = units * df.iloc[-1]['ETH-Close']
    print(f"最终持仓:{units:.2f} 份,对应市值 {final_value:.2f} 美元")
else:
    print(f"最终资金:{dollars:.2f} 美元")

修正要点

  • 去掉冗余函数,直接在循环内处理交易逻辑,避免全局变量与参数的冲突
  • 使用iterrows()遍历每一行数据,获取当前日期的价格而非整个Series
  • 新增is_holding状态变量,严格控制买入和卖出的交替执行
  • 保留打印日志,方便跟踪每一步交易操作

内容的提问来源于stack exchange,提问作者Shan Govind

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:31:15