如何在使用backtesting.py库回测时避免DataFrame初始周期数据被剔除
解决backtesting.py中均线NaN导致回测起始日期偏差的问题
我之前在使用backtesting.py做量化回测时,也碰到过完全一样的问题——当计算n1周期移动平均线时,DataFrame前n1行都会出现NaN值,导致策略没法按我设定的起始日期正常启动。这里分享几个针对这个库的专属解决方案,亲测好用:
方案1:提前预处理数据,截断NaN区段
最简单直接的办法就是在把数据传入回测之前,先把包含NaN的前n1行数据删掉,确保回测从均线有有效数值的周期开始。示例代码如下:
import pandas as pd from backtesting import Backtest, Strategy # 假设你的原始数据已经加载到df中 df['MA'] = df['Close'].rolling(window=n1).mean() # 直接截断前n1行的NaN数据,从第n1行开始保留有效数据 df = df.iloc[n1:] # 初始化回测,此时回测的起始日期就是第一个有均线值的日期 bt = Backtest(df, YourCustomStrategy, cash=10000) results = bt.run()
这种方式的好处是数据干净,回测全程都不会碰到NaN干扰,完全符合你对n1周期均线的策略定义。
方案2:在策略逻辑中判断NaN,跳过无效周期
如果你不想修改原始数据的时间范围(比如需要保留完整的回测时间轴,只是前n1个周期不执行交易),可以在策略的next()方法里添加NaN判断,直接跳过没有有效均线值的周期:
class YourCustomStrategy(Strategy): def init(self): # 在策略内部计算均线 self.ma = self.I(lambda x: x.rolling(window=n1).mean(), self.data.Close) def next(self): # 检查最新的均线值是否为NaN,是的话直接跳过当前周期 if pd.isna(self.ma[-1]): return # 这里写你的核心策略逻辑,比如均线交叉信号 if self.data.Close[-1] > self.ma[-1] and self.data.Close[-2] <= self.ma[-2]: self.buy() elif self.data.Close[-1] < self.ma[-1] and self.data.Close[-2] >= self.ma[-2]: self.sell()
这样回测还是会从你设定的起始日期开始,但前n1个周期里策略不会执行任何买卖操作,直到均线有有效值后才会启动交易逻辑。
方案3:调整均线计算的min_periods参数(谨慎使用)
如果你能接受前n1个周期的近似均线值,可以在计算均线时设置min_periods=1,这样即使不足n1个周期,也会计算出对应的平均值(比如第1天的均线就是当天收盘价,第2天是两天的平均)。示例代码:
class YourCustomStrategy(Strategy): def init(self): # 设置min_periods=1,提前生成均线值 self.ma = self.I(lambda x: x.rolling(window=n1, min_periods=1).mean(), self.data.Close) def next(self): # 此时无需判断NaN,因为所有周期都有均线值 if self.data.Close[-1] > self.ma[-1]: self.buy() else: self.sell()
⚠️ 注意:这种方法会改变你原本n1周期均线的定义,只适合你可以接受这种近似计算的场景,否则可能会影响策略的准确性。
总结一下,优先推荐方案1或方案2,具体选择取决于你是否需要保留原始的回测时间范围。
内容的提问来源于stack exchange,提问作者Boris Mikanikrezai
相关产品推荐
相关产品推荐

