Strategies
US Risk-On/Risk-Off Regime Rotation — SPY vs Defensive Sleeve (TLT/Cash), Single Long-SMA Trend Filter with Hysteresis Band, Decades of Daily History (2-Parameter)
Outcome: Abandoned
UsRiskOnRiskOffRegimeRotationSpyTltHysteresis
Outcome Summary
A slow, months-long regime-rotation mechanism generates too few trades to ever be statistically validated in-sample, and reframing the recurring cross-asset macro-rotation family onto adjacent ETFs re-overfits every time.
Hypothesis
Implementation
Long-only US risk-on/risk-off regime rotation on the USEQ venue, daily bars. A single 100%-notional sleeve is rotated between SPY (risk-on), TLT (risk-off) and CASH. Each ETF carries the SAME trend filter: close vs its own sma_days SMA with a symmetric hysteresis_pct band -- the state flips to 'up' only when price exceeds the SMA by the band and back to 'down' only when it falls the same distance below, so oscillation around the line does not whipsaw the book. SPY up -> hold SPY; SPY not up but TLT up -> hold TLT; neither -> flat. Two searchable parameters (sma_days, hysteresis_pct); zero supplementary data; ~2-4 switches per year, which keeps spread+impact drag negligible on a commission-free venue.
Verification Results
Remove notional_pct from _param_bounds (leave sma_days and hysteresis_pct only), keeping notional_pct a fixed structural constant as described in the code comment.
The hypothesis explicitly sells a TWO-parameter overfit defence (sma_days, hysteresis_pct), but config.parameters._param_bounds includes notional_pct [0.1, 1.0] as a third searchable bound. notional_pct only affects sizing (not the signal), and the code clamps it, so this is benign for correctness, but exposing it to the optimizer mildly weakens the '2-parameter, decades of history' overfit-defence narrative. Consider dropping notional_pct from _param_bounds so the search space matches the stated 2 parameters.
No change required.
Static analysis flags min_bars_required() as shadowing a base method. This is a FALSE POSITIVE: the base template calls self.min_bars_required() (base_template.py:478) to gate warmup, so overriding it to require sma_days+2 bars is the intended, supported extension point. No action needed; noted so the warning is not mistaken for a defect.
The hypothesis's central claim is a structural defence against the 2022 stocks-and-bonds-fall-together regime, yet the sandbox's rate_shock_2022 stress window still shows -15.5% (Sharpe -2.48, DD 16.9%) and the 'normal' vol tercile is the weakest (Sharpe 0.41). The cash-when-neither-trends rule reduces but does not eliminate the 2022 leg, and TLT's slow SMA lags the flight-to-quality turn. Headline sandbox is nonetheless positive (+69.8%, Sharpe 0.82, PF 5.46, PSR 0.97) over ~4.5y. Worth watching that 2022 behaviour on the full multi-decade backtest, but this is a performance question for the analyst, not a correctness blocker.
Backtest Review
- Sharpe
- 0.51
- Total return
- 435.39%
- Max drawdown
- 25.86%
- Trades
- 35
- Win rate
- 45.7%
- Profit factor
- 4.26
Trades implement the hypothesis: 35 long-only rotations, 0 shorts, ~1.5 switches/yr over 24y of TLT-available history — the months-long regime cadence the premise predicts.
Trend-following signature is coherent: win_rate 0.457 with profit_factor 4.26 (small losers, large winners), recovery_factor 29.6.
Economically viable on USEQ: avg_trade_return_pct 5.45% is ~100x the ~0.05% USEQ floor; commission-free, impact only 0.56% of gross — fee drag is a non-issue.
Strong overfit defence for the 3-phase run: only TWO free parameters (sma_days, hysteresis_pct) over decades of daily history, and an under-represented venue (USEQ) diversifying a Binance-heavy corpus.
Reliable, plausible result: metrics_reliable=true, return is real MTM with only ~14% unrealized at end, no artifact signature.
Modest risk-adjusted edge: Sharpe 0.51, and information_ratio is negative (-0.14) with thin alpha (~1.46%/yr) vs the SPY+TLT basket benchmark — partly explained by excluded SPY dividends (~1.5-2%/yr), but the active edge is small.
2022 rate-shock window still lost -16% (Sharpe -2.39): the cash-when-neither-trends rule mitigates but does not eliminate the stocks-and-bonds-fall-together leg (QA's concern — a post-optimization performance question).
35 trades is a low sample for parameter fitting; acceptable only because the search space is 2-dimensional and the mechanism is slow/structural.
Analysis
Trades implement the hypothesis: 18-35 long-only rotations, zero shorts, months-long regime holds, drawdown 18.3% inside the pre-registered 25% cap, and per-trade return well above the USEQ fee floor (fees are a non-issue here).
Sensitivity grid is smooth (0 cliffs, full-period Sharpe ~0.53-0.66 across the sma_days x hysteresis surface) - the parameters are stable, the problem is not parameter fragility.
Decisively OVERFIT and non-generalizing: walk-forward IS 1.28 -> OOS -0.016 (is_overfitted=true), window-2 IS 2.95 -> OOS -1.02, PBO 0.754 > 0.5. The full-period Sharpe is fitted data; on unseen windows the edge disappears or reverses.
Statistically indistinguishable from noise: DSR=0.0, expected-max Sharpe 1.37 over 225 trials (29 effective), is_significant=false, does not survive programme-level FDR (keeps 4 of 275).
Structurally un-validatable: only 18-35 trades over 24 years. Holdout carries just 3 trades (<10), and the OOS vault is explicitly flagged UNDERPOWERED (~10 expected trades, need ~100). The strategy is too slow for any in-history slice to both train and validate it.
Matches a repeatedly-dead family: SPY/TLT and QQQ/GLD/TLT and SPY/TLT/GLD macro regime-rotation siblings on USEQ have all been abandoned (overfit / risk_reject / fee_edge) - reframing the same defensive-rotation mechanism onto adjacent macro ETFs has re-overfit every time.
Pre-registered predictions missed on the two that matter: declared min_trades 60 (actual 18) and min_oos_sharpe 0.8 (actual -0.016).
Benjamini-Hochberg at q=0.10 over 275 programme candidates keeps 4. A candidate that does not survive here is not distinguishable from the programme's own noise, however good its individual statistics look.
Outcome Summary
The analyst abandoned it at the ANALYZING stage after the initial backtest passed BACKTEST_REVIEW (verdict: optimize): four HARD gates failed — is_overfitted=true, OOS Sharpe -0.016 (≤0), PBO 0.754 (>0.5), and only 3 holdout trades (<10) — and the OOS vault was flagged underpowered.
A long-only, two-parameter regime-rotation strategy on the USEQ venue that rotates one 100%-notional sleeve between SPY (risk-on), TLT (risk-off, only when TLT itself trends up), and cash, using a single long-SMA trend filter with a hysteresis band over decades of daily history.
The optimized full-period backtest looked strong on paper — total return 561%, CAGR 10.3%, Sharpe 0.57, profit factor 15.0, max drawdown 18.3%, and avg_trade_return_pct 12.5% far above the USEQ floor — but over just 18 trades in 24 years. Walk-forward collapsed out-of-sample (avg IS Sharpe 1.28 vs OOS -0.016, window-2 IS 2.95 vs OOS -1.02), with PBO 0.754 and deflated Sharpe 0.0.
Backtest and paper results are hypothetical. Trading involves risk of loss.