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/

    Lookback period for custom indicator

    Indicators/Strategies/Analyzers
    2
    2
    268
    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.
    • greenkode
      greenkode last edited by

      Hi,
      I am trying to implement a trading strategy based on this custom indicator.

      https://www.backtrader.com/blog/2019-05-20-momentum-strategy/momentum-strategy/

      def momentum_func(the_array):
          r = np.log(the_array)
          slope, _, rvalue, _, _ = linregress(np.arange(len(r)), r)
          annualized = (1 + slope) ** 252
          return annualized * (rvalue ** 2)
      
      
      class Momentum(bt.ind.OperationN):
          lines = ('trend',)
          params = dict(period=50)
          func = momentum_func
      

      Params

      params = dict(
              momentum=Momentum,
              momentum_period=20,
      
              volatr=bt.ind.ATR,
              vol_period=20,
              rebal_weekday=6,
      
              minimum_momentum=40
          )
      

      In the __init__ method. I'm calculating like this

              for d in self.datas:
                  self.inds[d]['momentum'] = self.p.momentum(d, period=20)
                  self.inds[d]['volatility'] = self.p.volatr(d, period=20)
      

      Notice that I'm passing the same period to both indicators.
      However when I look at the calculated values. It has a value at the 20th index.

      # Momentum indicator
      array('d', [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 137085.1866192367, 175141.41671668983, ...])
      

      The ATR indicator on the other hand only has a value at the 21st index.

      # ATR
      array('d', [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, 3.4824999999999817, 3.3083749999999825, ...])
      

      Is my custom indicator suffering from lookahead bias? How can I resolve this?

      On further investigation, here's the first array being passed into the momentum_func

      array('d', [4378.48, 4380.0, 4310.0, 4208.59, 4292.43, 4369.0, 4423.0, 4640.0, 4786.95, 4783.06, 4821.43, 5430.0, 5649.98, 5869.99, 5709.99, 5760.02, 5595.0, 5512.06, 5683.9, 6010.01])
      

      However in the next() method, if I call get(). here's the result I get.

      datum.close.get(size=self.p.volatility_window)
      
      array('d', [4380.0, 4310.0, 4208.59, 4292.43, 4369.0, 4423.0, 4640.0, 4786.95, 4783.06, 4821.43, 5430.0, 5649.98, 5869.99, 5709.99, 5760.02, 5595.0, 5512.06, 5683.9, 6010.01, 6024.97])
      

      So why is the data being shifted by 1?

      1 Reply Last reply Reply Quote 0
      • run-out
        run-out last edited by

        The reason you are getting the discprency is the nature of how ATR is calculated. ATR has the following definition:

        The range of a day's trading is simply [high − low]. The true range extends it to yesterday's closing price if it was outside of today's range.

        Note that ATR must have the ability to look back one period. This one period look back requirement means that all ATR calculations will need n+1 periods for warmup calculation.

        You can check this yourself by putting say bt.ind.SMA by itself for n periods (5 in this case):

        2015-07-08, Close: 30.64, sma: 31.37, 
        2015-07-09, Close: 30.02, sma: 31.04, 
        

        Now add in the ATR with the same period, and you will see the results start one period later.

        2015-07-09, Close: 30.02, sma: 31.04, vol:  0.64
        2015-07-10, Close: 30.82, sma: 30.88, vol:  0.70
        

        None of this has anything to do with your function, but is a matter of how ATR is calculated.

        RunBacktest.com

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