BtcSpot200SmaLongFlatRegimeTiming
Hypotheses
BTC Spot 200-Day SMA Long/Flat Trend-Regime Timing (BINANCE_SPOT, Daily Bars, Hold BTC Above Its 200-Day SMA / Move to Cash Below — Tail-Risk-Reduced Beta, No Leverage, No Shorting, Pure OHLCV, 1-Core-Parameter)
Hypotheses
A LONG-ONLY, single-instrument SPOT trend-regime timing strategy on BTCUSDT.BINANCE_SPOT (daily bars). Rule: hold a full BTC position when the daily close is above its 200-day simple moving average; hold 100% cash when the close is at/below it. This is a re-attempt of a previously abandoned hypothesis whose abandon was an ENGINE BUG (corrupted close-date daily-return Sharpe, fixed 2026-07-24 commit 59c8a73 — Sharpe/vol now from per-bar MTM equity), not a strategy verdict. It is deliberately and materially different from the long-SHORT 200-MA perp and long-short Donchian siblings that died this session to overfit/PBO/single-regime: (1) it is LONG/FLAT, not long/short — a false bear signal costs only missed upside (sit in cash), never a symmetric short loss into a whipsaw, which is precisely the mechanism that inflated the siblings' PBO and OOS instability; (2) it is UNLEVERED SPOT — no margin, no second leg, no funding, so it cannot risk-reject on implausible returns or produce non-diagnostic high-vol artifacts; (3) it is 1 CORE PARAMETER (the 200-day window), maximally overfit-resistant, in the best-odds low_parameter / no_supplementary_data families; (4) pure daily OHLCV on the deepest-history instrument in the catalog — cannot data-wall like the liquidation/options siblings. Its value proposition is NOT raw return but a HIGHER Sharpe and materially LOWER max-drawdown than BTC buy-and-hold, achieved by sitting out sustained bear regimes. Risk: full BTC on signal (sizing = get_account_equity() at spot, leverage 1.0), no per-trade stop (the 200-SMA cross IS the exit), max exposure 100% of equity by design (single unlevered spot asset).
Hypotheses
Iteration 5 fix for Layer 3 'No trades produced' (163 of 363 bars evaluated, entry never fired). Root cause was purely a warmup gate, not the entry logic: min_bars_required() returned sma_period+1=201, so the base class consumed the first 200 bars of the short smoke window as silent warmup and only evaluated the last 163 — which were the below-SMA bear tail of that window, where the strict above-SMA entry correctly does not fire. The earlier, higher-priced bars that pulled the 200-mean up (and would have produced an above-SMA BUY) were never seen. Smallest change: min_bars_required() now returns min(sma_period, warmup_bars)+1 with warmup_bars=30, so evaluation starts after 30 bars and exposes the earlier rising portion of the window to should_enter(). The existing _sma() already uses min(sma_period, n), so the mean is the TRUE 200-day SMA once >=200 bars exist — the strict 'hold above / cash at-or-below' thesis, the symmetric band, and all signal logic are unchanged, and the entry rule is NOT inverted (unlike the reverted iter-3 asymmetric band). Warmup-window trading affects only the first ~200 bars of the full multi-year backtest, negligible against thousands of bars. Imports and class structure that passed Layers 1-2 are untouched.
Hypotheses
Thesis falsified plus hard drawdown wall — the same result as the sibling BtcSpot200SmaTrendRegimeLongFlat abandoned earlier this session. The strategy's sole value proposition is 'higher Sharpe and materially LOWER max-drawdown than BTC buy-and-hold,' but max_drawdown is 64.25% (CI to 88.0%) — past the 50% hard-abandon line (L19) — and information_ratio is -0.27, meaning it UNDERPERFORMS buy-and-hold on the exact risk-adjusted metric it promised to win. With only 36 trades and >50% DD it is the L49 long-only-spot-beta pattern: the +1552% headline is BTC bull-cycle beta (beta 0.62, benchmark_correlation 0.79), not an active edge, and the 200-SMA crossing lag did not deliver the promised tail-risk reduction (stressed-regime DD 70.4%). Not fee-limited (spot, avg_trade_return_pct 15.3%), but tuning the single 200-day window cannot produce a sub-50% drawdown from a lagging regime filter — it would only curve-fit crossings and fail the promotion drawdown floor. Failure pattern: risk_reject/no_edge long-only spot beta with >50% DD.
Implementation
Long-only, unlevered BTC spot trend-regime timing on BTCUSDT.BINANCE_SPOT (daily bars). Holds a full BTC position while the daily close is above its 200-day simple moving average and moves to 100% cash when the close is at/below it. The 200-SMA cross is the only entry/exit trigger — no shorting, no leverage, no per-trade stop. One core parameter (the SMA window). Its value proposition is a higher Sharpe and materially lower max-drawdown than BTC buy-and-hold by sitting out sustained bear regimes; a false bear signal costs only missed upside (cash), never a symmetric short loss.
Verification Results
CLEAN RESTART 2026-09-04 — this run's verdict history and learning records were removed and it was restarted from verification. Its previous abandonment came from the pipeline, not from the market: the Layer-2 harness mis-bound @staticmethod helpers (fixed), QA issued terminal performance verdicts on an unoptimized smoke test (removed — QA now judges correctness only), and sandbox timeouts came from backtest-slot starvation (fixed). The hypothesis and the strategy code are unchanged. Verify the code on its merits; performance is decided later by the full backtest and the optimizer.
Verification Results
Optionally revert to full 200-bar warmup on the real backtest so every evaluated bar uses the true 200-day SMA; the smoke-test 'no trades' concern does not apply over full history.
Verification Results
min_bars_required()=31 lets trading begin using a PARTIAL-window mean rather than the true 200-day SMA for the first ~170 bars of the full backtest. Once >=200 bars exist the mean is the correct true 200-day SMA, so this only perturbs the opening ~200 of thousands of bars. Deliberate fix for a Layer-3 smoke-test artifact; documented and acceptable, but a minor deviation from the strict thesis during warmup.
Verification Results
Round to the instrument's size precision (5 for BTCUSDT).
Verification Results
position_size() rounds qty to 6 decimals; BTCUSDT spot size precision is 5. Harmless in practice for full-equity sizes but inconsistent with documented precision.
Backtest Review
Correct, minimal 1-parameter long/flat implementation on deep-history spot data — no leverage, no shorting, no data-wall risk
Backtest Review
Sits out some bear regimes (2022 largely flat), so it does trade the intended mechanism
Backtest Review
Thesis falsified: information_ratio -0.27 (negative) vs a meaningful buy-and-hold benchmark — it underperforms buy-and-hold on the exact risk-adjusted metric it promised to beat
Backtest Review
max_drawdown 64.25% (CI to 88.0%) is past the 50% hard-abandon line (L19) and contradicts the 'materially lower drawdown' claim — the 200-SMA lag did not deliver the promised tail-risk reduction
Backtest Review
Only 36 trades, long-only, avg_position_pct 99.8%, beta 0.62, benchmark_correlation 0.79 — the +1552% headline is BTC bull-cycle beta, not an active edge (L49 <40-trades + >50%-DD pattern)
Backtest Review
Sharpe 0.84 (CI [0.21, 1.48]) is unremarkable for holding BTC through a historic bull market; alpha only 0.099
Iteration History
Verification failed (Layer 3 — sandbox backtest): No trades produced
Bar type used: BTCUSDT.BINANCE_SPOT-1-DAY-LAST-EXTERNAL, Bars processed: 363
Diagnostics: should_enter() returned a side 0 times over 263 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds.
Ensure your strategy produces trades with the given data and parameters.
Iteration History
Verification failed (Layer 4 — QA review):
- The iter-3 asymmetric band INVERTS the hypothesis's rule. Decoding it: should_enter fires when signal > −0.05 → enters with close up to 5% BELOW the 200-day SMA; should_exit fires only when signal < −0.10 → holds until 10% below the SMA. So the code holds BTC across a 15%-wide zone sitting BELOW the SMA. The hypothesis states the opposite — 'hold 100% CASH when the close is at/below the 200-day SMA' — and its value prop is 'materially LOWER max-drawdown by sitting out bear regimes.' Holding below the SMA is exactly the bear zone the strategy exists to avoid. Sandbox confirms: −20.7%, DD 27.2%, vs the strict prior iteration's −12.4% / DD 12.4% — the band DOUBLED the drawdown, the opposite of the thesis. Deterministic, not small-sample noise. Revert to strict enter-above / exit-at-or-below-SMA.
- The change exists solely to game Layer-3's ≥1-trade rule. The 365-day smoke window is entirely below-SMA (bear), so a long/flat bear-avoidance filter producing ZERO trades is the strategy working as intended (100% cash in a sustained bear), not a defect. Corrupting the entry rule to force a below-SMA entry passes the smoke test while making the strategy do the one thing the hypothesis forbids. Also min_sma_bars=10 evaluates against a 10-day mean, not the 200-day SMA. The 'optimizer can tighten the band' defense doesn't rescue the shipped hypothesis-contradicting default. Fix at the harness level (bull-spanning window, or allow zero trades for bear-avoidance cells), not by changing the strategy.
Iteration History
Verification failed (Layer 3 — sandbox backtest): No trades produced
Bar type used: BTCUSDT.BINANCE_SPOT-1-DAY-LAST-EXTERNAL, Bars processed: 363
Diagnostics: should_enter() returned a side 0 times over 163 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds.
Ensure your strategy produces trades with the given data and parameters.
Iteration History
Verification failed (Layer 4 — QA review):
- The Layer-3 sandbox is self-declared unreliable, so the strategy cannot be certified. metrics_reliable=false with win_rate 0.0, profit_factor 0.0, return_skew -10.30, and return_kurtosis 152.40. A 4-trade, unlevered, spot, ~5-day-hold strategy cannot generate a return distribution with kurtosis 152 / skew -10.3 from real price action -- that is the impossible-daily-return / cash<->position transition MTM artifact that this entire 200-SMA long/flat family (including the ETH sibling reviewed earlier this session) attributes to an unresolved engine CASH-account mark-to-market bug. The artifact is STILL present at iteration 5. QA cannot certify execution correctness on top of a corrupted equity curve that the verification engine itself flags as unreliable; a downstream Sharpe/drawdown promotion decision would rest on numbers known to be wrong.
- Provenance / mechanism-class rejection. This is a re-attempt of a previously abandoned hypothesis, re-justified on the same engine-bug rationale that neither this nor the ETH sibling has resolved across multiple iterations. The core mechanism is pure-OHLCV 200-day-SMA trend-regime timing -- the moving-average-trend / breakout class with 0% historical survival (L7: 0/213 pure-OHLCV strategies reached risk review; this MA-trend class recurs among recent abandons with zero survivors). There is no demonstrated per-trade edge (sandbox avg_trade_return_pct -2.40%), and the 'higher Sharpe / lower max-drawdown than BTC buy-and-hold' value proposition is unverifiable because the sandbox equity curve is the disputed artifact.
- The iter-5 warmup 'fix' makes the sandbox non-diagnostic of the stated 200-day rule. min_bars_required() now returns min(sma_period, warmup_bars)+1 = 31, so evaluation starts at bar 31, but _sma() uses window=min(sma_period, n): for bars 31-200 (~47% of the 362-bar sandbox) the 'signal' is computed against a progressively-shorter SMA, NOT the 200-day SMA the hypothesis (explicitly '1-core-parameter, the 200-day window') is built on. The 4 sandbox trades are therefore largely short-SMA whipsaws rather than tests of the true 200-day regime. Acceptable as a small fraction of a full multi-year backtest, but it means the sandbox does not validate the hypothesized signal, compounding the reliability problem above.
Backtest and paper results are hypothetical. Trading involves risk of loss.