Back to Community
Calculating RSI2 for present date & day before

Hey guys,

Currently I'm trying to use the RSI function that can be imported from quantopian.pipeline.factors. My question is, when I call RSI(window_length=2), how does it know what stock to calculate the RSI for? The universe I'm currently using in my pipeline is Q500US.

Also, what I'm trying to do with my algorithim is calculate the RSI2 of the present date (not the actual present date, but the date the algorithim is currently on when it's backtesting) and compare it with the RSI2 of the day before the present date. How can I accomplish something like this?

Thanks for the help,
Thomas

5 responses

I've also tried to get the RSI2 of the present date and previous date using ta-lib like so here. However, the logs seem to show that the RSI2 of yesterday is different than what my output is displaying it actually was yesterday. After further investigation, the stock prices for the previous day seems to very slightly off from what it actually was the previous day (As small as -0.04 off on some days). Any ideas why?

Clone Algorithm
2
Loading...
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
"""
This is a template algorithm on Quantopian for you to adapt and fill in.
"""
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume
from quantopian.pipeline.filters.morningstar import Q500US
from datetime import timedelta  
from sqlalchemy import or_
import talib

def initialize(context):
    """
    Called once at the start of the algorithm.
    """  
    
    schedule_function(setAlerts, date_rules.every_day(), time_rules.market_close())
    schedule_function(my_rebalance, date_rules.every_day(), time_rules.market_open())
    # Record tracking variables at the end of each day.
    schedule_function(my_record_vars, date_rules.every_day(), time_rules.market_close())
         
    # Create our dynamic stock selector.
    attach_pipeline(make_pipeline(), 'my_pipeline')
    
    context.stock = symbol('SPY') #Equity asset
    context.rsi_period = 2
    context.OB = 70 #Overbought threshold
    context.OS = 30 #Oversold threshold
    
def setAlerts(context, data):         
    stock_prices = data.history(context.stock, 'price', 4, '1d')
    stock_prices_for_rsi_yesterday = stock_prices[0:3]    
    stock_prices_for_rsi_today = stock_prices[1:]

    rsi_yesterday = talib.RSI(stock_prices_for_rsi_yesterday, context.rsi_period)
    rsi_today = talib.RSI(stock_prices_for_rsi_today, context.rsi_period)
    
    print("-------------")
    print("RSI Yesterday")
    print(rsi_yesterday)
    print("RSI Today")
    print(rsi_today)

def make_pipeline():
    """
    A function to create our dynamic stock selector (pipeline). Documentation on
    pipeline can be found here: https://www.quantopian.com/help#pipeline-title
    """
    
    # Base universe set to the Q500US
    base_universe = Q500US()

    # Factor of yesterday's close price.
    yesterday_close = USEquityPricing.close.latest
     
    pipe = Pipeline(
        screen = base_universe,
        columns = {
            'close': yesterday_close,
        }
    )
    
    return pipe
 
def before_trading_start(context, data):    
    """
    Called every day before market open.
    """
    context.output = pipeline_output('my_pipeline')
  
    # These are the securities that we are interested in trading each day.
    context.security_list = context.output.index
     
def my_assign_weights(context, data):
    """
    Assign weights to securities that we want to order.
    """
    pass
 
def my_rebalance(context,data):
    """
    Execute orders according to our schedule_function() timing. 
    """
    pass
 
def my_record_vars(context, data):
    """
    Plot variables at the end of each day.
    """
    pass
 
def handle_data(context,data):
    """
    Called every minute.
    """
    pass
There was a runtime error.

Thomas,

RSI calculation just needs more data than rsi_period.
Try this:

import talib

def initialize(context):  
    schedule_function(record_rsi, date_rules.every_day(), time_rules.market_close())

def record_rsi(context, data):  
    stock = symbol('SPY')  
    rsi_period = 2  
    offset = 1  
    bars =  rsi_period + offset + 2

    prices = data.history(stock,'price', bars,'1d')  
    rsi_today = talib.RSI(prices[-4:-1], rsi_period)[-1]  
    rsi_yesterday = talib.RSI(prices[-5:-2], rsi_period)[-1]  

    print("-------------")  
    print("RSI Yesterday")  
    print(rsi_yesterday)  
    print("RSI Today")  
    print(rsi_today)

    record( rsi_today =  rsi_today,  rsi_yesterday = rsi_yesterday)  
