Backtest Period
1988-2005
Markets Traded
Equities
Maximum Drawdown
Period of Rebalancing
Monthly
Return (Annual)
26.8%
Sharpe Ratio
Standard Deviation (Annual)
Original paper
SSRN-id1405511.pdf315.0KB
Trading rules
- Include stocks from NYSE, AMEX, and NASDAQ
- Utilize short-interest ratio as predictor
- Sort stocks by short interest ratio
- Select top 1% of sorted stocks
- Apply equal weight to portfolio holdings
- Rebalance portfolio monthly
Python code
Backtrader
import backtrader as bt
class ShortInterestEffect(bt.Strategy):
def __init__(self):
self.sir = dict()
def prenext(self):
self.next()
def next(self):
if self.datetime.date().day != 1:
return
short_interest_ratios = list()
for data in self.datas:
if data._name in self.sir:
short_interest_ratios.append((data, self.sir[data._name]))
short_interest_ratios.sort(key=lambda x: x[1])
top_percentile = int(len(short_interest_ratios) * 0.01)
selected_stocks = short_interest_ratios[:top_percentile]
target_weight = 1.0 / len(selected_stocks)
for data, _ in selected_stocks:
self.order_target_percent(data, target_weight)
for data in self.datas:
if data not in [stock for stock, _ in selected_stocks]:
self.order_target_percent(data, 0.0)
def notify_data(self, data, status, *args, **kwargs):
if status == data.LIVE:
self.sir[data._name] = data.sir[0]
def run_backtest(feed_list, start_cash, fromdate, todate):
cerebro = bt.Cerebro()
cerebro.broker.set_cash(start_cash)
for feed in feed_list:
data = bt.feeds.PandasData(dataname=feed['data'], short_interest_ratio=feed['short_interest_ratio'])
cerebro.adddata(data, name=feed['symbol'])
cerebro.addstrategy(ShortInterestEffect)
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='drawdown')
cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='annual_return')
cerebro.run(stdstats=False, fromdate=fromdate, todate=todate)
return cerebro
This code assumes that you have your stock data and short-interest ratios prepared in the feed_list
parameter, with each element having the following structure:
{ 'symbol': 'ticker', 'data': pandas_dataframe, 'short_interest_ratio': 'column_name'}
Also, fromdate
and todate
are datetime.datetime
objects specifying the start and end dates for the backtest.