backtrader导入CSV数据触发'str'无to_pydatetime属性报错排查
问题描述
运行backtrader量化程序时抛出如下错误:
_load dt = tstamp.to_pydatetime() AttributeError: 'str' object has no attribute 'to_pydatetime'
报错触发场景:通过bt.feeds接口导入CSV格式行情数据,自定义了继承自bt.feeds.PandasData的PandasDataPlus类扩展cerebro的数据lines,排查后未定位错误根源。
涉及的实现代码如下:
import backtrader as bt from backtrader.feeds import GenericCSVData import pandas as pd import pandas_ta as ta import matplotlib.pyplot as plt import datetime as dt import numpy as np from datetime import datetime class PandasDataPlus(bt.feeds.PandasData): lines = ('crossover','crossover2','below','below2', ) params = (('crossover', 7),('crossover2', 8),('below', 9),('below2', 10),) class Stoch(bt.Strategy): def __init__(self): self.dataclose = self.data.close self.order=None self.buyprice = None self.buycomm=None def next(self): print(self.datas[0].lines.getlinealiases()) def notify_order(self, order): if order.status in [order.Submitted,order.Accepted]: return if order.status in [order.Completed]: if order.isbuy(): self.log( 'BUY EXECUTED, Price: %.2f,Cost: %.2f, Comm: %.2f' % (order.executed.price, order.executed.value, order.executed.comm) ) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: self.log('SELL EXECUTED, Price:Price: %.2f,Cost: %.2f, Comm: %.2f' % (order.executed.price, order.executed.value, order.executed.comm) ) self.bar_executed = len(self) elif order.status in [order.Canceled,order.Margin,order.Rejected]: self.log('Order Canceled/Margin/Rejected') self.order = None def notify_trader(self, order): if not trade.isclosed: return self.log('OPERATION PROFIT, GROSS %.2f , NET %.2f'% (trade.pnl,trade.pnlcomm)) def log(self,txt,dt=None,doprint=True): if doprint: dt=dt or self.datas[0].datetime.date(0) print('%s,%s,'% (dt.isoformat(), txt)) if __name__ == '__main__': cerebro = bt.Cerebro() dataframe = pd.read_csv('out.csv') df=dataframe df['Datetime'] = pd.to_datetime(df['Date']) df.set_index('Datetime',inplace=True) df['Stoch'] = pd.DataFrame(ta.stoch(df['High'],df['Low'],df['Close']),columns=['STOCHk_86_15_5']) value = 89 value2 = 20 df['crossover'] = ta.cross_value(df['Stoch'], value) df['below'] = ta.cross_value(df['Stoch'], 100-value,above=False) df['crossover2'] = ta.cross_value(df['Stoch'], value2) df['below2'] = ta.cross_value(df['Stoch'], 100-value2,above=False) data_TSLA = PandasDataPlus( dataname=dataframe, fromdate=dt.datetime(2020,1,1), todate=dt.datetime(2021,1,1), timeframe=bt.TimeFrame.Minutes, datetime = 0, open = 1, high = 2, low = 3, close = 4, volume = 5, openinterest = -1, crossover = 7,crossover2 = 8,below = 9,below2 = 10 ) cerebro.adddata(data_TSLA) cerebro.addstrategy(Stoch) cerebro.addanalyzer(bt.analyzers.SharpeRatio,_name='sharpratio') cerebro.addanalyzer(bt.analyzers.DrawDown, _name='drawdown') cerebro.broker.setcash(10000.0) cerebro.broker.setcommission(commission=0.0006) cerebro.addsizer(bt.sizers.PercentSizer,percents=90) result=cerebro.run() print('Sharp:',result[0].analyzers.sharpratio.get_analysis()['sharperatio']) print('Draw:',result[0].analyzers.drawdown.get_analysis()['max']['drawdown']) cerebro.plot()
使用的CSV数据为常规分钟级行情数据,包含Date、Open、High、Low、Close、Volume字段。
错误根源
- 核心错误:时间格式转换、自定义指标列计算都是在
df变量上完成的,但传给PandasDataPlus的dataname参数是未做任何处理的原始dataframe。这个原始DataFrame里的Date列还是字符串类型,也没有新增的crossover等自定义列,backtrader按位置读取时间列时拿到的是字符串,无法调用to_pydatetime()方法,直接抛出属性错误。 - 次要问题:
bt.feeds.PandasData默认会将传入DataFrame的索引作为datetime时间列,额外传入datetime=0这类CSV读取专用的列位置参数,会和PandasData的读取规则冲突。 - 隐藏bug:策略类里写的
notify_trader方法名错误,backtrader的交易状态回调方法名是notify_trade,且入参是trade不是order,原写法会导致交易盈亏日志完全不触发。
修复方案
- 将
PandasDataPlus初始化时的dataname参数从dataframe替换为处理完成的df - 删除PandasDataPlus初始化时传入的
datetime=0、open=1这类按列位置映射的参数,PandasData会自动按列名匹配OHLCV等默认字段,自定义字段的列名和定义的lines名称一致即可自动加载 - 修正回调方法名和参数,把
def notify_trader(self, order):改成def notify_trade(self, trade):
修复后的数据加载部分代码参考:
data_TSLA = PandasDataPlus( dataname=df, # 替换为处理好的带datetime索引的df fromdate=dt.datetime(2020,1,1), todate=dt.datetime(2021,1,1), timeframe=bt.TimeFrame.Minutes, openinterest=-1 )
改完后重新运行即可正常加载数据,不会再出现时间字段的属性错误。
内容的提问来源于stack exchange,提问作者Xu Xu
相关产品推荐
相关产品推荐

