Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Coding a custom indicator (RSI-EMA)

Hi,

Can someone please help me code the RSI-EMA on the minute interval? It's just simply applying an EMA onto the RSI to smooth it out.

Here's how I coded mine with Pine Script in TradingView:
https://www.tradingview.com/script/NJae8zzE-RSI-EMA-Indicator/

Thanks!

16 responses

Bump.

Hello Kory,

I successfully coded RSI(14) that way by importing talib.

import talib

    # Load historical data for the stocks  
    closes_prices = history(31, '1d', 'close_price')  
    rsi = closes_prices.apply(talib.RSI, timeperiod=14).iloc[-1]  

Afterwards I tried to talib.EMA this, but didn't work so far.

PS: I'm a total beginner. But I think the solution is close.

Hi Matt,

Thank you for your help. Aaron Olson and I met up after QuantCon and we have successfully coded the RSI-SMA (smoothing the RSI with an SMA instead of an EMA). We are still working on the RSI-EMA. Below is a 20-day RSI smoothed with a 50-day SMA.

Sorry to hijack the post but could someone explain me how to apply RSI(14) on a 1 dimension list like [1, 2 ... 19, 20] ? I'm banging my head on a wall :)

I think panda doesn't handle formula calculation directly to a list, so I think i need to convert it to a dataframe, but then again it doesnt work

    span = [1, 2 ... 19, 20]  
    serie = pd.Series(span)  
    df = pd.DataFrame(serie)  
    log.info(df) # <--- blank  
    rsi = df.apply(talib.RSI, timeperiod=14).iloc[-1]

Is it something i've missed?

I have attempted the same thing quite some time ago. Maybe it helps :)

https://github.com/BraunPhilipp/quant-trading/blob/master/indic.py

Hello, wondering if somebody knows how to calculate historical (like 1 day ago, 2 days ago) RSI for pipeline?

Here's a custom factor for RSI which can be used to get RSI N days ago. Simply change the window_length to get different N day lookbacks.

class Prev_N_RSI(CustomFactor):  
    """  
    Remember to set the window length to N + what the window really is  
    If the desired lookback N is 2 days and the RSI window is 14 days,  
    Then set the window_length to 2+14=16  
    """  
    inputs = [USEquityPricing.close]  
    # Default window length RSI window = 14  and N = 0  
    # Override this when instantiating the factor  
    window_length = 14

    def compute(self, today, assets, out, closes):  
         # Below is just for readibility RSI length assumed to be 14 days  
        rsi_window_length = 14  


        diffs = np.diff(closes[0:rsi_window_length], axis=0)  
        ups = np.nanmean(np.clip(diffs, 0, np.inf), axis=0)  
        downs = abs(np.nanmean(np.clip(diffs, -np.inf, 0), axis=0))  


        out[:] = 100 - (100 / (1 + (ups / downs)))  


See the attached workbook for how to implement as well as a quick check against values returned by the built in RSI factor.

Thank you, Dan! I am tried to apply to pipeline excluding masking security, like below, and it showed me NaN for historical RSI (rsi_1,2,3_day_ago) and actual value for yesterday's RSI. Would you know the reason?

rsi_window_length = 14  
#rsi = RSI(window_length=rsi_window_length)  #, mask = securities)  
#rsi_1_day_ago = Prev_N_RSI(window_length = rsi_window_length + 1)  #, mask = securities)  
#rsi_2_day_ago = Prev_N_RSI(window_length = rsi_window_length + 2)  #, mask = securities)  
rsi_3_day_ago = Prev_N_RSI(window_length = rsi_window_length + 3)  #, mask = securities)

It worked now, but It requires some masking, i guess otherwise the call will be too long, but I do not know for sure.
Currently here where i stuck again, in a case anybody can explore -
In short , I am getting RSI which is not correct for the set of filtered stocks, see below. RSI 3 days long showed 73.622047 across all pre-selected stocks. I think I am missing smth.

# Make our factors  
# Using a mask limits the computation to only the specified asset.  
close_1_day_ago = PreviousClose(window_length = 1) #, mask = my_filter)  
close_2_day_ago = PreviousClose(window_length = 2) #, mask = my_filter)  
close_3_day_ago = PreviousClose(window_length = 3) #, mask = my_filter)  
close_4_day_ago = PreviousClose(window_length = 4) #, mask = my_filter)  
close_5_day_ago = PreviousClose(window_length = 5) #, mask = my_filter) 

#securities = StaticAssets(symbols(['AAPL']))  
condition1 =  close_3_day_ago < close_2_day_ago  
condition2 =  close_2_day_ago < close_1_day_ago  
condition3 =  close_3_day_ago < close_4_day_ago  
condition4 =  close_4_day_ago < close_5_day_ago

all_conditions = condition1 & condition2 & condition3 & condition4  
base_universe = Q500US()

my_filter = base_universe & all_conditions

