Skip to content

View translation

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.
Strategy report

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