Clone Algorithm
8
Loading...
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
# RSI_2 test

import talib

def initialize(context):    
    schedule_function(record_rsi, date_rules.every_day(), time_rules.market_close())
    
def record_rsi(context, data): 
    
    stock = symbol('SPY') 
    rsi_period = 2
    offset = 1
    bars =  rsi_period + offset + 2
    
    prices = data.history(stock,'price', bars,'1d')
    rsi_today = talib.RSI(prices[-4:-1], rsi_period)[-1]
    
    rsi_yesterday = talib.RSI(prices[-5:-2], rsi_period)[-1]    
    
    print("-------------")
    print("RSI Yesterday")
    print(rsi_yesterday)
    print("RSI Today")
    print(rsi_today)

    record( rsi_today =  rsi_today,  rsi_yesterday = rsi_yesterday)
There was a runtime error.

Vladmir, thank you so much!!

Thomas

Here is an implementation of Wilder's RSI(n) as a pipeline factor.

Clone Algorithm
10
Loading...
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
"""
WRSI factor test
"""
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import CustomFactor
from quantopian.pipeline.filters import CustomFilter
import numpy as np
import talib


class WRSI(CustomFactor):
    # Relative Strength Index using Wilder's smoothing
    # (default RSI factor is Cutler's RSI which uses SMA smoothing)
    inputs = (USEquityPricing.close,)
    params = {'rsi_len' : 14,}
    window_length = 60 # allow at least 4 times RSI len for proper smoothing
    def compute(self, today, assets, out, close, rsi_len):
        diffs = np.diff(close, axis=0)
        count = len(diffs)
        decay_rate = (1.0 - (1.0 / rsi_len)) # Wilder's smoothing (different from standard EWMA)
        weights = np.full(count, decay_rate, float) ** np.arange(count + 1, 1, -1)
        ups = np.average(np.clip(diffs, 0, np.inf), axis=0, weights=weights)
        downs = abs(np.average(np.clip(diffs, -np.inf, 0), axis=0, weights=weights))
        out[:] = [100 - (100 / (1 + (up / down))) for up, down in zip(ups, downs)]

def initialize(context):
    attach_pipeline(make_pipeline(), 'my_pipeline')

def specific_assets_filter(assets):
    sids = set(map(int, assets))  
    is_my_sid = np.vectorize(lambda sid: sid in sids)
    class SpecificAssets(CustomFilter):  
        inputs = ()  
        window_length = 1  
        def compute(self, today, assets, out):  
            out[:] = is_my_sid(assets)
    return SpecificAssets()

def my_universe():
    return (specific_assets_filter(symbols('AAPL')))

def make_pipeline():
    filter = my_universe()
    c = USEquityPricing.close.latest
    rsi2 = WRSI(rsi_len=2, window_length=20, mask=filter)
  
    return Pipeline(
            screen = filter,
            columns={
                'c' : c,
                'rsi2' : rsi2,
            })

def before_trading_start(context, data):
    context.output = pipeline_output('my_pipeline')
    for stock in context.output.index:
        log.info("stock={}, rsi2={}".format(str(stock.symbol), context.output.rsi2[stock]))           

There was a runtime error.

Hello,

Is there a way to calculate WRSI n-days ago ?

I found this function

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)))  

But it does not calculate well the past RSI (n-days ago). The actual RSI is pretty close from RSI we can find on Finviz or softwares but the RSI 4 days ago for example is very different. See my post (last one) here for more details : https://www.quantopian.com/posts/coding-a-custom-indicator-rsi-ema

I believe it is because it is not Wilder's RSI but then how can we calculate a RSI n-days ago which is equivalent to "popular" (Finviz, Investing, softwares etc) RSI ?

I want to return stocks of which RSI 5 days ago (e.g.) was higher than actual RSI, which is around 50.
I am not looking to backtest for the moment, just to build a screener. Is it possible to do this in a notebook, just with a pipeline ? Using USEquityPricing.

Do you have any idea how can I do that ?

*Edit : I tried to do like in Prev_N_RSI function, that is putting 16 (14+2) for rsi_len for RSI 2 days ago, but it does not work very well.

I noticed RSI does not vary anymore from window_length=75-80.

But I'm glad the actual RSI is far better calculated than with the built-in function !