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/

    Resampling issues + adding multiple timeframes

    General Code/Help
    4
    34
    313
    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.
    • Jens Halsberghe
      Jens Halsberghe @dasch last edited by

      @dasch

      class Trend_Indicator(bt.Indicator):
          lines = ('Trend', 'ohlc')
          params = (
                  ('slowma', 21),
                  ('fastma', 8),
          )
      
          def __init__(self):
              
              # Add Bollinger bands
              self.BB = bt.indicators.BollingerBands(self.datas[0])
            
              self.ohlc.open = self.datas[0].open[0]
              self.ohlc.high = self.datas[0].high[0]
              self.ohlc.low = self.datas[0].low[0]
              self.ohlc.close = self.datas[0].close[0]
              
              self.SlowEMA= bt.indicators.EMA(self.datas[0],period=self.params.slowma)
              self.FastEMA = bt.indicators.EMA(self.datas[0],period=self.params.fastma)
              
              self.Trend.bollinger_touch = ""
              self.Trend.Status = ""
              self.Trend.Enter = ""
              self.Trend.ExitParameters = {"20BarRule": False, "EMARule": False, "OppositeBollingerTouch": False}
              self.Trend.EMARule = {"Close1":False, "Close2":False}
              self.Trend.Position = 0 
              self.Trend.Test = 0 
              self.addminperiod(21)
              
          def next(self):          
              
              if self.Trend.bollinger_touch == "Top" and self.data.low[0] > self.BB.lines.bot[0] and self.Trend.Enter == "":
              # if the upper bollinger band was touched and the candle we have now makes the highest high and highest close, 
              # we enter in an uptrend
                  if self.data.high[0] > self.ohlc.high and self.data.close[0] > self.ohlc.close:
                      self.Trend.Enter = "Uptrend entered"
                      self.ohlc.high = self.data.high[0]
                      self.Trend.Status = "Up"
                      self.Trend.ExitParameters["OppositeBollingerTouch"] = False
                      self.Trend.ExitParameters["20BarRule"] = False
                      self.Trend.ExitParameters["EMARule"] = False
                      self.Trend.Position = len(self.ohlc)
                      self.Trend.Test = len(self.data.high)
                  if self.data.high[0] > self.ohlc.high:
                      self.ohlc.high = self.data.high[0]
                  if self.data.close[0] > self.ohlc.close:
                      self.ohlc.close = self.data.close[0]                
      
              # we enter in a downtrend
              elif self.Trend.bollinger_touch == 'Bottom' and self.data.high[0] < self.BB.lines.top[0] and self.Trend.Enter == "":
              # if the bottom bollinger band was touched and the candle we have now makes the lowest low and lowest close, 
              # we enter in a downtrend
                  if self.data.low[0] < self.ohlc.low and self.data.close[0] < self.ohlc.close:
                      self.Trend.Enter = "Downtrend entered"
                      self.ohlc.low = self.data.low[0]
                      self.Trend.Status = "Down"
                      self.Trend.ExitParameters["OppositeBollingerTouch"] = False
                      self.Trend.ExitParameters["20BarRule"] = False
                      self.Trend.ExitParameters["EMARule"] = False
                      self.Trend.Position = len(self.ohlc)
                      self.Trend.Test = len(self.data.low)
                  if self.data.low[0] < self.ohlc.low:
                      self.ohlc.low = self.data.low[0]
                  if self.data.close[0] < self.ohlc.close:
                      self.ohlc.close = self.data.close[0]                
      
              elif self.Trend.bollinger_touch == "":
                  # look for a top bollinger touch, then store that bar's data
                  if self.data.high[0] >= self.BB.lines.top[0] and self.data.low[0] > self.BB.lines.bot[0]:
                      self.ohlc.open = self.data.open[0]
                      self.ohlc.high = self.data.high[0]
                      self.ohlc.low = self.data.low[0]
                      self.ohlc.close = self.data.close[0]
                      self.Trend.bollinger_touch = "Top"
                      
                  elif self.data.low[0] <= self.BB.lines.bot[0] and self.data.high[0] < self.BB.lines.top[0]:
                      self.ohlc.open = self.data.open[0]
                      self.ohlc.high = self.data.high[0]
                      self.ohlc.low = self.data.low[0]
                      self.ohlc.close = self.data.close[0]
                      self.Trend.bollinger_touch = "Bottom"
              
              # if the upper bollinger band was touched but now the lower bollinger band got touched, the upper bollinger touch resets
              if self.Trend.bollinger_touch == "Top" and self.data.low[0] <= self.BB.lines.bot[0]:
                      self.Trend.bollinger_touch = "Bottom"
                      self.ohlc.open = self.data.open[0]
                      self.ohlc.high = self.data.high[0]
                      self.ohlc.low = self.data.low[0]
                      self.ohlc.close = self.data.close[0]
                      
              # if the bottom bollinger band was touched but now the top bollinger band got touched, the bottom bollinger touch resets
              elif self.Trend.bollinger_touch == "Bottom" and self.data.high[0] >= self.BB.lines.top[0]:
                      self.Trend.bollinger_touch = "Top"
                      self.ohlc.open = self.data.open[0]
                      self.ohlc.high = self.data.high[0]
                      self.ohlc.low = self.data.low[0]
                      self.ohlc.close = self.data.close[0]
      
              # we are in an uptrend
              if self.Trend.Status == "Up":
                  # if the opposite bollinger band was touched, we exit the uptrend
                  if self.data.low[0] <= self.BB.lines.bot[0]:
                      self.Trend.Status = ""
                      self.Trend.Enter = ""
                      self.Trend.ExitParameters["OppositeBollingerTouch"] = True
                      self.Trend.bollinger_touch = "Bottom"
                      self.Trend.EMARule['Close1'] = False
                      self.Trend.EMARule['Close2'] = False
                      self.ohlc.open = self.data.open[0]
                      self.ohlc.high = self.data.high[0]
                      self.ohlc.low = self.data.low[0]
                      self.ohlc.close = self.data.close[0]
                  # if a fresh high is made, keep track of the position
                  if self.data.high[0] > self.ohlc.high:
                      self.ohlc.high = self.data.high[0]
                      self.Trend.Position = len(self.data.high)
                  # after 20 bars (excluding the first) no new high is made, we are not in a trend anymore
                  elif self.data.high[0] < self.ohlc.high:
                      if len(self.data.high) - self.Trend.Position >= 21:
                          self.Trend.Status = ""
                          self.Trend.Enter = ""
                          self.Trend.ExitParameters["20BarRule"] = True
                          self.Trend.bollinger_touch = "Bottom"
                          self.Trend.EMARule['Close1'] = False
                          self.Trend.EMARule['Close2'] = False
                          self.Trend.ExitParameters['20BarRule'] = True
                          
                  # if the top bollinger band was touched, reset the EMA rule
                  if self.data.high[0] >= self.BB.lines.top[0]:
                      self.Trend.EMARule['Close1'] = False
                      self.Trend.EMARule['Close2'] = False
                      
                  if self.data.close[0] < self.SlowEMA[0] and self.data.close[0] < self.FastEMA[0]:
                      self.Trend.EMARule['Close1'] = True
      
                  if self.Trend.EMARule['Close1'] == True and self.data.close[0] > self.SlowEMA[0] and self.data.close[0] > self.FastEMA[0]:
                      self.Trend.EMARule['Close2'] = True
                      
                  if self.Trend.EMARule['Close1'] == True and self.Trend.EMARule['Close2'] == True and self.data.close[0] < self.SlowEMA[0] and self.data.close[0] < self.FastEMA[0]:
                      self.Trend.EMARule['Close1'] = False
                      self.Trend.EMARule['Close2'] = False
                      self.Trend.Status = ""
                      self.Trend.Enter = ""
                      self.Trend.ExitParameters['EMARule'] = True
                      self.Trend.bollinger_touch = ""
                        
              if self.Trend.Enter == "Uptrend entered" and True not in self.Trend.ExitParameters.values():
                  self.Trend[0] = 1
                  
              # we are in a downtrend
              if self.Trend.Status == "Down":
                  # if the opposite bollinger band was touched, we exit the downtrend
                  if self.data.high[0] >= self.BB.lines.top[0]:
                      self.Trend.Status = ""
                      self.Trend.Enter = ""
                      self.Trend.ExitParameters["OppositeBollingerTouch"] = True
                      self.Trend.bollinger_touch = "Top"
                      self.Trend.EMARule['Close1'] = False
                      self.Trend.EMARule['Close2'] = False
                      self.ohlc.open = self.data.open[0]
                      self.ohlc.high = self.data.high[0]
                      self.ohlc.low = self.data.low[0]
                      self.ohlc.close = self.data.close[0]
      
                  # if a fresh low is made, keep track of the position
                  if self.data.low[0] < self.ohlc.high:
                      self.ohlc.low = self.data.low[0]
                      self.Trend.Position = len(self.data.low)
                  # after 20 bars (excluding the first) no new low is made, we are not in a trend anymore
                  elif self.data.low[0] > self.ohlc.low:
                      if len(self.data.low) - self.Trend.Position >= 21:
                          self.Trend.Status = ""
                          self.Trend.Enter = ""
                          self.Trend.ExitParameters["20BarRule"] = True
                          self.Trend.bollinger_touch = ""
                          self.Trend.EMARule['Close1'] = False
                          self.Trend.EMARule['Close2'] = False
                          self.Trend.ExitParameters['20BarRule'] = True
                          
                  # if the bottom bollinger band was touched, reset the EMA rule
                  if self.data.low[0] <= self.BB.lines.bot[0]:
                      self.Trend.EMARule['Close1'] = False
                      self.Trend.EMARule['Close2'] = False
                      
                  if self.data.close[0] > self.SlowEMA[0] and self.data.close[0] > self.FastEMA[0]:
                      self.Trend.EMARule['Close1'] = True
      
                  if self.Trend.EMARule['Close1'] == True and self.data.close[0] < self.SlowEMA[0] and self.data.close[0] < self.FastEMA[0]:
                      self.Trend.EMARule['Close2'] = True
                      
                  if self.Trend.EMARule['Close1'] == True and self.Trend.EMARule['Close2'] == True and self.data.close[0] > self.SlowEMA[0] and self.data.close[0] > self.FastEMA[0]:
                      self.Trend.EMARule['Close1'] = False
                      self.Trend.EMARule['Close2'] = False
                      self.Trend.Status = ""
                      self.Trend.Enter = ""
                      self.Trend.ExitParameters['EMARule'] = True
                      self.Trend.bollinger_touch = ""
                      
              if self.Trend.Enter == "Downtrend entered" and True not in self.Trend.ExitParameters.values():
                  self.Trend[0] = -1
      
      1 Reply Last reply Reply Quote 0
      • D
        dasch last edited by

        you have some issues with your code:

                self.ohlc.open = self.datas[0].open[0]
                self.ohlc.high = self.datas[0].high[0]
                self.ohlc.low = self.datas[0].low[0]
                self.ohlc.close = self.datas[0].close[0]
        

        so change it to:

                self.ohlc.open = None
                self.ohlc.high = None
                self.ohlc.low = None
                self.ohlc.close = None
        

        you also don't need to add a minperiod, since next will be called, when your indicators are filled.

        if you want to init the attributes, you assign to the lines (?) ex. this way: self.Trend.Status = "", which works but is confusing, you could also set the inital ohlc values in nextstart:

        def nextstart(self):
                        self.ohlc.open = self.data.open[0]
                        self.ohlc.high = self.data.high[0]
                        self.ohlc.low = self.data.low[0]
                        self.ohlc.close = self.data.close[0]
        

        see: https://www.backtrader.com/docu/operating/

        1 Reply Last reply Reply Quote 0
        • D
          dasch last edited by

          oh, somehow the way it will not work that way is gone. In init you will not be able to access data that way you do it.

          Check out the Stage 1 - Stage 2 difference in this doc:
          https://www.backtrader.com/docu/concepts/#stage-1-operators-create-objects
          https://www.backtrader.com/docu/concepts/#stage-2-operators-true-to-nature

          1 Reply Last reply Reply Quote 0
          • D
            dasch last edited by

            So here is your fixed code, but to say it again, the way you set the values is confusing.

            You create a indicator line ohlc, then you set attributes to it, you never fill it with any data. Also you set attributes to the Trend line to keep track of the trend state.

            Better would be not adding the ohlc line, set all your tracking vars to the indicator.

            import backtrader as bt
            
            
            class Trend_Indicator(bt.Indicator):
                lines = ('Trend', 'ohlc')
                params = (
                    ('slowma', 21),
                    ('fastma', 8),
                )
            
                def __init__(self):
            
                    # Add Bollinger bands
                    self.BB = bt.indicators.BollingerBands(self.datas[0])
            
                    self.SlowEMA = bt.indicators.EMA(
                        self.datas[0], period=self.params.slowma)
                    self.FastEMA = bt.indicators.EMA(
                        self.datas[0], period=self.params.fastma)
            
                    self.Trend.bollinger_touch = ""
                    self.Trend.Status = ""
                    self.Trend.Enter = ""
                    self.Trend.ExitParameters = {
                        "20BarRule": False, "EMARule": False, "OppositeBollingerTouch": False}
                    self.Trend.EMARule = {"Close1": False, "Close2": False}
                    self.Trend.Position = 0
                    self.Trend.Test = 0
            
                def nextstart(self):
                    self.ohlc.open = self.datas[0].open[0]
                    self.ohlc.high = self.datas[0].high[0]
                    self.ohlc.low = self.datas[0].low[0]
                    self.ohlc.close = self.datas[0].close[0]
            
                def next(self):
            
                    if self.Trend.bollinger_touch == "Top" and self.data.low[0] > self.BB.lines.bot[0] and self.Trend.Enter == "":
                        # if the upper bollinger band was touched and the candle we have now makes the highest high and highest close,
                        # we enter in an uptrend
                        if self.data.high[0] > self.ohlc.high and self.data.close[0] > self.ohlc.close:
                            self.Trend.Enter = "Uptrend entered"
                            self.ohlc.high = self.data.high[0]
                            self.Trend.Status = "Up"
                            self.Trend.ExitParameters["OppositeBollingerTouch"] = False
                            self.Trend.ExitParameters["20BarRule"] = False
                            self.Trend.ExitParameters["EMARule"] = False
                            self.Trend.Position = len(self.ohlc)
                            self.Trend.Test = len(self.data.high)
                        if self.data.high[0] > self.ohlc.high:
                            self.ohlc.high = self.data.high[0]
                        if self.data.close[0] > self.ohlc.close:
                            self.ohlc.close = self.data.close[0]
            
                    # we enter in a downtrend
                    elif self.Trend.bollinger_touch == 'Bottom' and self.data.high[0] < self.BB.lines.top[0] and self.Trend.Enter == "":
                        # if the bottom bollinger band was touched and the candle we have now makes the lowest low and lowest close,
                        # we enter in a downtrend
                        if self.data.low[0] < self.ohlc.low and self.data.close[0] < self.ohlc.close:
                            self.Trend.Enter = "Downtrend entered"
                            self.ohlc.low = self.data.low[0]
                            self.Trend.Status = "Down"
                            self.Trend.ExitParameters["OppositeBollingerTouch"] = False
                            self.Trend.ExitParameters["20BarRule"] = False
                            self.Trend.ExitParameters["EMARule"] = False
                            self.Trend.Position = len(self.ohlc)
                            self.Trend.Test = len(self.data.low)
                        if self.data.low[0] < self.ohlc.low:
                            self.ohlc.low = self.data.low[0]
                        if self.data.close[0] < self.ohlc.close:
                            self.ohlc.close = self.data.close[0]
            
                    elif self.Trend.bollinger_touch == "":
                        # look for a top bollinger touch, then store that bar's data
                        if self.data.high[0] >= self.BB.lines.top[0] and self.data.low[0] > self.BB.lines.bot[0]:
                            self.ohlc.open = self.data.open[0]
                            self.ohlc.high = self.data.high[0]
                            self.ohlc.low = self.data.low[0]
                            self.ohlc.close = self.data.close[0]
                            self.Trend.bollinger_touch = "Top"
            
                        elif self.data.low[0] <= self.BB.lines.bot[0] and self.data.high[0] < self.BB.lines.top[0]:
                            self.ohlc.open = self.data.open[0]
                            self.ohlc.high = self.data.high[0]
                            self.ohlc.low = self.data.low[0]
                            self.ohlc.close = self.data.close[0]
                            self.Trend.bollinger_touch = "Bottom"
            
                    # if the upper bollinger band was touched but now the lower bollinger band got touched, the upper bollinger touch resets
                    if self.Trend.bollinger_touch == "Top" and self.data.low[0] <= self.BB.lines.bot[0]:
                            self.Trend.bollinger_touch = "Bottom"
                            self.ohlc.open = self.data.open[0]
                            self.ohlc.high = self.data.high[0]
                            self.ohlc.low = self.data.low[0]
                            self.ohlc.close = self.data.close[0]
            
                    # if the bottom bollinger band was touched but now the top bollinger band got touched, the bottom bollinger touch resets
                    elif self.Trend.bollinger_touch == "Bottom" and self.data.high[0] >= self.BB.lines.top[0]:
                            self.Trend.bollinger_touch = "Top"
                            self.ohlc.open = self.data.open[0]
                            self.ohlc.high = self.data.high[0]
                            self.ohlc.low = self.data.low[0]
                            self.ohlc.close = self.data.close[0]
            
                    # we are in an uptrend
                    if self.Trend.Status == "Up":
                        # if the opposite bollinger band was touched, we exit the uptrend
                        if self.data.low[0] <= self.BB.lines.bot[0]:
                            self.Trend.Status = ""
                            self.Trend.Enter = ""
                            self.Trend.ExitParameters["OppositeBollingerTouch"] = True
                            self.Trend.bollinger_touch = "Bottom"
                            self.Trend.EMARule['Close1'] = False
                            self.Trend.EMARule['Close2'] = False
                            self.ohlc.open = self.data.open[0]
                            self.ohlc.high = self.data.high[0]
                            self.ohlc.low = self.data.low[0]
                            self.ohlc.close = self.data.close[0]
                        # if a fresh high is made, keep track of the position
                        if self.data.high[0] > self.ohlc.high:
                            self.ohlc.high = self.data.high[0]
                            self.Trend.Position = len(self.data.high)
                        # after 20 bars (excluding the first) no new high is made, we are not in a trend anymore
                        elif self.data.high[0] < self.ohlc.high:
                            if len(self.data.high) - self.Trend.Position >= 21:
                                self.Trend.Status = ""
                                self.Trend.Enter = ""
                                self.Trend.ExitParameters["20BarRule"] = True
                                self.Trend.bollinger_touch = "Bottom"
                                self.Trend.EMARule['Close1'] = False
                                self.Trend.EMARule['Close2'] = False
                                self.Trend.ExitParameters['20BarRule'] = True
            
                        # if the top bollinger band was touched, reset the EMA rule
                        if self.data.high[0] >= self.BB.lines.top[0]:
                            self.Trend.EMARule['Close1'] = False
                            self.Trend.EMARule['Close2'] = False
            
                        if self.data.close[0] < self.SlowEMA[0] and self.data.close[0] < self.FastEMA[0]:
                            self.Trend.EMARule['Close1'] = True
            
                        if self.Trend.EMARule['Close1'] == True and self.data.close[0] > self.SlowEMA[0] and self.data.close[0] > self.FastEMA[0]:
                            self.Trend.EMARule['Close2'] = True
            
                        if self.Trend.EMARule['Close1'] == True and self.Trend.EMARule['Close2'] == True and self.data.close[0] < self.SlowEMA[0] and self.data.close[0] < self.FastEMA[0]:
                            self.Trend.EMARule['Close1'] = False
                            self.Trend.EMARule['Close2'] = False
                            self.Trend.Status = ""
                            self.Trend.Enter = ""
                            self.Trend.ExitParameters['EMARule'] = True
                            self.Trend.bollinger_touch = ""
            
                    if self.Trend.Enter == "Uptrend entered" and True not in self.Trend.ExitParameters.values():
                        self.Trend[0] = 1
            
                    # we are in a downtrend
                    if self.Trend.Status == "Down":
                        # if the opposite bollinger band was touched, we exit the downtrend
                        if self.data.high[0] >= self.BB.lines.top[0]:
                            self.Trend.Status = ""
                            self.Trend.Enter = ""
                            self.Trend.ExitParameters["OppositeBollingerTouch"] = True
                            self.Trend.bollinger_touch = "Top"
                            self.Trend.EMARule['Close1'] = False
                            self.Trend.EMARule['Close2'] = False
                            self.ohlc.open = self.data.open[0]
                            self.ohlc.high = self.data.high[0]
                            self.ohlc.low = self.data.low[0]
                            self.ohlc.close = self.data.close[0]
            
                        # if a fresh low is made, keep track of the position
                        if self.data.low[0] < self.ohlc.high:
                            self.ohlc.low = self.data.low[0]
                            self.Trend.Position = len(self.data.low)
                        # after 20 bars (excluding the first) no new low is made, we are not in a trend anymore
                        elif self.data.low[0] > self.ohlc.low:
                            if len(self.data.low) - self.Trend.Position >= 21:
                                self.Trend.Status = ""
                                self.Trend.Enter = ""
                                self.Trend.ExitParameters["20BarRule"] = True
                                self.Trend.bollinger_touch = ""
                                self.Trend.EMARule['Close1'] = False
                                self.Trend.EMARule['Close2'] = False
                                self.Trend.ExitParameters['20BarRule'] = True
            
                        # if the bottom bollinger band was touched, reset the EMA rule
                        if self.data.low[0] <= self.BB.lines.bot[0]:
                            self.Trend.EMARule['Close1'] = False
                            self.Trend.EMARule['Close2'] = False
            
                        if self.data.close[0] > self.SlowEMA[0] and self.data.close[0] > self.FastEMA[0]:
                            self.Trend.EMARule['Close1'] = True
            
                        if self.Trend.EMARule['Close1'] == True and self.data.close[0] < self.SlowEMA[0] and self.data.close[0] < self.FastEMA[0]:
                            self.Trend.EMARule['Close2'] = True
            
                        if self.Trend.EMARule['Close1'] == True and self.Trend.EMARule['Close2'] == True and self.data.close[0] > self.SlowEMA[0] and self.data.close[0] > self.FastEMA[0]:
                            self.Trend.EMARule['Close1'] = False
                            self.Trend.EMARule['Close2'] = False
                            self.Trend.Status = ""
                            self.Trend.Enter = ""
                            self.Trend.ExitParameters['EMARule'] = True
                            self.Trend.bollinger_touch = ""
            
                    if self.Trend.Enter == "Downtrend entered" and True not in self.Trend.ExitParameters.values():
                        self.Trend[0] = -1
            
            Jens Halsberghe 1 Reply Last reply Reply Quote 0
            • A
              ab_trader last edited by

              Indicator lines should be calculated as follow

              self.lines.Trend = something
              self.lines.ohlc = something
              

              You may want to read docs on indicator development one more time instead of hitting the wall continuously.

              D 1 Reply Last reply Reply Quote 1
              • D
                dasch @ab_trader last edited by

                @ab_trader it would be good practice, i assume. I prefer also to use self.lines.x . But since backtrader creates these shortcuts, why not use them?

                A 1 Reply Last reply Reply Quote 0
                • D
                  dasch last edited by

                  here is a cleaned up version of the indicator.

                  Trend_Indicator(bt.Indicator):
                      lines = ('trend',)
                      params = (
                          ('slow_ema', 21),
                          ('fast_ema', 8),
                      )
                  
                      def __init__(self):
                  
                          # Add Bollinger bands
                          self.bb = bt.indicators.BollingerBands()
                  
                          self.slow_ema = bt.indicators.EMA(period=self.params.slow_ema)
                          self.fast_ema = bt.indicators.EMA(period=self.params.fast_ema)
                  
                          self.ohlc = {"o": None, "h": None, "l": None, "c": None}
                  
                          self.trend_bollinger_touch = 0
                          self.trend_status = 0
                          self.trend_enter = 0
                          self.trend_exit_params = {
                              "20BarRule": False,
                              "EMARule": False,
                              "OppositeBollingerTouch": False}
                          self.trend_ema_rule = {
                              "Close1": False,
                              "Close2": False}
                          self.trend_position = 0
                          self.trend_test = 0
                  
                      def nextstart(self):
                          self._update_ohlc()
                  
                      def next(self):
                          if (self.trend_bollinger_touch == 1
                                  and self.data.low[0] > self.bb.lines.bot[0]
                                  and self.trend_enter == 0):
                              # if the upper bollinger band was touched and the candle
                              # we have now makes the highest high and highest close,
                              # we enter in an uptrend
                              if (self.data.high[0] > self.ohlc["h"]
                                      and self.data.close[0] > self.ohlc["c"]):
                                  self._update_ohlc(["h"])
                                  self.trend_enter = 1
                                  self.trend_status = 1
                                  self.trend_exit_params["OppositeBollingerTouch"] = False
                                  self.trend_exit_params["20BarRule"] = False
                                  self.trend_exit_params["EMARule"] = False
                                  self.trend_position = len(self.ohlc)
                                  self.trend_test = len(self.data.high)
                              if self.data.high[0] > self.ohlc["h"]:
                                  self._update_ohlc(["h"])
                              if self.data.close[0] > self.ohlc["c"]:
                                  self._update_ohlc(["c"])
                  
                          # we enter in a downtrend
                          elif (self.trend_bollinger_touch == -1
                                  and self.data.high[0] < self.bb.lines.top[0]
                                  and self.trend_enter == 0):
                              # if the bottom bollinger band was touched and the candle we
                              # have now makes the lowest low and lowest close, we enter
                              # in a downtrend
                              if (self.data.low[0] < self.ohlc["l"]
                                      and self.data.close[0] < self.ohlc["c"]):
                                  self._update_ohlc(["l"])
                                  self.trend_enter = -1
                                  self.trend_status = -1
                                  self.trend_exit_params["OppositeBollingerTouch"] = False
                                  self.trend_exit_params["20BarRule"] = False
                                  self.trend_exit_params["EMARule"] = False
                                  self.trend_position = len(self.ohlc)
                                  self.trend_test = len(self.data.low)
                              if self.data.low[0] < self.ohlc["l"]:
                                  self._update_ohlc(["l"])
                              if self.data.close[0] < self.ohlc["c"]:
                                  self._update_ohlc(["c"])
                  
                          elif self.trend_bollinger_touch == 0:
                              # look for a top bollinger touch, then store that bar's data
                              if (self.data.high[0] >= self.bb.lines.top[0]
                                      and self.data.low[0] > self.bb.lines.bot[0]):
                                  self._update_ohlc()
                                  self.trend_bollinger_touch = 1
                  
                              elif (self.data.low[0] <= self.bb.lines.bot[0]
                                      and self.data.high[0] < self.bb.lines.top[0]):
                                  self._update_ohlc()
                                  self.trend_bollinger_touch = -1
                  
                          # if the upper bollinger band was touched but now the lower bollinger
                          # band got touched, the upper bollinger touch resets
                          if (self.trend_bollinger_touch == 1
                                  and self.data.low[0] <= self.bb.lines.bot[0]):
                              self._update_ohlc()
                              self.trend_bollinger_touch = -1
                  
                          # if the bottom bollinger band was touched but now the top bollinger
                          # band got touched, the bottom bollinger touch resets
                          elif (self.trend_bollinger_touch == -1
                                  and self.data.high[0] >= self.bb.lines.top[0]):
                              self._update_ohlc()
                              self.trend_bollinger_touch = 1
                  
                          # we are in an uptrend
                          if self.trend_status == 1:
                              # if the opposite bollinger band was touched, we exit the uptrend
                              if self.data.low[0] <= self.bb.lines.bot[0]:
                                  self.trend_status = 0
                                  self.trend_enter = 0
                                  self.trend_exit_params["OppositeBollingerTouch"] = True
                                  self.trend_bollinger_touch = -1
                                  self.trend_ema_rule['Close1'] = False
                                  self.trend_ema_rule['Close2'] = False
                                  self._update_ohlc()
                              # if a fresh high is made, keep track of the position
                              if self.data.high[0] > self.ohlc["h"]:
                                  self._update_ohlc(["h"])
                                  self.trend_position = len(self.data.high)
                              # after 20 bars (excluding the first) no new high is made, we are
                              # not in a trend anymore
                              elif self.data.high[0] < self.ohlc["h"]:
                                  if len(self.data.high) - self.trend_position >= 21:
                                      self.trend_status = 0
                                      self.trend_enter = 0
                                      self.trend_bollinger_touch = -1
                                      self.trend_exit_params["20BarRule"] = True
                                      self.trend_ema_rule['Close1'] = False
                                      self.trend_ema_rule['Close2'] = False
                                      self.trend_exit_params['20BarRule'] = True
                  
                              # if the top bollinger band was touched, reset the EMA rule
                              if self.data.high[0] >= self.bb.lines.top[0]:
                                  self.trend_ema_rule['Close1'] = False
                                  self.trend_ema_rule['Close2'] = False
                  
                              if (self.data.close[0] < self.slow_ema[0]
                                      and self.data.close[0] < self.fast_ema[0]):
                                  self.trend_ema_rule['Close1'] = True
                  
                              if (self.trend_ema_rule['Close1'] is True
                                      and self.data.close[0] > self.slow_ema[0]
                                      and self.data.close[0] > self.fast_ema[0]):
                                  self.trend_ema_rule['Close2'] = True
                  
                              if (self.trend_ema_rule['Close1'] is True
                                      and self.trend_ema_rule['Close2'] is True
                                      and self.data.close[0] < self.slow_ema[0]
                                      and self.data.close[0] < self.fast_ema[0]):
                                  self.trend_ema_rule['Close1'] = False
                                  self.trend_ema_rule['Close2'] = False
                                  self.trend_exit_params['EMARule'] = True
                                  self.trend_enter = 0
                                  self.trend_status = 0
                                  self.trend_bollinger_touch = 0
                  
                          # we are in a downtrend
                          if self.trend_status == -1:
                              # if the opposite bollinger band was touched, we exit the downtrend
                              if self.data.high[0] >= self.bb.lines.top[0]:
                                  self.trend_status = 0
                                  self.trend_enter = 0
                                  self.trend_bollinger_touch = 1
                                  self.trend_exit_params["OppositeBollingerTouch"] = True
                                  self.trend_ema_rule['Close1'] = False
                                  self.trend_ema_rule['Close2'] = False
                                  self._update_ohlc()
                  
                              # if a fresh low is made, keep track of the position
                              if self.data.low[0] < self.ohlc["h"]:
                                  self._update_ohlc(["l"])
                                  self.trend_position = len(self.data.low)
                              # after 20 bars (excluding the first) no new low is made, we are
                              # not in a trend anymore
                              elif self.data.low[0] > self.ohlc["l"]:
                                  if len(self.data.low) - self.trend_position >= 21:
                                      self.trend_status = 0
                                      self.trend_enter = 0
                                      self.trend_bollinger_touch = 0
                                      self.trend_exit_params["20BarRule"] = True
                                      self.trend_ema_rule['Close1'] = False
                                      self.trend_ema_rule['Close2'] = False
                                      self.trend_exit_params['20BarRule'] = True
                  
                              # if the bottom bollinger band was touched, reset the EMA rule
                              if self.data.low[0] <= self.bb.lines.bot[0]:
                                  self.trend_ema_rule['Close1'] = False
                                  self.trend_ema_rule['Close2'] = False
                  
                              if (self.data.close[0] > self.slow_ema[0]
                                      and self.data.close[0] > self.fast_ema[0]):
                                  self.trend_ema_rule['Close1'] = True
                  
                              if (self.trend_ema_rule['Close1'] is True
                                      and self.data.close[0] < self.slow_ema[0]
                                      and self.data.close[0] < self.fast_ema[0]):
                                  self.trend_ema_rule['Close2'] = True
                  
                              if (self.trend_ema_rule['Close1'] is True
                                      and self.trend_ema_rule['Close2'] is True
                                      and self.data.close[0] > self.slow_ema[0]
                                      and self.data.close[0] > self.fast_ema[0]):
                                  self.trend_status = 0
                                  self.trend_enter = 0
                                  self.trend_bollinger_touch = 0
                                  self.trend_ema_rule['Close1'] = False
                                  self.trend_ema_rule['Close2'] = False
                                  self.trend_exit_params['EMARule'] = True
                  
                          # update line
                          if (self.trend_enter == -1
                                  and True not in self.trend_exit_params.values()):
                              self.lines.trend[0] = -1
                          elif (self.trend_enter == 1
                                  and True not in self.trend_exit_params.values()):
                              self.lines.trend[0] = 1
                  
                      def _update_ohlc(self, values=["o", "h", "l", "c"]):
                          if "o" in values:
                              self.ohlc["o"] = self.data.open[0]
                          if "h" in values:
                              self.ohlc["h"] = self.data.high[0]
                          if "l" in values:
                              self.ohlc["l"] = self.data.low[0]
                          if "c" in values:
                              self.ohlc["c"] = self.data.close[0]
                  
                  1 Reply Last reply Reply Quote 2
                  • A
                    ab_trader @dasch last edited by

                    @dasch I didn't see indicators made this way in the docs or blog posts. Can you share a link?

                    D 1 Reply Last reply Reply Quote 0
                    • D
                      dasch @ab_trader last edited by

                      @ab_trader here: https://www.backtrader.com/docu/inddev/

                      Let’s recall that self.lines.dummyline is the long notation and that it can be shortened to:

                      self.l.dummyline
                      

                      and even to:

                      self.dummyline
                      

                      The latter being only possible if the code has not obscured this with a member attribute.

                      A 1 Reply Last reply Reply Quote 2
                      • A
                        ab_trader @dasch last edited by

                        @dasch I see, thank you. Looks like I just forgot it since it was not used in the original bt scripts I've used as examples.

                        D 1 Reply Last reply Reply Quote 0
                        • D
                          dasch @ab_trader last edited by

                          @ab_trader there are a lot of shortcuts to different lines, which are not used that much in examples, so it would only make sense to use them, when you know what you are doing.

                          Thats why your statement is mostly the way to go to use self.lines.x (which also is more readable in code)

                          A 1 Reply Last reply Reply Quote 1
                          • Jens Halsberghe
                            Jens Halsberghe @dasch last edited by

                            @dasch thanks a lot. much appreciated
                            Yes it probably could be a lot better than I have created it. I'm still quite new to backtrader so learning bit by bit.
                            what was then actually the problem which caused the error?

                            D 1 Reply Last reply Reply Quote 0
                            • D
                              dasch @Jens Halsberghe last edited by

                              @Jens-Halsberghe the actual problem was just the assignment of ohlc values in init:

                                      self.ohlc.open = self.datas[0].open[0]
                                      self.ohlc.high = self.datas[0].high[0]
                                      self.ohlc.low = self.datas[0].low[0]
                                      self.ohlc.close = self.datas[0].close[0]
                              
                              1 Reply Last reply Reply Quote 1
                              • A
                                ab_trader @dasch last edited by

                                @dasch said in Resampling issues + adding multiple timeframes:

                                there are a lot of shortcuts to different lines, which are not used that much in examples, so it would only make sense to use them, when you know what you are doing.

                                I totally agree.

                                1 Reply Last reply Reply Quote 1
                                • 1
                                • 2
                                • 2 / 2
                                • First post
                                  Last post
                                Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                                $(document).ready(function () { app.coldLoad(); }); }