For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

How to calculate indicator line using prior period values?



  • I'm attempting to write an indicator based off a projected moving average formula (CP2) which also has Lamberts Marker Direction Formula (MDI) in there as well.

    My issue is that I need to use prior period values of CP2 to calculate the MDI formula but I'm not sure of the best approach as I understand that most of the calculations should be done in the init() function.

    Here is what I have so far and as you can see I have attempted to use an array to store the CP2 values which is probably not best practice but getting the 'IndexError: list index out of range' error because it can't access the values. I guess I mostly need help in how to write this in the best practice format.

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    # Import the backtrader platform
    import backtrader as bt
    import math
    from decimal import *
    
    class ProjectedMovingAverageIndicator(bt.Indicator):
    
      lines = ('CP2','MDI',)
      params = (('periodSlow', 100),('periodFast', 25),('movav', bt.indicators.MovAv.Simple),)
      plotinfo = dict(subplot=True)
      plotlines = dict(
        CP2=dict(_samecolor=False),
        MDI=dict(_samecolor=False),
        )
    
      def __init__(self):
        self.addminperiod(self.params.periodSlow)
    
        # Calculate moving averages
        self.movavSlow = self.p.movav(self.data.close, period=self.p.periodSlow)
        self.movavFast = self.p.movav(self.data.close, period=self.p.periodFast)
        self.CP2 = []
    
      def next(self):
    
        # Perry Kaufman project moving average
        self.CP2.append(self.p.periodSlow * ((self.movavSlow[0] - self.data.close[-1]) / self.p.periodSlow) - ((self.movavFast[0] - self.data.close[-1]) / self.p.periodFast))
    
        # Market Direction Indicator
        MDI = 100 * (self.CP2[-2] - self.CP2[-1]) / ((self.data.close[-1] + self.data.close[-1]) / 2)
    
        # Create lines
        self.l.CP2[0] = self.CP2[-1]
        self.l.MDI[0] = MDI
    
        print("CP2: ", CP2[-1], " MDI: ", MDI)
    

    Thanks



  • IMHO the better way is to define the CP2 line using delaying indexing. See Delayed Indexing Concept.

    Probably something like:

      def __init__(self):
        self.addminperiod(self.params.periodSlow)
    
        # Calculate moving averages
        self.movavSlow = self.p.movav(self.data.close, period=self.p.periodSlow)
        self.movavFast = self.p.movav(self.data.close, period=self.p.periodFast)
    
        # Perry Kaufman project moving average
        self.CP2 = self.p.periodSlow * ((self.movavSlow(0) - self.data.close(-1)) / self.p.periodSlow) - ((self.movavFast(0) - self.data.close(-1)) / self.p.periodFast)
    
      def next(self):
        # Market Direction Indicator
        MDI = 100 * (self.CP2[-2] - self.CP2[-1]) / ((self.data.close[-1] + self.data.close[-1]) / 2)
    
        # Create lines
        self.l.CP2[0] = self.CP2[-1]
        self.l.MDI[0] = MDI
    
        print("CP2: ", self.CP2[-1], " MDI: ", MDI)
    
    


  • @vladisld said in How to calculate indicator line using prior period values?:

    Market Direction Indicator

    MDI = 100 * (self.CP2[-2] - self.CP2[-1]) / ((self.data.close[-1] + self.data.close[-1]) / 2)
    
    # Create lines
    self.l.CP2[0] = self.CP2[-1]
    self.l.MDI[0] = MDI
    
    print("CP2: ", self.CP2[-1], " MDI: ", MDI)
    

    Amazing, thanks @vladisld!


Log in to reply
 

});