Backtest Period
1995-2018
Markets Traded
Equities
Maximum Drawdown
Period of Rebalancing
Daily
Return (Annual)
2.5%
Sharpe Ratio
Standard Deviation (Annual)
Original paper
SSRN-id3412429.pdf2157.2KB
Trading rules
- Investment universe: S&P 500 stocks
- N = 25 days
- Use 14-day RSI to identify bull range: RSI between 40 and 100 over 25 days
- Momentum signal: highest high value of 14-day RSI must be greater than 70 over 25 days
- Equally weighted stocks in portfolio
- Daily portfolio rebalancing
Python code
Backtrader
import backtrader as bt
class RSI_Momentum_Strategy(bt.Strategy):
params = (
('rsi_period', 14),
('n_days', 25),
('rsi_low', 40),
('rsi_high', 100),
('momentum_threshold', 70),
)
def __init__(self):
self.rsi = {data: bt.indicators.RSI(data, period=self.params.rsi_period) for data in self.datas}
self.highest_rsi = {data: bt.indicators.Highest(self.rsi[data], period=self.params.n_days) for data in self.datas}
def next(self):
selected_stocks = []
for data in self.datas:
rsi = self.rsi[data]
highest_rsi = self.highest_rsi[data]
if self.params.rsi_low <= rsi <= self.params.rsi_high and highest_rsi > self.params.momentum_threshold:
selected_stocks.append(data)
if not selected_stocks:
for data in self.datas:
self.order_target_percent(data, target=0)
return
target_weight = 1 / len(selected_stocks)
for data in self.datas:
if data in selected_stocks:
self.order_target_percent(data, target=target_weight)
else:
self.order_target_percent(data, target=0)
The above code defines a Backtrader strategy that implements the given trading rules. The code calculates the RSI for each stock in the S&P 500, checks if the RSI is in the bull range, and selects stocks with the highest high value of 14-day RSI greater than 70 over 25 days. The portfolio is then equally weighted and rebalanced daily.