rsi_window_length = 14  
#rsi = RSI(window_length=rsi_window_length) #, mask = securities)  
#rsi_1_day_ago = Prev_N_RSI(window_length = rsi_window_length + 1) #, mask = securities)  
#rsi_2_day_ago = Prev_N_RSI(window_length = rsi_window_length + 2, mask = my_filter)  
rsi_3_day_ago = Prev_N_RSI(window_length = rsi_window_length + 3, mask = my_filter)

# Now create our pipeline object which does the heavy lifting to get the data we specify  
# Add a screen to just return specific assets. Otherwise all assets in the Q database are returned  
# Defining the pipeline is really just defining the columns we want in the returned dataframe and  
# limiting the rows (if desired) to a particular subset of assets.  
my_pipe = Pipeline(  
        screen = my_filter, #securities  
        columns = {  
            'close_1_day_ago': close_1_day_ago,  
            'close_2_day_ago': close_2_day_ago,  
            'close_3_day_ago': close_3_day_ago,  
            'close_4_day_ago': close_4_day_ago,  
            'close_5_day_ago': close_5_day_ago,  
            #'rsi' : rsi,  
            #'rsi_1_day_ago' : rsi_1_day_ago,  
            #'rsi_2_day_ago' : rsi_2_day_ago,  
            'rsi_3_day_ago' : rsi_2_day_ago,  
        }  
    )



Could you attach a notebook (rather than pasting code) which shows the issues you are experiencing. It may be easier to troubleshoot.

Oops. My mistake. A little problem with slicing in the custom factor. Should be:


class Prev_N_RSI(CustomFactor):  
    """  
    Remember to set the window length to N + what the window really is  
    If the desired lookback N is 2 days and the RSI window is 14 days,  
    Then set the window_length to 2+14=16  
    """  
    inputs = [USEquityPricing.close]  
    # Default window length RSI window = 14 / N = 0  
    # Override this when instantiating the factor  
    window_length = 14  


    def compute(self, today, assets, out, closes):  
        # Below is just for readibility RSI length assumed to be 14 days  
        rsi_window_length = 14  
        diffs = np.diff(closes[0:rsi_window_length], axis=0)

        ups = np.nanmean(np.clip(diffs, 0, np.inf), axis=0)  
        downs = abs(np.nanmean(np.clip(diffs, -np.inf, 0), axis=0))  
        out[:] = 100 - (100 / (1 + (ups / downs)))  

Check and see if the attached notebook is more what you expected...

Thank you, Dan.

I just compared the prices across the stock pull I got with Yahoo Finance and Google Fiance, these are not matching. RSI is wrong accordingly. Something is off in this function. Do you mind to tale a look?

The close prices look OK to me. Attached is your notebook with the pipeline run on a single day (12-12-2017).

Spot checking the first 4 "close_1_day_ago" prices here is what the pipeline returned.

Equity(216 [HES]) 45.7700  
Equity(357 [TWX]) 90.820  
Equity(368 [AMGN]) 176.8000  
Equity(734 [BAX]) 64.1400  

Since the pipe was run on 12-12-2017 the "close_price_1_day_ago" would therefore be the close on the previous trading day which was 12-11-2017. Here's what I get on Yahoo for the close prices for those securities on 12-11-2017.

HES 45.76  
TWX 90.82  
AMGN 176.83  
BAX 64.14  

TWX and BAX are identical. The others are off .01 and .03. Note the close prices on Q may not match exactly with the close prices from other sources. See this post https://www.quantopian.com/posts/discrepancies-in-prices-from-yahoo-finances-and-price-from-q.

You are right, I have been using different start and end date, therefore was getting differences. Not clear how these differences were calculated, selecting start and end data as the same I am getting correct results. Thank you so much for your help and explanations!

Glad to help. Good luck!

Hello Dan,
Thank you very much for the past RSI function !

But I have a problem. I compared these function outputs for actual rsi to rsi 5 days ago with RSI 14 in ProRealTime (PRT) software for Apple and the results are differents, very differents from 4 days ago.
Between 3 and 4 days ago the RSI decreases by 9 and between 4 and 5 by 11. In the software the RSI 5 days ago was between 63 and 68 (depending on what the RSI formula is applied : close, open, high, low, typical, weighted, median or total) but the function returns 54...
It seems the more you go backward in time the greater the error. For actual RSI there is no really difference with PRT but for RSI 1 day ago the difference with PRT is at least 2.2.

Is there an error in my code ?
See the attached notebook to see the ouputs.

RSI 0 day ago was just to compare with the built-in RSI function and we can see the results are equals...

Also I wonder which RSI formula does the function uses ? Refering to the code I would say to closes.

Thank you very much again !

Edit : I just saw that if I run the pipeline with past dates the (built-in) RSI is the same as the Prev_N_RSI so I would say the error comes from the pipeline itself, not from the Prev_N_RSI function...