首次使用Backtrader调用cerebro.plot()遇RRuleLocator属性错误求助
解决Backtrader调用cerebro.plot()时的AttributeError问题
错误详情
调用cerebro.plot()时触发以下错误:
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[3], line 158 155 print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) 157 # Plot the result --> 158 cerebro.plot() File /opt/homebrew/lib/python3.10/site-packages/backtrader-1.9.76.123-py3.10.egg/backtrader/cerebro.py:989, in Cerebro.plot(self, plotter, numfigs, iplot, start, end, width, height, dpi, tight, use, **kwargs) 987 for stratlist in self.runstrats: 988 for si, strat in enumerate(stratlist): --> 989 rfig = plotter.plot(strat, figid=si * 100, 990 numfigs=numfigs, iplot=iplot, 991 start=start, end=end, use=use) 992 # pfillers=pfillers2) 994 figs.append(rfig) File /opt/homebrew/lib/python3.10/site-packages/backtrader-1.9.76.123-py3.10.egg/backtrader/plot/plot.py:262, in Plot_OldSync.plot(self, strategy, figid, numfigs, iplot, start, end, **kwargs) 257 # Applying fig.autofmt_xdate if the data axis is the last one 258 # breaks the presentation of the date labels. why? 259 # Applying the manual rotation with setp cures the problem 260 # but the labels from all axis but the last have to be hidden 261 for ax in laxis: --> 262 self.mpyplot.setp(ax.get_xticklabels(), visible=False) 264 self.mpyplot.setp(lastax.get_xticklabels(), visible=True, 265 rotation=self.pinf.sch.tickrotation) 267 # Things must be tight along the x axis (to fill both ends) File /opt/homebrew/lib/python3.10/site-packages/matplotlib/axes/_base.py:74, in _axis_method_wrapper.__set_name__.<locals>.wrapper(self, *args, **kwargs) 73 def wrapper(self, *args, **kwargs): ---> 74 return get_method(self)(*args, **kwargs) File /opt/homebrew/lib/python3.10/site-packages/matplotlib/axis.py:1456, in Axis.get_ticklabels(self, minor, which) 1454 if minor: 1455 return self.get_minorticklabels() --> 1456 return self.get_majorticklabels() File /opt/homebrew/lib/python3.10/site-packages/matplotlib/axis.py:1413, in Axis.get_majorticklabels(self) 1411 def get_majorticklabels(self): 1412 """Return this Axis' major tick labels, as a list of `~.text.Text`.""" --> 1413 self._update_ticks() 1414 ticks = self.get_major_ticks() 1415 labels1 = [tick.label1 for tick in ticks if tick.label1.get_visible()] File /opt/homebrew/lib/python3.10/site-packages/matplotlib/axis.py:1262, in Axis._update_ticks(self) 1257 def _update_ticks(self): 1258 """ 1259 Update ticks (position and labels) using the current data interval of 1260 the axes. Return the list of ticks that will be drawn. 1261 """ --> 1262 major_locs = self.get_majorticklocs() 1263 major_labels = self.major.formatter.format_ticks(major_locs) 1264 major_ticks = self.get_major_ticks(len(major_locs)) File /opt/homebrew/lib/python3.10/site-packages/matplotlib/axis.py:1484, in Axis.get_majorticklocs(self) 1482 def get_majorticklocs(self): 1483 """Return this Axis' major tick locations in data coordinates.""" --> 1484 return self.major.locator() File /opt/homebrew/lib/python3.10/site-packages/matplotlib/dates.py:1378, in AutoDateLocator.__call__(self) 1375 def __call__(self): 1376 # docstring inherited 1377 dmin, dmax = self.viewlim_to_dt() --> 1378 locator = self.get_locator(dmin, dmax) 1379 return locator() File /opt/homebrew/lib/python3.10/site-packages/backtrader-1.9.76.123-py3.10.egg/backtrader/plot/locator.py:226, in AutoDateLocator.get_locator(self, dmin, dmax) 222 locator = MicrosecondLocator(interval, tz=self.tz) 224 locator.set_axis(self.axis) --> 226 locator.set_view_interval(*self.axis.get_view_interval()) 227 locator.set_data_interval(*self.axis.get_data_interval()) 228 return locator AttributeError: 'RRuleLocator' object has no attribute 'set_view_interval'
问题背景
此前通过克隆Backtrader官方仓库安装,解决了ImportError: Cannot import name 'warnings' from 'matplotlib.dates'问题,但调用绘图函数时触发新的AttributeError;尝试删除报错代码行后重新安装,生成的图表显示混乱。
解决方案
方案1:修改Backtrader的locator.py文件
找到Backtrader安装目录下的backtrader/plot/locator.py,定位到AutoDateLocator.get_locator方法(约第224-228行),修改代码为:
locator.set_axis(self.axis) # 仅在locator支持时调用方法 if hasattr(locator, 'set_view_interval'): locator.set_view_interval(*self.axis.get_view_interval()) if hasattr(locator, 'set_data_interval'): locator.set_data_interval(*self.axis.get_data_interval()) return locator
修改后保存文件,重新运行代码即可。
方案2:降低Matplotlib版本
该问题源于Matplotlib 3.7+版本中RRuleLocator移除了set_view_interval和set_data_interval方法,可安装兼容版本:
pip install matplotlib==3.6.3
重新安装后无需修改Backtrader代码,即可正常调用绘图函数。
方案3:使用维护中的Backtrader分支
官方Backtrader已停止维护,可使用社区维护的分支(如backtrader2),该分支已修复此类兼容性问题:
pip install backtrader2
替换原Backtrader导入为import backtrader2 as backtrader即可。
内容的提问来源于stack exchange,提问作者Mario Diw
相关产品推荐
相关产品推荐

