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



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



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


Log in to reply
 

});