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/

    Develop Heikinashi Indicators

    Indicators/Strategies/Analyzers
    2
    5
    1908
    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.
    • S
      santa3 last edited by

      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()
      
      B 1 Reply Last reply Reply Quote 0
      • S
        santa3 last edited by

        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()
        
        1 Reply Last reply Reply Quote 0
        • S
          santa3 last edited by

          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
          
          1 Reply Last reply Reply Quote 0
          • B
            backtrader administrators @santa3 last edited by

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

            1 Reply Last reply Reply Quote 1
            • B
              backtrader administrators last edited by

              This indicator is now in the development branch

              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(); }); }