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

Backtrader回测完成后如何添加新数据并重新运行回测?

Backtrader回测完成后如何添加新数据并重新运行回测?

我明白你找不到相关API的感受,Backtrader确实没有直接支持在已运行的Cerebro实例上添加新数据再重启回测的方法——因为一旦调用cerebro.run(),整个回测的内部状态(比如策略的持仓记录、时间节点跟踪、指标计算结果等)都已经走完流程并固定下来了,没法直接重置复用。

不过有两种实用的解决方案可以满足你的需求,根据你的实际场景选择就行:

方案一:重新构建Cerebro实例(最稳妥通用)

把配置回测的逻辑封装成一个独立函数,这样不管是第一次跑,还是要合并新数据再跑,都可以调用这个函数生成全新的Cerebro实例,完全避免状态污染的问题。这也是Backtrader官方推荐的常规做法。

结合你的代码,改造后大概是这样:

import backtrader as bt
import pandas as pd

def run_backtest(data_df):
    # 每次调用都创建全新的Cerebro实例
    cerebro = bt.Cerebro()
    # 加载数据
    data = bt.feeds.PandasData(dataname=data_df)
    cerebro.adddata(data)
    # 添加策略和分析器
    cerebro.addstrategy(MyStrategy)
    cerebro.addanalyzer(bt.analyzers.TradeAnalyzer)
    cerebro.addanalyzer(bt.analyzers.Returns)
    cerebro.addanalyzer(bt.analyzers.AnnualReturn)
    
    # 执行回测
    bt_result = cerebro.run()
    final_value = cerebro.broker.getvalue()
    
    return bt_result, final_value

# 第一次用旧数据跑回测
df_old = pd.read_csv('data.csv')
result_old, value_old = run_backtest(df_old)

# 假设你拿到了新数据,合并旧数据与新数据(注意保证时间顺序正确)
new_df = pd.read_csv('new_data.csv')
combined_df = pd.concat([df_old, new_df]).sort_values('datetime').reset_index(drop=True)

# 用合并后的完整数据重新跑回测
result_new, value_new = run_backtest(combined_df)

方案二:模拟增量回测(保留之前的持仓状态)

如果你想要的不是重新跑全部数据,而是基于之前回测的最终持仓、现金状态,继续用新数据跑后续的回测,那需要手动保存和恢复策略与Broker的状态(Backtrader本身没有内置这个功能)。

举个简单的实现示例:

1. 先跑旧数据并保存状态

# 初始化旧数据回测
cerebro_old = bt.Cerebro()
data_old = bt.feeds.PandasData(dataname=df_old)
cerebro_old.adddata(data_old)
cerebro_old.addstrategy(MyStrategy)
result_old = cerebro_old.run()

# 提取需要保留的状态
strategy = result_old[0]
saved_position = strategy.getposition(data_old)  # 持仓数量、成本
saved_cash = cerebro_old.broker.getcash()        # 剩余现金
saved_value = cerebro_old.broker.getvalue()      # 账户总价值

2. 用新数据跑回测并加载状态

# 初始化新数据回测
cerebro_new = bt.Cerebro()
data_new = bt.feeds.PandasData(dataname=new_df)
cerebro_new.adddata(data_new)

# 通过参数把保存的状态传递给策略
cerebro_new.addstrategy(MyStrategy, 
                        initial_pos_size=saved_position.size,
                        initial_pos_price=saved_position.price)

# 设置Broker的初始现金和总价值
cerebro_new.broker.setcash(saved_cash)
cerebro_new.broker.setvalue(saved_value)

# 添加分析器并执行回测
cerebro_new.addanalyzer(bt.analyzers.TradeAnalyzer)
result_new = cerebro_new.run()

3. 在策略中初始化状态

需要在你的MyStrategy类里添加状态初始化的逻辑:

class MyStrategy(bt.Strategy):
    params = (
        ('initial_pos_size', 0),
        ('initial_pos_price', 0.0),
    )
    
    def start(self):
        # 如果有初始持仓,手动设置到Broker中
        if self.params.initial_pos_size != 0:
            data = self.datas[0]
            self.broker.addposition(data, self.params.initial_pos_size, self.params.initial_pos_price)

不过要注意,这种方法需要你自己处理所有关键状态的保存和恢复(比如指标的历史值、未成交订单等),比较繁琐,适合有一定Backtrader使用经验的用户。

备注:内容来源于stack exchange,提问作者G_will

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:34:40