Backtrader Community

    • 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/

    Multi timeframe indicator plotted twice and in wrong timeframe

    Indicators/Strategies/Analyzers
    2
    5
    1140
    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
      fino last edited by fino

      Hello backtrader community. I just started using backtrader to test a H1 strategy that uses a D1 indicator. The indicator gives two values at the beginning of the day that are valid for all H1 candles until the end of the day. Two horizontal lines (in the H1 TF) similar to a pivot.

      The current implementation of this indicator does not works: it has these two problems:

      • both the H1 and the D1 charts are shown. I only want the H1 chart.
      • the indicator shows the right values in the D1 chart, but it is not plotted in the H1 chart (where I want it as a series of straight lines).

      Here is a screenshot of the problem

      0_1549956795059_mtf2.png

      See? No indicator in the H1 chart and a superfluous D1 chart.

      As you can see in the following code, at the top level I first load the H1 data and then the D1 data. This should make H1 the default data source, right?

      Then, in the strategy, I set up the indicator to use self.data1. This should link its calculations to the D1 timeframe, shouldn't it?

      Here is the code (simplified but working)

      #!/usr/bin/env python
      import backtrader as bt
      import backtrader.indicators as btind
      
      class MyMA(bt.Indicator):
          lines = ('ma',)
          params = dict(period=30)
      
          def __init__(self):
              diff = self.data.high - self.data.open
              self.l.ma = btind.SMA(diff, period=self.p.period)
      
      class Levels(bt.Indicator):
          lines = ('last_close', 'adj_close')
          params = dict(period=30)
      
          def __init__(self):
              ma = MyMA(period=self.p.period)
              self.l.last_close = self.data.close(-1)
              self.l.adj_close = self.data.close(-1) - ma(-1)
      
      class LevelsDisplay(bt.Strategy):
          params = dict(period=30)
      
          def __init__(self):
              # data1 = D1 Timeframe
              self.levels = Levels(self.data1, period=self.p.period)
              self.levels.plotinfo.subplot = False
      
      csv_opts = dict(
          headers=True, separator=';', dtformat='%Y-%m-%d %H:%M:%S %z',
          openinterest=-1)
      h1_opts = dict(dataname='data-h1.csv',
                     timeframe=bt.TimeFrame.Minutes, compression=60)
      d1_opts = dict(dataname='data-d1.csv',
                     timeframe=bt.TimeFrame.Days)
      
      cerebro = bt.Cerebro(stdstats=False)
      data_h1 = bt.feeds.GenericCSVData(**{**csv_opts, **h1_opts})
      data_d1 = bt.feeds.GenericCSVData(**{**csv_opts, **d1_opts})
      cerebro.adddata(data_h1)
      cerebro.adddata(data_d1)
      cerebro.addstrategy(LevelsDisplay, period=3)
      cerebro.run(runonce=False)
      cerebro.plot(style='candle')
      

      And this is data-d1.csv:

      TIME;OPEN;HIGH;LOW;CLOSE;VOLUMES
      2019-02-01 01:00:00 +0100;11198;11218;11116;11180;104846000
      2019-02-04 01:00:00 +0100;11180;11209;11100;11176;76459000
      2019-02-05 01:00:00 +0100;11178;11371;11177;11367;92184000
      2019-02-06 01:00:00 +0100;11337;11347;11297;11324;78242000
      2019-02-07 01:00:00 +0100;11262;11286;11022;11022;111363000
      2019-02-08 01:00:00 +0100;10991;11045;10864;10906;105464736
      

      and data-h1.csv:

      TIME;OPEN;HIGH;LOW;CLOSE;VOLUMES
      2019-02-01 09:00:00 +0100;11198;11218;11159;11197;13547140
      2019-02-01 10:00:00 +0100;11197;11211;11166;11180;7988925
      2019-02-01 11:00:00 +0100;11181;11187;11142;11161;7331403
      2019-02-01 12:00:00 +0100;11161;11177;11147;11150;5334638
      2019-02-01 13:00:00 +0100;11152;11160;11130;11134;6911563
      2019-02-01 14:00:00 +0100;11135;11186;11135;11175;5151842
      2019-02-01 15:00:00 +0100;11175;11181;11118;11119;9776934
      2019-02-01 16:00:00 +0100;11117;11175;11116;11162;10919961
      2019-02-01 17:00:00 +0100;11160;11186;11152;11180;37883752
      2019-02-04 09:00:00 +0100;11180;11209;11131;11143;12075054
      2019-02-04 10:00:00 +0100;11142;11197;11141;11186;6030952
      ...
      

      What am I doing wrong?

      B 1 Reply Last reply Reply Quote 0
      • B
        backtrader administrators @fino last edited by

        @fino said in Multi timeframe indicator plotted twice and in the timeframe:

        The current implementation of this indicator does not works: it has these two problems:

        Sorry, but it does work.

        @fino said in Multi timeframe indicator plotted twice and in the timeframe:

        • both the H1 and the D1 charts are shown. I only want the H1 chart.

        You have not told the system that you only want the H1 chart. It cannot be a problem. You have not configured things to work the way you want.

        See - Docs - Plotting and use plotinfo.plot=False for whatever you don't want plotted.

        @fino said in Multi timeframe indicator plotted twice and in the timeframe:

        • the indicator shows the right values in the D1 chart, but it is not plotted in the H1 chart

        @fino said in Multi timeframe indicator plotted twice and in the timeframe:

        data_h1 = bt.feeds.GenericCSVData(**{**csv_opts, **h1_opts})
        data_d1 = bt.feeds.GenericCSVData(**{**csv_opts, **d1_opts})
        

        @fino said in Multi timeframe indicator plotted twice and in the timeframe:

                self.levels = Levels(self.data1, period=self.p.period)
        

        Well, you load d1 as the second feed in the system (hence self.data1) and you apply the indicator to self.data1. It should be no surprise that the indicator plots on d1 and not on h1. It would be a surprise if it did otherwise.

        Again. See - Docs - Plotting and use plotinfo.plotmaster=YOUR_DESIRED_DATA to plot on your chosen target.

        @fino said in Multi timeframe indicator plotted twice and in the timeframe:

        See? No indicator in the H1 chart and a superfluous D1 chart.

        See above. There is nothing superfluous. You have to configure what you want and what you don't want and where you want it and where you don't want it.

        @fino said in Multi timeframe indicator plotted twice and in the timeframe:

        As you can see in the following code, at the top level I first load the H1 data and then the D1 data. . This should make H1 the default data source, right?

        No idea what you mean with "default data source". There is no such thing in backtrader. The only thing you have achieved is that h1 can be referred as self.data0 or self.datas[0] or self.data. This is described here: Docs - Strategy in the section Member Attributes

        @fino said in Multi timeframe indicator plotted twice and in the timeframe:

        Then, in the strategy, I set up the indicator to use self.data1. This should link its calculations to the D1 timeframe, shouldn't it?

        Yes. And that's why the indicator obviously plots on d1

        1 Reply Last reply Reply Quote -1
        • F
          fino last edited by

          @backtrader said in Multi timeframe indicator plotted twice and in wrong timeframe:

          @fino said in Multi timeframe indicator plotted twice and in the timeframe:

          The current implementation of this indicator does not works: it has these two problems:

          Sorry, but it does work.

          Hi @backtrader, thank you for your assistance. Yes, the code does work, but it does not do what I want it to do. Obviously the problem is that I'm giving the wrong instructions because I'm new to backtrader and still haven't understood most of it. So I thank you in advance for your help.

          See - Docs - Plotting and use plotinfo.plotmaster=YOUR_DESIRED_DATA to plot on your chosen target.

          I tried with

          self.levels.plotinfo.plotmaster = self.data0
          

          but it failed with the following error: ValueError: x and y must have same first dimension, but have shapes (54,) and (6,).

          I need to replicate the generated indicator values (6) for each H1 candle (9 * 6 = 56), don't I? What is the best way to do this?

          1 Reply Last reply Reply Quote 0
          • B
            backtrader administrators last edited by

            Use coupling: Docs - Mixing Timeframes in Indicators

            This functionality allows to calculate an indicator on a timeframe an automatically apply the indicator to another lower timeframe.

            F 1 Reply Last reply Reply Quote -1
            • F
              fino @backtrader last edited by

              @backtrader said in Multi timeframe indicator plotted twice and in wrong timeframe:

              Use coupling: Docs - Mixing Timeframes in Indicators

              This functionality allows to calculate an indicator on a timeframe an automatically apply the indicator to another lower timeframe.

              I tried coupling the D1 indicator with the following code as suggested by the guide, but I still get the same error: ValueError: x and y must have same first dimension, but have shapes (54,) and (6,)

              class LevelsDisplay(bt.Strategy):
                  params = dict(period=30)
              
                  def __init__(self):
                      # self.data1 = D1 Timeframe
                      levels = Levels(self.data1, period=self.p.period)
                      self.levels = levels()
                      self.levels.plotinfo.subplot = False
                      self.levels.plotinfo.plotmaster = self.data0
              

              I do not see any other places in the Strategy where I could couple.

              The guide says

              See how the () is executed with no arguments (in the background a None is being supplied). The following is happening:

              pivotpoint.s1() is returning an internal LinesCoupler object which follows the rhythm of the larger scope. This coupler fills itself with the latest delivered value from the real s1 (starting with a default value of NaN)

              How does the Cerebro know which timeframe is the "the larger scope"? Does it analyze all the added data?

              BTW the Mixing Timeframes guide is where I started and it does not mention plotmaster at all. Maybe it could be useful for newbies if it was somehow mentioned. Just a suggestion.

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