RSI Calculation (Daily RSI in Minute Mode) using data.history() - Based on StockCharts.com

Hello All,

I am still pretty new to Quantopian and to coding for trading algorithms, but I have something to offer the community today. I've asked for guidance a few times and have always gotten help and responses. Now, I am happy to share what I've created. I have been looking for a solution to calculate RSI (for the day) in minute mode. Many posts talk about how Talib does not calculate correctly, or has errors, because it has to run in day mode; though data.history() may be set to minute. Another problem I was hoping to avoid was the warm-up period that would keep the RSI function itself useless unless a certain number of days had gone by.

So, I took an example made with Talib.RSI and utilized while: loops to warm up the data in before_trading_start(). You'll have to excuse the crude approach. I am not familiar with advanced programming, so my methods could seem overly simplistic or archaic. Henceforth, my numbers come very close to the values for the time period as viewed on StockCharts.com: Looking at YHOO from 7/25/16 - 8/24/16 on a 3 Day RSI (starting out small; algorithm can easily be adjusted for larger RSI values). StockCharts.com specifically points out that, in order to replicate its values, it uses 250 data points in order to start the RSI calculation.

Therefore, the first average gain and first average loss values are calculated from the differences between the first three periods, each divided by three (this is the first while: loop). The next loop calculates the rest of the warm-up series using Wilder's smoothing equation, where each subsequent calculation equals the previous average gain and/or loss, each multiplied by (length of RSI - 1), then added to the current period's gain and/or loss, and each divided by (length of RSI). This gives the new average gain and loss values.

Under handle_data, the subsequent RSI relationship is continued each time handle_data is called and continues through the end of the backtest. This algorithmic instruction should be feasible in live trading, as well. The following data is from the example the utilized Talib:

2016-07-25 15:59 handle_data:25 INFO 37.3417958932
2016-07-26 15:59 handle_data:25 INFO 54.9210693868
2016-07-27 15:59 handle_data:25 INFO 49.3927903539
2016-07-28 15:59 handle_data:25 INFO 44.3083684581
2016-07-29 15:59 handle_data:25 INFO 27.9526135573
2016-08-01 15:59 handle_data:25 INFO 61.4514650932
2016-08-02 15:59 handle_data:25 INFO 49.5293847827
2016-08-03 15:59 handle_data:25 INFO 38.9958637198
2016-08-04 15:59 handle_data:25 INFO 69.4606992821
2016-08-05 15:59 handle_data:25 INFO 70.0551660101
2016-08-08 15:59 handle_data:25 INFO 78.1400151631
2016-08-09 15:59 handle_data:25 INFO 81.1529654125
2016-08-10 15:59 handle_data:25 INFO 93.4746145855
2016-08-11 15:59 handle_data:25 INFO 97.796455887
2016-08-12 15:59 handle_data:25 INFO 98.9967987925
2016-08-15 15:59 handle_data:25 INFO 88.090889088
2016-08-16 15:59 handle_data:25 INFO 79.665635098
2016-08-17 15:59 handle_data:25 INFO 82.6256008185
2016-08-18 15:59 handle_data:25 INFO 85.6035747889
2016-08-19 15:59 handle_data:25 INFO 87.5583643851
2016-08-22 15:59 handle_data:25 INFO 46.3575580514
2016-08-23 15:59 handle_data:25 INFO 52.0037471206
2016-08-24 15:59 handle_data:25 INFO 20.3210716879

The following is from the log output of my construct:

2016-07-25 16:00 PRINT 37.3417958932
2016-07-26 16:00 PRINT 54.9210693868
2016-07-27 16:00 PRINT 49.3927903539
2016-07-28 16:00 PRINT 44.3083684581
2016-07-29 16:00 PRINT 27.9526135573
2016-08-01 16:00 PRINT 61.4514650932
2016-08-02 16:00 PRINT 49.5293847827
2016-08-03 16:00 PRINT 38.9958637198
2016-08-04 16:00 PRINT 69.4606992821
2016-08-05 16:00 PRINT 70.0551660101
2016-08-08 16:00 PRINT 78.1400151631
2016-08-09 16:00 PRINT 81.1529654125
2016-08-10 16:00 PRINT 93.4746145855
2016-08-11 16:00 PRINT 97.796455887
2016-08-12 16:00 PRINT 98.9967987925
2016-08-15 16:00 PRINT 88.090889088
2016-08-16 16:00 PRINT 79.665635098
2016-08-17 16:00 PRINT 82.6256008185
2016-08-18 16:00 PRINT 85.6035747889
2016-08-19 16:00 PRINT 87.5583643851
2016-08-22 16:00 PRINT 46.3575580514
2016-08-23 16:00 PRINT 52.0037471206
2016-08-24 16:00 PRINT 20.3210716879

Pretty excited that I got exact results. I just wanted to build something that answered the call some in the community have made, have it set to run in minute mode, and to replicate what I've seen on StockCharts.com.

Danny

22
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5887b2aca5dee75e40539fb9
There was a runtime error.
2 responses

Hello all,

Updating my post with a functioning RSI function. You are able to input a price series, name the period frequency, set for previous values, alter the span of the timeframes, and alter the initial calculation window; note default settings.

Enjoy.

###################################################################################

def rsi(prices,period,previous=0,span=390,window=250):
### ### ### SET VALUES FOR CALCULATING RSI # PERIOD ### ### ###
warm_up_period = ((((((window+1)+(period))*span)+2)+(abs(previous)*span))
warm_up_counter = -period
momentary_gain = 0.
momentary_loss = 0.

### ### ### INITIATE FIRST DAY RSI CALCULATION, RAW DAYS - GAIN VS LOSS ### ### ###
while warm_up_counter<0:
warm_up_counter += 1
day_prev = float(prices[-int(warm_up_period):-(int(warm_up_period-1))])
warm_up_period -= span
day_next = float(prices[-int(warm_up_period):-(int(warm_up_period-1))])
if day_next>=day_prev:
momentary_gain += day_next-day_prev
else:
momentary_loss += day_prev-day_next
average_gain = momentary_gain/period
average_loss = momentary_loss/period

### ### ### INITIATE ALL REMAINING 250 SUBSEQUENT RSI CALCULATIONS ### ### ###
while warm_up_counter<=window:
warm_up_counter += 1
day_prev = float(prices[-int(warm_up_period):-(int(warm_up_period-1))])
warm_up_period -= span
day_next = float(prices[-int(warm_up_period):-(int(warm_up_period-1))])
if day_next>=day_prev:
momentary_gain = day_next-day_prev
momentary_loss = 0.
else:
momentary_loss = day_prev-day_next
momentary_gain = 0.
average_gain = ((average_gain*(period-1))+momentary_gain)/period
average_loss = ((average_loss*(period-1))+momentary_loss)/period

### ### ### CALCULATE RSI VALUE ### ### ###
rsi = (100-(100/(1+(average_gain/average_loss))))
return rsi

"""
# HANDLE_DATA CALL EXAMPLE...
cp = data.history(context.equity,'price',120000,'1m')[:-1]

rsi10 = rsi(cp,10,0) # simple 10-day RSI
rsi10p = rsi(cp,10,1) # previous day's 10-day RSI

rsi10_half_days = rsi(cp,10,0,195)
rsi10_third_days  = rsi(cp,10,0,130)
rsi10_five_minutes = rsi(cp,10,0,5)
"""


Hi Daniel, thanks for your post! This is exactly what I'm looking for. I am not very confident in implementing it, though. How would you use this code to calculate a minutely RSI? My goal is to have the data in real time so I can make day trades based on that indicator.