Backtest Period
1993-2006
Markets Traded
Equities
Maximum Drawdown
Period of Rebalancing
Intraday
Return (Annual)
14%
Sharpe Ratio
Standard Deviation (Annual)
Original paper
SSRN-id1625495.pdf307.3KB
Trading rules
- Buy SPY ETF at daily closing price
- Sell SPY ETF at daily opening price
- Consider slippage costs and fees
- Combine with a more sophisticated strategy
- Use as a trade execution strategy for entry/exit improvements
Python code
Backtrader
import backtrader as bt
class OvernightAnomaly(bt.Strategy):
params = (
('slippage', 0.001),
('commission', 0.001),
)
def __init__(self):
self.spy = self.datas[0]
self.order = None
self.buy_price = None
self.sell_price = None
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
return
if order.status in [order.Completed]:
if order.isbuy():
self.buy_price = order.executed.price * (1 + self.params.slippage)
self.buy_comm = order.executed.comm
else:
self.sell_price = order.executed.price * (1 - self.params.slippage)
self.sell_comm = order.executed.comm
self.order = None
def next(self):
if self.position:
self.sell(data=self.spy, exectype=bt.Order.Market, size=self.position.size)
else:
self.buy(data=self.spy, exectype=bt.Order.Close)
def stop(self):
pnl = self.broker.getvalue() - self.broker.startingcash
print('PnL: %.2f' % pnl)
if __name__ == '__main__':
cerebro = bt.Cerebro()
data = bt.feeds.YahooFinanceData(dataname='SPY', fromdate='2000-01-01', todate='2021-12-31', adjclose=True)
cerebro.adddata(data)
cerebro.addstrategy(OvernightAnomaly)
cerebro.broker.setcash(100000.0)
cerebro.broker.setcommission(commission=0.001)
cerebro.run()
Please note that this code snippet demonstrates a simple implementation of the Overnight Anomaly strategy using Backtrader. It does not include the combination with a more sophisticated strategy or using it as a trade execution strategy for entry/exit improvements. These features would require additional customization and are beyond the scope of a single code snippet.