Strategies
Long-Horizon Trend-Following Basket Across Majors (~200-Day Absolute Trend, Long-Short, Binance USD-M Futures, Pure OHLCV, Weekly Rebalance)
Outcome: Abandoned
LongHorizonTrendFollowingMajorsBasketLS
Backtest gate: - metrics unreliable: 261 trades / 2437 data days is too little evidence (need >=5 trades over >=10 days) — increase signal frequency or widen the window
Hypothesis
Negative expectancy on a reliable 273-trade / 6.7-year sample: profit_factor 0.962 (<1), avg_trade_pnl_usd -39.30, expectancy -$39.30/trade, CAGR -2.19%. The +48.2% total_return is a mark-to-market artifact — end_unrealized_pct 58.9 means the ENTIRE headline is un-exited open positions marked to the last bar; the realized record is negative. The high equal-weighted avg_trade_return_pct (3.03%) is contradicted by the negative size-weighted USD expectancy: losing legs carry larger notional. Sharpe 0.35 with CI [-0.43, 1.08] straddling zero, losing in 3 of the last 5 full years (2025 -38.3%), and the edge confined to the normal-vol tercile confirm no robust gross edge. Commissions are only 1.18% of gross, so this is not fee-fragility — the long-horizon net-directional trend signal is gross-negative on majors, and optimizing the 3 tunables cannot invert a PF<1 signal. This is the multi-instrument long-short basket signature (L45/L63, multi_instrument ~0/84) whose headline return is beta/leverage MTM, not per-name edge. Not worth 2 hours of optimization. abandon_class=negative_expectancy.
Implementation
Long-short long-horizon (Faber / managed-futures) absolute-trend basket across 10 full-history Binance USD-M majors (BTC, ETH, BNB, XRP, ADA, SOL, DOGE, LTC, LINK, BCH) on 1-DAY bars. Each leg is held LONG when its own ~200-day trailing return is positive and SHORT when negative, sized equal-RISK by inverse realized volatility (vol_target / std(20d returns), clamped to [0.3, 1.5]) and capped so aggregate gross never exceeds 1x equity. Because the signal is ABSOLUTE (own-trend) rather than cross-sectional, the book is net-directional: net-long in broad uptrends, net-short in broad downtrends, which is the structural crash protection. Positions move to target through a single netting delta order per leg on each calendar rebalance date; with the default no-trade band of 1.0 a leg trades only when its trend sign FLIPS, when it is newly armed, or when its target goes to zero, so trends are allowed to run and turnover stays at a few flips per name per year. Pure OHLCV, no supplementary data, leverage 1.0.
Verification Results
sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of BTCUSDT.BINANCE-1-DAY-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Optionally revise the hypothesis text to say '200-day trend lookback, weekly rebalance, on daily bars' to stop the heuristic from re-flagging it. No code change required.
The Layer 1.5 consistency check flagged the hypothesis title ('~200-Day / 40-week / Weekly Rebalance') against config.bar_type=1-DAY as a possible timeframe contradiction. On inspection this is a FALSE POSITIVE: the hypothesis specifies a ~200-DAY trend LOOKBACK and a WEEKLY REBALANCE cadence, not weekly bars. The code correctly uses 1-DAY bars with trend_lookback=200 (days) and rebalance_days=7 (weekly grid). A weekly-bar implementation would make the 200-lookback span 200 weeks and would be the actual mismatch. No change needed; noting so the warning is not re-raised as blocking.
No action needed; the override is deliberate and respected by the base.
min_bars_required(self) overrides a base framework method (static analyzer base_shadow warning). Verified against base_template.py line 412: the base DOES call self.min_bars_required() to gate primary processing, so the override (returns max(trend_lookback,vol_lookback)+2 = 202) is correctly honored and is actually beneficial (ensures 200-day warmup). calculate_signal also independently guards with an internal length check, so even a mis-wired warmup would not cause a look-ahead. Benign.
Sandbox is positive and coherent (total_return +58.8%, PF 1.21, avg_trade_return_pct +4.06% over 266 trades, avg hold 74d), but risk-adjusted edge is modest and regime-dependent: Sharpe 0.43 with CI [-0.34, 1.18] straddling zero, and regime_performance shows the edge lives almost entirely in the 'normal' vol tercile (+82.2%, Sharpe 1.43) while both 'calm' (-8.3%) and 'stressed' (-5.5%) terciles are negative. Max drawdown 39% (CI to 65%) and a 699-day underwater span. This is a single unoptimized draw over a truncated window, so it does not block — but the analyst should confirm the long-horizon trend factor survives outside the normal-vol regime and clears the medium-horizon momentum baskets it claims to be distinct from before spending optimization time.
Backtest Review
- Sharpe
- 0.35
- Total return
- 48.20%
- Max drawdown
- 44.24%
- Trades
- 273
- Win rate
- 41.8%
- Profit factor
- 0.96
Well-formed diversified basket on full-history majors; adequate 273-trade / 6.7-year sample (metrics_reliable=true)
Trades implement the hypothesis (139 long / 134 short net-directional legs, ~72d holds — the low-turnover let-trends-run design is faithfully coded)
avg_trade_return_pct 3.03% clears the fee floor on an equal-weighted basis; commissions only 1.18% of gross, so this is NOT a fee-drag death
Negative gross edge: profit_factor 0.962 (<1), avg_trade_pnl_usd -39.30, expectancy -$39.30/trade — size-weighted USD expectancy is negative because losers carry larger notional than the positive equal-weighted avg_trade_return_pct suggests
The +48.2% headline is a mark-to-market illusion: end_unrealized_pct 58.9 means the entire headline is un-exited open positions at backtest end; realized track record is negative and CAGR is -2.19%
Sharpe 0.35 with CI [-0.43, 1.08] straddles zero; loses in most calendar years (2021 -26.7%, 2024 -3.6%, 2025 -38.3%) and the edge lives only in the normal-vol tercile (calm -14.5%, stressed +9.8% but normal +56.8%) — QA's regime concern borne out
Long-horizon trend as a distinct factor is not demonstrated: benchmark_meaningful=false, and the strategy does not beat simply holding the basket on a realized basis
Analysis
Backtest gate: - metrics unreliable: 261 trades / 2437 data days is too little evidence (need >=5 trades over >=10 days) — increase signal frequency or widen the window
Backtest and paper results are hypothetical. Trading involves risk of loss.