Develop Heikinashi Indicators



  • Thank you for develop best backtrading app!

    I have problem when I develop Heikin-Ashi Indicators.
    I can't get value that i want.
    when i want develop autocorrelation indicators, what should I do?

    My code show below

    from datetime import datetime
    import backtrader as bt
    
    class HeikinAshi(bt.indicators.PeriodN):
        """
        Heikin Ashi candlesticks:
        
        Parameter:
            No needs
        
        Description:
            Heikin-Ashi candlesticks are a weighted version of candlesticks calculated with the following formula
            
        Formula:
            h_close = (open + high + low + close) / 4
            h_high = maximum of high, open, or close (whichever is highest)
            h_low = minimum of low, open, or close (whichever is lowest)
            h_open = (open of previous bar + close of previous bar) / 2
            
        See also:
            https://en.wikipedia.org/wiki/Candlestick_chart#Heikin_Ashi_candlesticks
            http://stockcharts.com/school/doku.php?id=chart_school:chart_analysis:heikin_ashi
        """
        lines = ('signal', 'ha_close', 'ha_open')
    
        def __init__(self):
            super(HeikinAshi, self).__init__()
    
            open = self.data.open
            high = self.data.high
            low = self.data.low
            close = self.data.close
    
            self.ha_close = (open + high + low + close) / 4
            # h_high = bt.Max(open, high, low, close)
            # h_low = bt.Min(open, high, low, close)
            self.ha_open = (self.ha_open(-1) + self.ha_close(-1)) / 2
    
        def next(self):
            print(self.ha_open[0])  # <- Value is 'nan', I wanna numeric
        
    class NoStrategy(bt.Strategy):
        def __init__(self):
            HeikinAshi(self.data)
    
    if __name__ == '__main__':
        cerebro = bt.Cerebro()
        cerebro.addstrategy(NoStrategy)
        data0 = bt.feeds.YahooFinanceData(dataname='YHOO', fromdate=datetime(2011, 1, 1),
                                          todate=datetime(2012, 12, 31))
        cerebro.adddata(data0)
        
        cerebro.run()
        #cerebro.plot()
    


  • I resolve by myself :D

    I use once method instead of next.

    from datetime import datetime
    import backtrader as bt
    
    class HeikinAshi(bt.Indicator):
        """
        Heikin Ashi candlesticks:
        
        Parameter:
            No needs
        
        Description:
            Heikin-Ashi candlesticks are a weighted version of candlesticks calculated with the following formula
            
        Formula:
            h_close = (open + high + low + close) / 4
            h_high = maximum of high, open, or close (whichever is highest)
            h_low = minimum of low, open, or close (whichever is lowest)
            h_open = (open of previous bar + close of previous bar) / 2
            
        See also:
            https://en.wikipedia.org/wiki/Candlestick_chart#Heikin_Ashi_candlesticks
            http://stockcharts.com/school/doku.php?id=chart_school:chart_analysis:heikin_ashi
        """
        lines = ('signal', 'ha_close', 'ha_open')
    
        def __init__(self):
            super(HeikinAshi, self).__init__()
    
            open = self.data.open
            high = self.data.high
            low = self.data.low
            close = self.data.close
    
            self.ha_close = (open + high + low + close) / 4
            # h_high = bt.Max(open, high, low, close)
            # h_low = bt.Min(open, high, low, close)
    
        def once(self, start, end):
            ha_close = self.ha_close.array
            ha_open = self.ha_open.array
    
            for i in range(start, end):
                if i == 1:
                    ha_open[i] = self.data.open[0]
                else:
                    ha_open[i] = (ha_open[i - 1] + ha_close[i - 1]) / 2
        
    class NoStrategy(bt.Strategy):
        def __init__(self):
            HeikinAshi(self.data)
    
    if __name__ == '__main__':
        cerebro = bt.Cerebro()
        cerebro.addstrategy(NoStrategy)
        data0 = bt.feeds.YahooFinanceData(dataname='YHOO', fromdate=datetime(2011, 1, 1),
                                          todate=datetime(2012, 12, 31))
        cerebro.adddata(data0)
        
        cerebro.run()
        #cerebro.plot()
    


  • I noticed simple code below.
    I think once method doesn't work when I use resampledata.

    def __init__(self):
            super(HeikinAshi, self).__init__()
            open = self.data.open
            high = self.data.high
            low = self.data.low
            close = self.data.close
    
            self.ha_open = open
    
            self.ha_close = (open + high + low + close) / 4
            # h_high = bt.Max(open, high, low, close)
            # h_low = bt.Min(open, high, low, close)
            self.ha_open = (self.ha_open(-1) + self.ha_close(-1)) / 2
    

  • administrators

    @santa3 said in Develop Heikinashi Indicators:

        self.ha_open = (self.ha_open(-1) + self.ha_close(-1)) / 2
    
    def next(self):
        print(self.ha_open[0])  # <- Value is 'nan', I wanna numeric
    

    The initial problem here is:

    • ha_open(-1) needs a seed value which is not being provided and the recursive calculation fails

      As such, the only value the platform can fill in advance is NaN and any calculation with Nan will return the same.

      A seed value could be provided during nextstart or oncestart. It is what the ExponentialMovingAverage for example does, by using a SimpleMovingAverage as the seed value.

    @santa3 said in Develop Heikinashi Indicators:

    def once(self, start, end):
        ha_close = self.ha_close.array
        ha_open = self.ha_open.array
    
        for i in range(start, end):
            if i == 1:
                ha_open[i] = self.data.open[0]
            else:
                ha_open[i] = (ha_open[i - 1] + ha_close[i - 1]) / 2
    

    Same here. oncestart is the one in which ha_open should be seeded and not here.

    But the major problem is here:
    @santa3 said in Develop Heikinashi Indicators:

            self.ha_close = (open + high + low + close) / 4
            self.ha_open = (self.ha_open(-1) + self.ha_close(-1)) / 2
    

    Because the calculations are not being assigned to the lines but simply to an attribute of the class. This should be

    >         self.lines.ha_close = (open + high + low + close) / 4
    >         self.lines.ha_open = (self.lines.ha_open(-1) + self.lines.ha_close(-1)) / 2
    

    Which still doesn't solve the problem of the recursive calculation and the seed. And in this case oncestart or nextstart wouldn't be good because the calculation is over when they are seen and the seed used for the calculation is NaN already. In any case the problem can be solved by seeding during the entire prenext phase.

        def prenext(self):
            self.lines.ha_open[0] = self.data.open[0]
    

    When the indicator moves to next, there will be something at index [-1], because values were recorded in the appropriate line by prenext.


  • administrators

    This indicator is now in the development branch


Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.