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
相关产品推荐
相关产品推荐

