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

首次使用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):
---&gt; 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 19:54:55