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/

    Bullish and Bearish Divergence MACD/RSI

    Indicators/Strategies/Analyzers
    8
    17
    4540
    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.
    • C
      CooleRnax last edited by CooleRnax

      Hello,

      I'm trying to figure out how can I access these signals?

      To get it i thought for example to find first low, than the previous low indexes.
      Then get prices compare them. Then get indicator's values and compare them too. I got stuck at getting second low/high. Please help.

      self.high_first = btind.FindFirstIndexHighest(self.data.high, period=self.p.hl_period)
      self.high_second = btind.FindFirstIndexHighest(self.data.high(self.high_first-1), period=self.p.hl_period)
      self.low_first = btind.FindFirstIndexLowest(self.data.low, period=self.p.hl_period)
      self.low_second = btind.FindFirstIndexLowest(self.data.low(self.low_first-1), period=self.p.hl_period)
      B 1 Reply Last reply Reply Quote 0
      • C
        CooleRnax last edited by

        I might don't know something and I'm reinventing the wheel, It would be great if somebody point me the right direction.

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

          @coolernax said in Bullish and Bearish Divergence MACD/RSI:

          self.high_first = btind.FindFirstIndexHighest(self.data.high, period=self.p.hl_period)
          self.high_second = btind.FindFirstIndexHighest(self.data.high(self.high_first-1), period=self.p.hl_period)
          

          The problem is that self.data.high(self.high_first - 1) is not a valid construct. Because self.high_first will be determined at runtime, whereas a delayed line (using parenthesis) needs to know the value from how many periods ago it will returning.

          A potential coding

          class SecondHigh(bt.ind.PeriodN):
              lines = ('first_high', 'second_high',)
          
              def __init__(self):
                  self.hf = self.lines.first_high  = bt.ind.FindFirstIndexHighest(self.data.high, period=self.p.period)
          
              def next(self):
                  # 0 is valid return value for now, make sure to get at least 1 item
                  iterable = self.data.get(size=self.hf[0] + 1)
                  m = max(iterable)
                  self.lines.second_high[0] = next(i for i, v in enumerate(reversed(iterable)) if v == m)
          

          Finding the index of the maximum is not made with the better iterable.index(max(iterable)) to comply with the idea in backtrader that the current index is 0.

          The FindFirstXXX family of functions return the indices in absolute value and this is also done here .

          Note: this is a handcrafted snippet which may have typos and not work at all.

          1 Reply Last reply Reply Quote 0
          • C
            CooleRnax last edited by

            @backtrader said in Bullish and Bearish Divergence MACD/RSI:

            @coolernax said in Bullish and Bearish Divergence MACD/RSI:

            self.high_first = btind.FindFirstIndexHighest(self.data.high, period=self.p.hl_period)
            self.high_second = btind.FindFirstIndexHighest(self.data.high(self.high_first-1), period=self.p.hl_period)
            

            The problem is that self.data.high(self.high_first - 1) is not a valid construct. Because self.high_first will be determined at runtime, whereas a delayed line (using parenthesis) needs to know the value from how many periods ago it will returning.

            A potential coding

            class SecondHigh(bt.ind.PeriodN):
                lines = ('first_high', 'second_high',)
            
                def __init__(self):
                    self.hf = self.lines.first_high  = bt.ind.FindFirstIndexHighest(self.data.high, period=self.p.period)
            
                def next(self):
                    # 0 is valid return value for now, make sure to get at least 1 item
                    iterable = self.data.get(size=self.hf[0] + 1)
                    m = max(iterable)
                    self.lines.second_high[0] = next(i for i, v in enumerate(reversed(iterable)) if v == m)
            

            Finding the index of the maximum is not made with the better iterable.index(max(iterable)) to comply with the idea in backtrader that the current index is 0.

            The FindFirstXXX family of functions return the indices in absolute value and this is also done here .

            Note: this is a handcrafted snippet which may have typos and not work at all.

            Thanks I will try your example

            1 Reply Last reply Reply Quote 0
            • C
              CooleRnax last edited by CooleRnax

              @backtrader I created an indicator that works, but sometimes I face error like this:
              ValueError: max() arg is an empty sequence

              Please take a look
              Here is the code:

              class RSIDivergence(bt.ind.PeriodN):
                  lines = ('signal',)
                  params = dict(
                      rsi_period=14,
                      hl_period=100,
                      hl_min=20
                  )
              
                  # plotinfo = dict(
                  #     subplot=True,
                  #     plotlinelabels=True, plotlinevalues=True, plotvaluetags=True,
                  # )
              
                  # plotlines = dict(
                  #     high_first_price=dict(_name='high_first_price', color='red', ls='-'),
                  #     high_second_price=dict(_name='high_second_price', color='blue', ls='-'),
                  #     low_first_price=dict(_name='low_first_price', color='red', ls='-'),
                  #     low_second_price=dict(_name='low_second_price', color='blue', ls='-'),
                  # )
              
                  def __init__(self):
                      self.hfi = bt.ind.FindFirstIndexHighest(self.data.high, period=self.p.hl_period)
                      self.lfi = bt.ind.FindFirstIndexLowest(self.data.low, period=self.p.hl_period)
                      self.rsi = bt.ind.RSI_Safe(period=self.p.rsi_period)
              
                  def signal_get(self):
                      signal = 0
                      if self.hfp >= self.hsp:
                          if self.rsi[-int(self.hfi[0])] < self.rsi[-int(self.hsi)]:
                              print('bearish', self.rsi[-int(self.hfi[0])], self.rsi[-int(self.hsi)])
                              signal -= 1
              
                      if self.lfp <= self.lsp:
                          if self.rsi[-int(self.lfi[0])] > self.rsi[-int(self.lsi)]:
                              print('bullish', self.rsi[-int(self.hfi[0])], self.rsi[-int(self.hsi)])
                              signal += 1
              
                      return signal
              
                  def next(self):
                      iterable = self.data.high.get(size=int(self.hfi[0]) + self.p.hl_min)
                      m = max(iterable)
                      self.hsi = next(i for i, v in enumerate(reversed(iterable)) if v == m) + self.p.hl_min
              
                      iterable = self.data.low.get(size=int(self.lfi[0]) + self.p.hl_min)
                      m = min(iterable)
                      self.lsi = next(i for i, v in enumerate(reversed(iterable)) if v == m) + self.p.hl_min
              
                      self.hfp = self.data.high[-int(self.hfi[0])]
                      self.hsp = self.data.high[-int(self.hsi)]
                      self.lfp = self.data.low[-int(self.lfi[0])]
                      self.lsp = self.data.low[-int(self.lsi)]
              
                      # self.lines.high_first_price[0] = self.hfp
                      # self.lines.high_second_price[0] = self.hsp
                      # self.lines.low_first_price[0] = self.lfp
                      # self.lines.low_second_price[0] = self.lsp
                      self.lines.signal[0] = self.signal_get()
              1 Reply Last reply Reply Quote 0
              • C
                CooleRnax last edited by CooleRnax

                @coolernax said in Bullish and Bearish Divergence MACD/RSI:

                iterable

                I have created the fix, hope you can include similar indicator for RSI/MACD in the main branch:

                class RSIDivergence(bt.ind.PeriodN):
                    lines = ('signal',)
                    params = dict(
                        rsi_period=30,
                        hl_period=100,
                        hl_min=25
                    )
                
                    def __init__(self):
                        self.hfi = bt.ind.FindFirstIndexHighest(self.data.high, period=self.p.hl_period)
                        self.lfi = bt.ind.FindFirstIndexLowest(self.data.low, period=self.p.hl_period)
                        self.rsi = bt.ind.RSI_Safe(period=self.p.rsi_period)
                
                    def signal_get(self):
                        signal = 0
                        if self.hfp >= self.hsp:
                            if self.rsi[-int(self.hfi[0])] < self.rsi[-int(self.hsi)]:
                                signal -= 1
                
                        if self.lfp <= self.lsp:
                            if self.rsi[-int(self.lfi[0])] > self.rsi[-int(self.lsi)]:
                                signal += 1
                
                        return signal
                
                    def next(self):
                        h_iterable = self.data.get(size=self.p.hl_period, ago=-int(self.hfi[0]) - self.p.hl_min)
                        l_iterable = self.data.get(size=self.p.hl_period, ago=-int(self.lfi[0]) - self.p.hl_min)
                
                        if len(h_iterable) > 0 and len(l_iterable) > 0:
                            m = max(h_iterable)
                            self.hsi = next(i for i, v in enumerate(reversed(h_iterable)) if v == m) + int(self.hfi[0]) + self.p.hl_min
                
                            m = min(l_iterable)
                            self.lsi = next(i for i, v in enumerate(reversed(l_iterable)) if v == m) + int(self.lfi[0]) + self.p.hl_min
                
                            self.hfp = self.data.high[-int(self.hfi[0])]
                            self.hsp = self.data.high[-int(self.hsi)]
                            self.lfp = self.data.low[-int(self.lfi[0])]
                            self.lsp = self.data.low[-int(self.lsi)]
                
                            self.lines.signal[0] = self.signal_get()
                        else:
                            self.lines.signal[0] = 0
                1 Reply Last reply Reply Quote 0
                • mrahmadt
                  mrahmadt last edited by mrahmadt

                  Thank you.

                  mamos 1 Reply Last reply Reply Quote 0
                  • mamos
                    mamos @mrahmadt last edited by

                    Hello,

                    I'm trying use your custom indicator RSIDivergence but I don't understand how I can use it?
                    Do you have a simple example ?
                    I am sorry for my english and I am not good developper

                    1 Reply Last reply Reply Quote 1
                    • mamos
                      mamos last edited by

                      I don't understand why nobody answer me ?

                      Please help me

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

                        @coolernax said in Bullish and Bearish Divergence MACD/RSI:

                        class RSIDivergence(bt.ind.PeriodN):
                        lines = ('signal',)

                        I am not the author but looking at these excerpts from the code

                        @coolernax said in Bullish and Bearish Divergence MACD/RSI:

                        class RSIDivergence(bt.ind.PeriodN):
                            lines = ('signal',)
                            ...
                            ...
                            def signal_get(self):
                                signal = 0
                                if self.hfp >= self.hsp:
                                    if self.rsi[-int(self.hfi[0])] < self.rsi[-int(self.hsi)]:
                                        signal -= 1
                        
                                if self.lfp <= self.lsp:
                                    if self.rsi[-int(self.lfi[0])] > self.rsi[-int(self.lsi)]:
                                        signal += 1
                        
                                return signal
                        
                            def next(self):
                            ...
                            ...
                        
                                    self.lines.signal[0] = self.signal_get()
                                else:
                                    self.lines.signal[0] = 0
                        

                        The indicator has:

                        • A line named signal which is the output indicating the divergence
                        • It can have the values -1, 0 or 1 which should be self-explanatory
                        Vasu Dev 1 Reply Last reply Reply Quote 0
                        • mamos
                          mamos last edited by

                          @backtrader thanks you very much . I'm happy now ! I will test soon :D

                          1 Reply Last reply Reply Quote 0
                          • Vasu Dev
                            Vasu Dev @backtrader last edited by

                            @backtrader
                            -1 for Bearish Divergence
                            1 for Bullish Divergence ????

                            mamos 1 Reply Last reply Reply Quote 0
                            • mamos
                              mamos @Vasu Dev last edited by

                              @vasu-dev
                              yes I think:
                              -1 for Bearish Divergence
                              1 for Bullish Divergence
                              but I have result not good... and you?

                              Someone have an example working good ?

                              1 Reply Last reply Reply Quote 0
                              • pepelepew25
                                pepelepew25 last edited by pepelepew25

                                After testing the code above and plotting the divergences that it found, I think that the issue is with this line:

                                self.hfi = bt.ind.FindFirstIndexHighest(self.data.high, period=self.p.hl_period)
                                

                                It looks for the highest point (same for the lowest) within the hl_period (100 bars)

                                Then in the following line it looks again backwards from that point to find the second high

                                h_iterable = self.data.get(size=self.p.hl_period, ago=-int(self.hfi[0]) - self.p.hl_min)
                                

                                So basically the code returns signals for very old divergences. If you are on daily chart, you will try to trade on a divergence that is 100 days old.

                                So the first day after the high point it signals a sell, then for the next 100 days it still signals a sell !

                                I have amended the first line to look for a high/low point for the last day only.
                                In this way if the divergence is growing then it's fine you still get a sell signal, but if the divergence is gone then you don't try to keep selling for 100 days.

                                D 1 Reply Last reply Reply Quote 0
                                • D
                                  dowdtw @pepelepew25 last edited by

                                  @pepelepew25 hey how did you go about plotting this please? I'm plotting adding plotinfo, plotlines but getting nothing!

                                  D 1 Reply Last reply Reply Quote 0
                                  • D
                                    dowdtw @dowdtw last edited by

                                    @dowdtw I figured it out. No Dramas.:)

                                    P Jr G 1 Reply Last reply Reply Quote 1
                                    • P Jr G
                                      P Jr G @dowdtw last edited by

                                      @dowdtw Would be great if you could share your solution...

                                      1 Reply Last reply Reply Quote 1
                                      • 1 / 1
                                      • First post
                                        Last post
                                      Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                                      $(document).ready(function () { app.coldLoad(); }); }