Next we'll use Moonshot to backtest the momentum factor we explored in the previous notebook.
Moonshot is an open-source, vectorized backtester created by QuantRocket. A vectorized backtester is one which uses vectorized operations to backtest an entire date range at once, in contrast to event-driven backtesters like Zipline which process one event at a time. Moonshot uses pandas to perform vectorized operations. You can learn more about Moonshot in the usage guide.
Cross-sectional momentum strategies which buy recent winners and sell recent losers commonly go by the name of UMD, or "Up Minus Down." An implementation of UMD for Moonshot is available in umd.py.
To "install" the strategy, execute the following cell to move the strategy file to the /codeload/moonshot
directory, where Moonshot looks:
The ! sytax below lets us execute terminal commands from inside the notebook.
# make directory if doesn't exist
!mkdir -p /codeload/moonshot
!mv umd.py /codeload/moonshot/
The usage guide describes in detail how a Moonshot backtest works, but here we'll just cover a few highlights. Near the top of the file, you'll see the UpMinusDown
class, which inherits from the Moonshot
class.
class UpMinusDown(Moonshot):
CODE = "umd"
MOMENTUM_WINDOW = 252
RANKING_PERIOD_GAP = 22
LOOKBACK_WINDOW = MOMENTUM_WINDOW
TOP_N_PCT = 50
REBALANCE_INTERVAL = "M"
def prices_to_signals(self, prices):
closes = prices.loc["Close"]
returns = closes.shift(self.RANKING_PERIOD_GAP)/closes.shift(self.MOMENTUM_WINDOW) - 1
...
Strategy logic is implemented in class methods (for example, prices_to_signals
), and parameters are stored as class attributes (for example, REBALANCE_INTERVAL
).
Now find the UpMinusDownDemo
class further down in the file:
class UpMinusDownDemo(UpMinusDown):
CODE = "umd-demo"
DB = "usstock-free-1d"
UNIVERSES = "usstock-free"
TOP_N_PCT = 50
COMMISSION_CLASS = USStockCommission
This class is a subclass of UpMinusDown
and thus inherits its functionality while overriding a few of its parameters. This is the actual strategy we will run in our backtest. Note the DB
parameter: it tells the strategy to use the history database we created in an earlier tutorial. The optional UNIVERSES
parameter indicates which subset of securities in the database to query. (Since the securities in our sample universe are the only securities in our history database, the UNIVERSES
parameter could be omitted in this case.) The CODE
parameter gives us an easy way to reference the strategy via the QuantRocket API.