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/

    ATR TP/SLs producing unexpected results

    Indicators/Strategies/Analyzers
    2
    4
    64
    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.
    • A
      adenosine last edited by

      Hi there. I'm working to port over my PineScript strategies to Backtrader and I've gotten mostly everything to work except for the ATR TP/SL brackets.

      The code below is intended to grab the ATR values when the buying condition is met. If the buying condition is met and there is no active position, the ATR TP/SL is calculated based on the ATR value at the time and adds/subtracts it from the current price based on whether a long/short order is being entered into. Subsequently while a position is open, a check is made to determine if price touches either the TP/SL levels set and exits accordingly.

      from app import buy
      import backtrader as bt
      import backtrader.analyzers as btanalyzers
      import datetime
      
      cerebro = bt.Cerebro()
      cerebro.broker.set_cash(1000000.0)
      fromdate = datetime.datetime.strptime('2020-06-01', '%Y-%m-%d')
      todate = datetime.datetime.strptime('2021-03-12', '%Y-%m-%d')
      
      class test_strategy(bt.Strategy):
          
          params = (#Ichimoku settings
                    ('conversion_len',     16  ),
                    ('base_len',           7   ),
                    ('laggingSpan2_len',   20  ),           
                    #ATR settings
                    ('ATR_len',            12  ), 
                    ('ATRLTP_multi',       1.5 ), 
                    ('ATRLSL_multi',       1.7 ),
                    ('ATRSTP_multi',       2.2 ),
                    ('ATRSSL_multi',       2.1 ),         
                   )
      
          def __init__(self):
              self.ichimoku = bt.indicators.Ichimoku(tenkan=self.p.conversion_len, kijun=self.p.base_len, senkou=self.p.laggingSpan2_len)
              self.ATR = bt.indicators.AverageTrueRange(self.data, period=self.p.ATR_len)
              
              belowCloud = bt.indicators.Min(self.ichimoku.lines.senkou_span_a, self.ichimoku.lines.senkou_span_b)
                      
              self.buying = self.datas[0].close(0) > self.ichimoku.lines.kijun_sen        
              self.selling =  bt.And(self.datas[0].close(0) < belowCloud, self.datas[0].close(0) < self.ichimoku.lines.kijun_sen)        
      
          def start(self):
              self.order = None    
          
          def next(self):
              curr_close = self.data.close[0]
              if self.buying and not self.position:
                  self.buy(size=1)
                  self.ATRL_TP = (self.ATR[0] * self.p.ATRLTP_multi) + curr_close
                  self.ATRL_SL = curr_close - (self.ATR[0] * self.p.ATRLSL_multi)
                  
              if self.selling and not self.position:
                  self.sell(size=1)
                  self.ATRS_TP = (self.ATR[0] * self.p.ATRSTP_multi) + curr_close
                  self.ATRS_SL = curr_close - (self.ATR[0] * self.p.ATRSSL_multi)        
      
              if self.position.size > 0:
                  if curr_close >= self.ATRL_TP: 
                      self.close() 
                      self.ATRL_TP = 0.0    
                  elif curr_close <= self.ATRL_SL:
                      self.close()
                      self.ATRL_SL = 0.0
              elif self.position.size < 0:
                  if curr_close <= self.ATRS_TP: 
                      self.close()       
                      self.ATRS_TP = 0.0   
                  elif curr_close >= self.ATRS_SL:
                      self.close()    
                      self.ATRS_SL = 0.0    
                      
      data = bt.feeds.GenericCSVData(dataname='data/BTC2H.csv', dtformat=2, compression=120, timeframe=bt.TimeFrame.Minutes, fromdate=fromdate, todate=todate)
      
      cerebro.adddata(data)
      cerebro.addstrategy(test_strategy)
      cerebro.addanalyzer(btanalyzers.PositionAnalyzer)
      
      cerebro.run()
      cerebro.plot(style='candle', barup='green', bardown='red')
      

      The TP/SL brackets produced in backtesting don't match up with what I'm expecting though. In the analyzer output below, the ATR value is 1180.28 for when the first order (2021-01-04) is entered which should produce a TP level of 1758.015. However the TP for this order is 1771.78 which doesn't match. My guess is that the ATR is being recalculated somewhere but I can't find when and where.

      cca287d9-6b1b-40f0-b739-23aeb4acc08b-image.png

      Thanks for reading. Is there something I'm missing here?

      A E 2 Replies Last reply Reply Quote 0
      • A
        adenosine @adenosine last edited by

        @adenosine said in ATR TP/SLs producing unexpected results:

        The TP/SL brackets produced in backtesting don't match up with what I'm expecting though. In the analyzer output below, the ATR value is 1180.28 for when the first order (2021-01-04) is entered which should produce a TP level of 1758.015. However the TP for this order is 1771.78 which doesn't match. My guess is that the ATR is being recalculated somewhere but I can't find when and where.

        Sorry, wrong TP value here. Instead of 1758.015, it should be 1770.42

        1 Reply Last reply Reply Quote 0
        • E
          EMR @adenosine last edited by

          @adenosine The best way to know if the ATR value match what you expect it to be would be to log its value, along with entry price (as you may know for market orders, it is supposed to be the open of next bar)
          I may have made a mistake checking it, but when I ported over to backtrader some strats with ATR-dependant TP & SL, and ATR calculation in backtrader seemed good to me.

          BTW you can use bracket orders : https://www.backtrader.com/docu/order-creation-execution/bracket/bracket/
          BTW2 : Maybe it is by design but just in case : your sell bracket (under "if self.selling and not self.position:") looks like your buy bracket : TP above price, SL under.

          A 1 Reply Last reply Reply Quote 3
          • A
            adenosine @EMR last edited by

            @emr Interesting. After switching to bracketed orders it worked. Still don't really understand why though.

            And you're right, the TP/SL was flipped around for the sell order. Thanks for the extra set of eyes.

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