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?

2
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(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

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

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

8
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.

Thomas

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

10
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

return Pipeline(
screen = filter,
columns={
'c' : c,
'rsi2' : rsi2,
})

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 !