Custom strategy using RSI
Contents
Custom strategy using RSI#
New user? The best way to learn SigTech is to follow the steps in our user guide.
Unrestricted data: This notebook only uses data in our core offer to all users. Go ahead and run it.
Changes will not be saved: Edits made to SigTech’s example notebooks like this will only persist for the duration of your session. When you restart the research environment, this notebook will have been restored to its original state, and any changes you have made will have been lost. To make permanent changes, copy and paste the content to a new notebook in one of your workspaces.
Introduction#
The purpose of this notebook is to show how to create a custom strategy which acts on an RSI indicator.
Environment#
This section will import relevant internal and external libraries, as well as setting up the platform environment.
[ ]:
import sigtech.framework as sig
from sigtech.framework.signal.library.momentum import rsi
import pandas as pd
import datetime as dtm
import seaborn as sns
sns.set(rc={'figure.figsize': (18, 6)})
env = sig.init(env_date=dtm.date(2024, 2, 22))
Universe#
[ ]:
sig_master = env.sig_master()
rdsa = sig_master.filter('RDSA', 'EXCHANGE_TICKER')\
.filter_primary_tradable() \
.filter_operating_mic(operating_mics='XLON')
rdsa = rdsa.to_single_stock()
rdsa_xlon = rdsa[list(rdsa.keys())[0]]
[ ]:
rs = sig.ReinvestmentStrategy(
currency=rdsa_xlon.currency,
start_date=dtm.date(2010, 1, 4),
underlyer=rdsa_xlon.name,
)
Strategy#
[ ]:
class CustomRSIStrategy(sig.DailyStrategy):
asset_ticker: str
def __post_init__(self):
self.asset = sig.obj.get(self.asset_ticker)
self.asset_history = self.asset.history()
super().__post_init__()
def strategy_initialization(self, dt):
""" "Magic" function that is run before the strategy's first trading date. """
# We loop over every day in our history schedule
for d in self.history_schedule().all_data_dates()[1:]:
self.add_method(d, self.rsi_decision) # a processor is just a method
def rsi_decision(self, dt):
""" Takes a trading decision based on RSI level. """
# Calculate the 14-period RSI
h = self.asset_history
d = self.size_date_from_decision_dt(dt)
asset_history = h[:d].iloc[-20:].to_frame() # we cut to the last prices
rsi_series = rsi(14, asset_history).squeeze().dropna()
# Store today's and yesterday's values
rsi_tod = rsi_series.iloc[-1]
rsi_yday = rsi_series.iloc[-2]
# Decide on how to trade
# Exiting out of oversold - we buy
if rsi_tod > 30. and rsi_yday < 30.:
self.add_position_target(dt, self.asset_ticker, 1., unit_type='WEIGHT')
# Crossing 50 from beneath, exiting
elif rsi_tod > 50. and rsi_yday < 50.:
self.add_position_target(dt, self.asset_ticker, 0., unit_type='WEIGHT')
# Exiting out of overbought - we sell
elif rsi_tod < 70. and rsi_yday > 70.:
self.add_position_target(dt, self.asset_ticker, -1., unit_type='WEIGHT')
# Crossing 50 from above, exiting
elif rsi_tod < 50. and rsi_yday > 50.:
self.add_position_target(dt, self.asset_ticker, 0., unit_type='WEIGHT')
[ ]:
rsi_strat = CustomRSIStrategy(
currency=rs.currency,
start_date=dtm.date(2011, 1, 4),
asset_ticker=rs.name,
include_trading_costs=False,
)
Performance Analytics#
[ ]:
strategies = pd.concat({
'RDSA RSI Strategy': rsi_strat.history(),
'RDSA Long-only Strategy': rs.history()
}, axis=1).dropna()
[ ]:
sig.PerformanceReport(strategies).report()