Skip to content

View translation

BtcDailyMacroTrendRegime50200CrossLS

Hypotheses

BTC Single-Asset Macro Trend Regime Long-Short on BINANCE Daily (50d/200d MA Crossover, Months-Long Holding, Macro Horizon)

Hypotheses

Single-asset macro trend regime strategy on BTCUSDT.BINANCE using the classic 50-day / 200-day moving average crossover — one of the most documented and simplest macro-regime classifiers in financial literature. LONG when 50d_MA > 200d_MA AND the spread is widening (confirmed bull regime); SHORT when 50d_MA < 200d_MA AND spread is widening on the down side (confirmed bear regime); FLAT during regime transitions (crossover events without confirmation). This is the SINGLE-ASSET application of the Antonacci 2014 'Dual Momentum' framework simplified to time-series only. Holding periods are MONTHS (regime cycles last 3-12 months in BTC), filling the SEVERELY UNDER-REPRESENTED macro_1w_plus horizon quota (currently 0.5% — nearly untouched in 1135 experiments). The mechanism is FUNDAMENTALLY DIFFERENT from my in-pipeline TSM family (t-stat-based fast-moving signal, weekly turnover) and RSI MR family (extreme-reversal short-horizon signal): macro regime captures the slowest-moving trend persistence available in BTC daily data. Single-asset scope means no multi-asset translation curse. BTCUSDT.BINANCE 1D is on the system's explicit safe-list. Helps direction quota (90.0% long-only — adds long/short/flat positions). Fills macro horizon quota (0.5% vs the implicit need for slower-horizon strategies to balance the 48.8% mid_long_4h_12h concentration). The combination of TSM (weeks) + RSI MR (days) + MACRO REGIME (months) on the same instrument creates a multi-horizon strategy stack.

Hypotheses

Iteration-2 minimal fix for the Layer-2 TypeError (_sma() takes 2 positional arguments but 3 were given). Root cause is identical to the known proxy-binding trap: _sma was declared @staticmethod, but the Layer-2 _StrategyProxy rebinds class callables onto a stand-in instance, discarding the staticmethod descriptor and passing the proxy instance as an injected first positional argument, so the 2-param helper is called with 3 args. The fix moves _sma to a module-level free function (never bound to an instance, so no self can be injected) and updates the two call sites; module functions sidestep the descriptor protocol entirely. Nothing else changed: imports stay clean (Layer 1 green), and the 50/200 spread / regime-confirmation / entry / crossover-exit / sizing logic exercised by the synthetic harness is byte-identical. Venue remains BINANCE USD-M futures (long-short needs margin), leverage 1.0 (no amplification, so the leverage_set_but_unused gate does not trigger). The strategy fills the under-represented macro months-long horizon with a single-asset, translation-safe regime classifier.

Hypotheses

The BTC 50/200 macro-regime long-short has negative realized expectancy and is too sparse to validate. profit_factor 0.664, expectancy -$2,513/trade, Sharpe -0.066, max_drawdown 42%, with the -1.4% headline illusory: end_unrealized_pct 28.7 exceeds total_return, so the realized closed-trade record is ~-30% (the headline is an open-position mark-to-market currently up 28.7%). The 50/200 crossover whipsaws on a single asset (false golden/death crosses), losing in 3 of 6 years (2021 -36%, 2022 -13%, 2025 -28%) with avg_loss > avg_win and kurtosis 397. The strategy is a months-hold macro regime that fires only 12 trades over 6.4 years (~2/yr), far too few to support walk-forward (3 windows get ~4 trades each, holdout ~0) or any meaningful optimization. The code is correct and trades exactly as designed, so this is a refuted premise plus structural sparsity, not a code bug -- iterate cannot help and optimizing 12 net-losing trades would fit noise. Not worth 2 hours. FAILURE PATTERN: single-asset macro 50/200 MA-crossover long-short on BTC daily produces a sparse (~2/yr), net-losing realized record (PF 0.66, negative expectancy, ~-30% realized masked by open-position MTM) with a 42% drawdown -- the slow crossover whipsaws on a single asset's bull/bear transitions, and a months-hold macro regime cannot generate enough trades to validate; classic trend-crossover regime signals need a broad cross-section or many regime cycles to extract an edge, neither of which a single BTC instrument over 6 years provides.

Implementation

Long-short BTC macro trend regime on BTCUSDT.BINANCE USD-M futures, DAILY bars, pure OHLCV single feed. Uses the 50/200-day SMA crossover with a widening-spread confirmation: LONG when 50d > 200d and the normalized spread is wider than 5 bars ago (confirmed bull), SHORT when 50d < 200d and the spread is widening on the downside (confirmed bear), FLAT during unconfirmed transitions. Rides the whole multi-month regime, exiting on the opposite crossover or a 25% catastrophic stop. The signal is the continuous normalized 50/200 spread (varies every bar); the discrete regime direction gates entry. leverage 1.0.

