Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Plotting code broken after update packages

    General Discussion
    3
    6
    376
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • F
      FredYellow last edited by

      Hello all,

      I had a working program running in my pipenv shell untill I updated all dependencies using

      pipenv update
      

      Now I get the following error when my code tries to plot the result of a backtest:

      Traceback (most recent call last):
        File "main.py", line 942, in <module>
          cerebro.plot(b)
              # Plot Bokeh object
        File "C:\Users\Craptop\.virtualenvs\FREBT-VbURPJvn\lib\site-packages\backtrader\cerebro.py", line 991, in plot
          start=start, end=end, use=use)
        File "C:\Users\Craptop\.virtualenvs\FREBT-VbURPJvn\lib\site-packages\backtrader_plotting\bokeh\bokeh.py", line 511, in plot
          df: pd.DataFrame = self.build_strategy_data(obj, start, end)
        File "C:\Users\Craptop\.virtualenvs\FREBT-VbURPJvn\lib\site-packages\backtrader_plotting\bokeh\bokeh.py", line 473, in build_strategy_data
          for lineidx in range(obj.size()):
      AttributeError: 'LinesOperation' object has no attribute 'size'
      
      

      My entire code still works fine, it's just the plotting (I'm using Bokeh) that seems broken. I have been searching for a solution but can't find one. Can anyone point me in the right direction?

      Regards,
      Frederik

      Richard Klein 1 Reply Last reply Reply Quote 0
      • Richard Klein
        Richard Klein @FredYellow last edited by

        @fredyellow I'm also having this problem. Any updates?

        1 Reply Last reply Reply Quote 0
        • Richard Klein
          Richard Klein last edited by

          @richard-klein
          The following edits seem to have fixed this for me. Admittedly, probably not very robust, but it seems strategy.getindicators() was returning all line objects--not all are indicators. Used "if not hasattr(obj, 'plotinfo')" to ensure we were working with indicators.

          backtrader_plotting/bokeh/label_resolver.py

          def indicator2fullid(ind: bt.Indicator) -> str:
              """Returns a string listing allZ involved data feeds. Empty string if there is only a single feed in the mix"""
              names = []
          
              # EDITED 
              if not hasattr(ind, 'plotinfo'):
                  return
          
              for x in ind.datas:
              
                  #EDITED
                  #elif isinstance(x, bt.AbstractDataBase):        
                  if isinstance(x, bt.AbstractDataBase):
                      return datatarget2label([x])
          
                  elif isinstance(x, bt.LineSeriesStub):
                      # indicator target is one specific line of a datafeed
                      # AFAIK it's not possible to know which line it is so we only add a generic indicator "[L]"
                      return datatarget2label([x._owner]) + '[L]'
                  elif isinstance(x, bt.Indicator):
                      names.append(indicator2label(x))
              return f"({','.join(names)})"
          
          
          

          backtrader_plotting/bokeh/bokeh.py

              def build_strategy_data(self, strategy: bt.Strategy,
                                      start: Optional[datetime.datetime] = None, end: Optional[datetime.datetime] = None,
                                      num_back: Optional[int] = None,
                                      startidx: int = 0):
                  """startidx: index number to write into the dataframe for the index column"""
                  strategydf = pd.DataFrame()
          
                  start, end = Bokeh._get_start_end(strategy, start, end)
          
                  strat_clk: array[float] = strategy.lines.datetime.plotrange(start, end)
          
                  # if patches occured then we see duplicate entries in the strategie clock -> clean them
                  strat_clk = np.unique(strat_clk)
          
                  if num_back is None:
                      num_back = len(strat_clk)
          
                  strat_clk = strat_clk[-num_back:]
          
                  # we use timezone of first data. we might see duplicated timestamps here
                  dtline = [bt.num2date(x, strategy.datas[0]._tz) for x in strat_clk]
          
                  # add an index line to use as x-axis (instead of datetime axis) to avoid datetime gaps (e.g. weekends)
                  indices = list(range(startidx, startidx + len(dtline)))
                  strategydf['index'] = indices
          
                  strategydf['datetime'] = dtline
          
                  for data in strategy.datas:
                      source_id = FigureEnvelope._source_id(data)
                      df_data = convert_to_pandas(strat_clk, data, start, end, source_id)
          
                      strategydf = strategydf.join(df_data)
          
                      df_colors = FigureEnvelope.build_color_lines(df_data, self.p.scheme, col_open=source_id + 'open', col_close=source_id + 'close', col_prefix=sourc$
                      strategydf = strategydf.join(df_colors)
          
                  for obj in itertools.chain(strategy.getindicators(), strategy.getobservers()):
                      #for lineidx in range(obj.size()):
          
                      # EDITED
                      if not hasattr(obj, 'plotinfo'):
                          continue
                      ################
          
                      for lineidx in range(obj.size()):
                          line = obj.lines[lineidx]
                          source_id = FigureEnvelope._source_id(line)
                          dataline = line.plotrange(start, end)
          
                          line_clk = get_clock_line(obj).plotrange(start, end)
                          dataline = convert_by_line_clock(dataline, line_clk, strat_clk)
                          strategydf[source_id] = dataline
          
                  # apply a proper index (should be identical to 'index' column)
                  if strategydf.shape[0] > 0:
                      strategydf.index = indices
                  return strategydf
          
          
          
          F 1 Reply Last reply Reply Quote 1
          • F
            FredYellow @Richard Klein last edited by

            @richard-klein That fixed it! Well done!
            What could be the cause of this?

            1 Reply Last reply Reply Quote 0
            • F
              FredYellow last edited by

              Now the Bokeh plotting works again, however it seems all of the parameters given in the object constructor are ignored:

              b = Bokeh(	filename='FREBT.html',					# Bokeh plotting object constructor
                                  title='FREBT',
                                  style='bar', 										# Candlesticks
                                  plot_mode="single",									# single / tabs
                                  plot_width=1550,                                    # 
                                  plot_height_data = 500,                             # See Scheme.py on Github "backtrader_plotting " for all possible params concerning Bokeh layout
                                  plot_height_observer = 120,
                                  plot_height_indicator = 100,
                                  legend_click = "hide",								# Hides line clicked on. "Mute" disables this
                                  legend_background_transparency = 0.9,
                                  tools = "pan,wheel_zoom,box_zoom,reset,save")
              		cerebro.plot(b)
              

              Any ideas?

              Richard Klein 1 Reply Last reply Reply Quote 0
              • Richard Klein
                Richard Klein @FredYellow last edited by

                @fredyellow
                This works for me.

                    b = Bokeh(style='bar',scheme=Tradimo(),output_mode='save',filename='test.html')
                    cerebro.plot(b)
                

                Maybe try editing the "Tradimo" scheme to include your parameters or create a new scheme and load your parameters via that custom scheme--scheme=custom().
                backtrader_plotting/schemes/Tradimo.py

                1 Reply Last reply Reply Quote 0
                • 1 / 1
                • First post
                  Last post
                Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors