Would appreciate some help with Connors RSI
-
Hi,
I'm new to backorder and new to python, so please bare with me.
I'm trying to implement an indicator for the ConnorsRSI. At a certain point in the algorithm I need to take the RSI of a line that I create, and it gives me back nan instead of an rsi value. I have no clue where I go wrong, and hope that somebody can point me in the right direction.
Please feel free to give other hints and tips if I make obvious coding mistakes.
The code for the indicator itself is:class ConnorsRSI(bt.Indicator): lines = ('crsi','rsi','streak','streak_rsi', 'prank') params = ( ('rsi_length', 3), ('streak_length', 2), ('loopback_length', 100), ) plotlines = dict( obv=dict( _name='crsi', color='purple', alpha=0.50 ) ) def updown(self): upday=False downday=False if self.data[0] > self.data[-1]: upday = True else: upday = False if self.data[0] < self.data[-1]: downday = True else: downday = False if upday and self.lines.streak[-1] >= 0: self.lines.streak[0] = self.lines.streak[-1] + 1 elif upday and self.lines.streak[-1] <= 0: self.lines.streak[0] = 1 elif downday and self.lines.streak[-1] <= 0: self.lines.streak[0] = self.lines.streak[-1] - 1 elif downday and self.lines.streak[-1] >= 0: self.lines.streak[0] = -1 elif self.data[0] == self.data[-1]: self.lines.streak[0] = 0 else: self.lines.streak[0] = 0 def __init__(self): # Plot a horizontal Line self.plotinfo.plotyhlines = [0] self.lines.rsi = bt.indicators.RSI(self.data, period=self.params.rsi_length) self.lines.prank = bt.indicators.PercentRank(self.data, period=self.params.loopback_length) def next(self): self.updown() self.lines.streak_rsi = bt.indicators.RSI(self.lines.streak, period=self.params.streak_length) def nextstart(self): self.lines.streak[0] = 0
The issue is in the 'next', where I calculate (or want to calculate) the RSI value over the streaks. The output I get is:
2016-05-25: Prev: 48.76: Close: 49.26, rsi: 79.21353438233095 Streak: 0.0 Streak_rsi: nan PercentRank: 59 2016-05-26: Prev: 49.26: Close: 49.04, rsi: 68.50800494096566 Streak: -1.0 Streak_rsi: nan PercentRank: 56 2016-05-27: Prev: 49.04: Close: 49.45, rsi: 77.14326450516853 Streak: 1.0 Streak_rsi: nan PercentRank: 64 2016-05-31: Prev: 49.45: Close: 50.09, rsi: 86.08028735088246 Streak: 2.0 Streak_rsi: nan PercentRank: 70 2016-06-01: Prev: 50.09: Close: 49.95, rsi: 76.29219423676898 Streak: -1.0 Streak_rsi: nan PercentRank: 69 2016-06-02: Prev: 49.95: Close: 49.6, rsi: 53.48552312948757 Streak: -2.0 Streak_rsi: nan PercentRank: 65 2016-06-03: Prev: 49.6: Close: 48.95, rsi: 29.183093574328538 Streak: -3.0 Streak_rsi: nan PercentRank: 52 2016-06-06: Prev: 48.95: Close: 49.27, rsi: 46.97498518905785 Streak: 1.0 Streak_rsi: nan PercentRank: 57 2016-06-07: Prev: 49.27: Close: 49.24, rsi: 45.37197817316539 Streak: -1.0 Streak_rsi: nan PercentRank: 56 2016-06-08: Prev: 49.24: Close: 49.18, rsi: 41.15842240824419 Streak: -2.0 Streak_rsi: nan PercentRank: 55
Thanks!
-
You can't do this
self.lines.streak_rsi = bt.indicators.RSI(self.lines.streak, period=self.params.streak_length)
in the
next()
, only in__init()__
.As a solution you may want to bring all calculations into the
init()
and usebt
RSI or calculate RSI in thenext()
by yourself based on[x]
notations. Or apply RSI tostreak
in a separate indicator. -
@ab_trader thanks for looking into this. I changed the code as below (calculating the RSI myself in the
init()
, but still getting the rsi over the streak back as anan
. Is this not what you meant?class ConnorsRSI(bt.Indicator): lines = ('crsi','rsi','streak', 'streak_rsi','prank') params = ( ('rsi_length', 3), ('streak_length', 2), ('loopback_length', 100), ) plotlines = dict( obv=dict( _name='crsi', color='purple', alpha=0.50 ) ) def updown(self): upday=False downday=False if self.data[0] > self.data[-1]: upday = True else: upday = False if self.data[0] < self.data[-1]: downday = True else: downday = False if upday and self.lines.streak[-1] >= 0: self.lines.streak[0] = self.lines.streak[-1] + 1 elif upday and self.lines.streak[-1] <= 0: self.lines.streak[0] = 1 elif downday and self.lines.streak[-1] <= 0: self.lines.streak[0] = self.lines.streak[-1] - 1 elif downday and self.lines.streak[-1] >= 0: self.lines.streak[0] = -1 elif self.data[0] == self.data[-1]: self.lines.streak[0] = 0 else: self.lines.streak[0] = 0 def __init__(self): # Plot a horizontal Line self.plotinfo.plotyhlines = [0] self.lines.rsi = bt.indicators.RSI(self.data, period=self.params.rsi_length) self.lines.prank = bt.indicators.PercentRank(self.data, period=self.params.loopback_length) # calculate rsi over streak upday = bt.indicators.UpDay(self.lines.streak, period=self.params.streak_length) downday = bt.indicators.DownDay(self.lines.streak, period=self.params.streak_length) maup = bt.indicators.MovAv.Smoothed(upday, period=self.params.streak_length) madown = bt.indicators.MovAv.Smoothed(downday, period=self.params.streak_length) rs = maup / madown self.lines.streak_rsi = 100.0 - 100.0 / (1.0 + rs) def next(self): self.updown() def nextstart(self): self.lines.streak[0] = 0
Thanks for your support!
-
UpDay
andDownDay
indicators are applied to undefinedself.lines.streak
. I am not surprised that result isnan
.You may want go deeper into code debugging by yourself with the logging of all interim calculations. Your indicator seems recursive, so this blog post might help
-
-
Brilliant @backtrader ! I'll make sure to add indicators once I get the hang of creating them!