Verification Results

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['fast_period', 'slow_period', 'min_notional', 'position_pct', 'stop_loss_pct', 'confirm_lookback'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: TypeError: BtcDailyMacroTrendRegime50200CrossLS._sma() takes 2 positional arguments but 3 were given (bar timestamp: 1735701960000) - steady_downtrend: TypeError: BtcDailyMacroTrendRegime50200CrossLS._sma() takes 2 positional arguments but 3 were given (bar timestamp: 1735701960000) - flat_ranging: TypeError: BtcDailyMacroTrendRegime50200CrossLS._sma() takes 2 positional arguments but 3 were given (bar timestamp: 1735701960000) - volatility_spike: TypeError: BtcDailyMacroTrendRegime50200CrossLS._sma() takes 2 positional arguments but 3 were given (bar timestamp: 1735701960000) - zero_volume: TypeError: BtcDailyMacroTrendRegime50200CrossLS._sma() takes 2 positional arguments but 3 were given (bar timestamp: 1735701960000) - price_gap: TypeError: BtcDailyMacroTrendRegime50200CrossLS._sma() takes 2 positional arguments but 3 were given (bar timestamp: 1735701960000)

Backtest Review

Implemented correctly and trades as specified: 12 macro-regime entries (6 long / 6 short), 0 dropped, months-long holds — no code bug; fills the macro-horizon gap

Backtest Review

Headline masks a heavy realized loss: end_unrealized_pct 28.7 exceeds total_return -1.4, so realized closed-trade return is ~-30% (the -1.4% is an open-position mark-to-market)

Backtest Review

No realized edge: profit_factor 0.664, expectancy -$2,513/trade, Sharpe -0.066 (CI -1.17 to 0.53), omega 0.90, max_drawdown 42%; avg_loss > avg_win, kurtosis 397

Backtest Review

Too sparse to optimize/validate: 12 trades over 6.4 years (~2/yr, avg hold 154d) — walk-forward windows get ~4 trades, holdout ~0

Backtest Review

50/200 crossover whipsaws on BTC: negative in 3 of 6 years (2021 -36%, 2022 -13%, 2025 -28%), largest_loss -$24,940

Outcome Summary

This strategy applied the textbook 50/200-day macro crossover to BTC long-and-short, aiming to fill the nearly-empty months-long horizon quota with a multi-horizon stack. A prior iteration crashed in Layer-2 on a staticmethod descriptor issue; the iter-2 fix (module-level SMA helper) let it run, producing 12 regime trades over 6.4 years. But the slow crossover whipsawed on BTC's regime transitions: profit factor 0.66, negative expectancy, a 42% drawdown, and a ~-30% realized record hidden behind an open-position MTM that flattered the headline to -1.4%. The analyst abandoned it before optimization, judging it both edgeless and far too sparse (~2 trades/year) to validate — a single-asset macro crossover simply cannot generate enough regime cycles to extract or test an edge.

Outcome Summary

A slow 50/200 MA-crossover regime signal needs a broad cross-section or many regime cycles to extract an edge — neither of which a single BTC instrument over 6 years provides — so it whipsaws on false golden/death crosses, produces a net-losing ~2-trade/year record masked by open-position mark-to-market, and is structurally unvalidatable.

Outcome Summary

The analyst abandoned it at backtest review as a refuted premise plus structural sparsity rather than a bug — the code traded exactly as designed, but the 50/200 crossover whipsaws on a single asset's bull/bear transitions (avg loss > avg win, negative realized expectancy), and ~2 trades/year is far too few to support walk-forward (3 windows would get ~4 trades each) or a holdout, so optimization would only fit noise.

Outcome Summary

A long-short single-asset macro trend-regime strategy on BTCUSDT daily perpetual futures (pure OHLCV) using the classic 50/200-day SMA crossover — going long in a confirmed widening bull regime (50d > 200d), short in a confirmed widening bear regime, flat during transitions, and holding for whole multi-month regime cycles with a catastrophic 25% stop, to fill the under-represented macro horizon.

Outcome Summary

Over 6.4 years it made only 12 trades (6 long, 6 short, ~2/year, ~154-day average hold, none dropped) with no realized edge: profit factor 0.664, expectancy -$2,513/trade, Sharpe -0.066 (CI -1.17 to 0.53), 42% max drawdown, kurtosis 397; the -1.4% headline was illusory since end-unrealized 28.7% exceeded it, leaving realized closed-trade return around -30%, and it lost in 3 of 6 years (2021 -36%, 2022 -13%, 2025 -28%).
Strategy report

Backtest and paper results are hypothetical. Trading involves risk of loss.