Nicolas Liebaert Structured products & derivatives

Systematic strategy

A backtest that does not flatter itself

A 50/200 crossover on SPXL, the 3x leveraged S&P 500 ETF, with a realised volatility filter. It halves the maximum drawdown, and it loses to simply holding the ETF on every risk-adjusted measure. Both halves of that sentence matter, and most published backtests only show you one of them.

Exhibit 1 SPXL, daily, costs charged on every change of position

Loading the model

Python, NumPy and pandas are being started in your browser, then the price history is loaded and the backtest is run from scratch.

Price history, adjusted closes so dividends are reinvested on both legs. The position on any day is built from the signal of the day before, and there is a test in the repository that checks it by rewriting the end of the price series and asserting the earlier positions do not move.

What the sliders show

Move the volatility cap. Sharpe swings from roughly zero at a 30% cap to around 0.74 at 60%. A parameter that moves the headline result that much is a parameter the backtest cannot justify, and anyone showing you only their chosen setting is showing you a fitted number. What the filter does reliably is cut the drawdown. What it does not reliably do is add return.

Move the moving averages. Sharpe stays in a narrow band across all nine pairs, and stays below buy and hold in nearly all of them. That stability is the useful result: the conclusion does not depend on the parameter choice.

Raise the cost. Almost nothing happens, because the strategy trades rarely. That is worth checking rather than assuming, and it is the first thing to check on any strategy that trades often.

Why it loses

In 2022 the strategy was in the market 2% of the year and lost 8%, while the ETF lost 57%. That is the entire case for the approach, and it is a real one.

The problem is everything else. A 200 day average on a 3x ETF turns slowly, so by the time a crossover confirms a recovery the fastest part of the rebound is gone. 2019 is the clearest case: +17% against +103%. Leverage magnifies the drawdowns avoided, and magnifies the rebounds missed by exactly the same factor, and the rebounds arrive faster than a slow average can follow.

Full source and ten tests at github.com/Nicolas8330/momentum-spxl.