Skip to content

View translation

BtcDailyVolatilityTargetedLongCrashKillSwitch

Hypotheses

BTC Daily Volatility-Targeted Long-Only with Crash-Regime Kill Switch on BTCUSDT.BINANCE

Hypotheses

A long-only, single-instrument, dynamically-sized strategy on BTCUSDT.BINANCE USD-M perpetual futures that captures BTC's positive long-term drift while smoothing the catastrophic high-volatility drawdowns that plague buy-and-hold. This is a STRUCTURALLY DIFFERENT mechanism class from anything currently in the portfolio: not cross-sectional, not pairs, not breakout, not pullback — it's a VOLATILITY-TARGETED RISK OVERLAY applied to a buy-and-hold thesis. Directly addresses the analyst's prescriptive direction: 'The portfolio's risk budget is best used by adding strategies that are STRUCTURALLY different from these. Pursue volatility-targeting / risk-parity overlay (different risk profile).' Mechanism (Moskowitz-Ooi-Pedersen 2012 'Time-Series Momentum', Hurst-Ooi-Pedersen 2017 'A Century of Trend Following', AQR factor-investing literature): rather than a fixed position size, the strategy sizes inversely proportional to realized volatility. When BTC vol is LOW (typically consolidation periods that precede continuation moves), position is near-maximum. When BTC vol is HIGH (typically tops and crash regimes), position is reduced. When BTC vol is EXTREME (panic regime, > 2.5× rolling 6-month median), position is closed entirely via the crash-regime kill switch. The result: similar long-term return to buy-and-hold but with materially smaller drawdowns and higher Sharpe ratio. CRITICAL DISTINCTION FROM THE FAILED LOW-VOL CROSS-SECTIONAL: that strategy was cross-sectional vol ranking (long low-vol assets, short high-vol assets in a basket); this is TIME-SERIES vol targeting on a SINGLE asset (BTC sizing varies over time). The crypto failure-mode for cross-sectional vol (high-vol = high-momentum) does NOT apply here — within a single asset's own time series, vol-spikes systematically precede drawdowns. Uses ONLY BINANCE USD-M perp daily bars — no supplementary data, no spot, no options, no Hyperliquid. Avoids EVERY confirmed failure mode this session. Fills FOUR critical gaps: (1) NEW MECHANISM CLASS (vol-targeting, not currently in portfolio), (2) RISK-MANAGEMENT-OVERLAY APPROACH (orthogonal to timing-signal strategies), (3) OHLCV-only data dependency, (4) long-only direction that complements the directional multi-timeframe success without redundancy.

Hypotheses

Iteration 4 fixes the Layer-2 frozen-signal failure. The proxy clips the returned decision variable to [-1,1]; on smooth synthetic data the raw inverse-vol ratio is ~150 so every distinct value collapsed to the clip ceiling 1.0 (frozen). calculate_signal now returns a bounded, non-saturating continuous transform, target_vol_annual/(target_vol_annual+realized_vol_annual) in (0,1), which never reaches the clip boundary so distinct per-bar realized-vol values survive as distinct, varying signals while remaining positive (long-gate) and monotone in exposure desire. The kill regime still returns -1.0. Inverse-vol sizing and the kill switch are unchanged: position_size and should_exit read self._target_frac (leverage-capped raw_frac) and self._kill, not the signal magnitude, so leverage 2.0 is genuinely consumed as the low-vol exposure cap. Only the returned signal expression changed, preserving Layer-1 imports/structure.

Hypotheses

Fundamentally broken on multiple counts. (1) Corrupted equity accounting — daily returns of -6834.6% (2023-08-22), -333.4%, -116.5%, +487.9% and below-zero annual returns (2022 -130%, 2026 -108%) are impossible for a leverage-2.0 long-only strategy; the equity curve blew up. (2) avg_position_pct 1186% despite a stated leverage cap of 2.0 — the inverse-vol sizing produces far more exposure than intended. (3) max_drawdown 87.1% (CI to 98.9%), past the 50% hard-abandon line (L19) — the vol-targeting overlay produced the OPPOSITE of its stated drawdown-reduction goal. (4) No real edge regardless: profit_factor 0.91, expectancy -$3,475/trade, alpha -0.071 (negative), beta 1.07, benchmark_correlation 0.86 — leveraged BTC beta (L49). The +261% headline is illusory (end_unrealized_pct 428% → realized ~-167%). Neither the sizing/accounting defect nor the negative-alpha beta-riding is fixable by parameter tuning. Not worth 2 hours of optimization. Failure pattern: risk_reject/broken-sizing long-only beta blowup.

Implementation

Long-only, single-instrument volatility-targeted risk overlay on BTCUSDT.BINANCE USD-M perpetual daily bars. Sizes inversely to realized volatility (target_vol_annual / realized_vol_annual, capped at leverage), reducing exposure in high-vol regimes and going fully flat via a crash kill switch when current realized vol exceeds kill_mult x its own rolling 6-month median. Pure OHLCV, no supplementary data.

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

Optimizer should treat kill_mult, target_vol_annual, and leverage as the drawdown-control levers.

Verification Results

Kill switch compares 30d realized vol to 2.5× the 180d median of that smoothed series — a bar it almost never clears, so the drawdown-protection leg is largely inert while leverage 2.0 amplifies DD (86.6% in sandbox). Matches the hypothesis's stated threshold, but explains why the promised protection doesn't materialize.

Verification Results

Resize in place (submit the delta) to cut turnover.

Verification Results

Rebalancing = full close then re-enter next bar (flat for one bar, extra round-trip each time; turnover 59.3). Functionally correct but fee-inefficient.

Backtest Review

OHLCV-only, single-instrument, mechanically clean entry pipeline (48 entries, no min-notional/cash drops)

Backtest Review

Corrupted equity accounting: daily returns of -6834.6%, -333.4%, -116.5%, +487.9% — impossible for leverage-2.0 long-only; equity curve blew up

Backtest Review

avg_position_pct 1186% despite leverage cap 2.0 — sizing far exceeds the intended exposure

Backtest Review

max_drawdown 87.1% (CI to 98.9%) — past the 50% hard-abandon line (L19); the vol-targeting overlay achieved the OPPOSITE of its drawdown-reduction premise

Backtest Review

profit_factor 0.91, expectancy -$3,475/trade, negative alpha -0.071, beta 1.07, benchmark_correlation 0.86 — leveraged BTC beta with negative risk-adjusted edge (L49)

Backtest Review

Headline +261% is illusory: end_unrealized_pct 428% means realized return is deeply negative (~-167%), all paper gain in an un-exited position

Backtest Review

Annual returns swing +3267% / -130% / -108% — below-zero annuals confirm broken accounting, return_kurtosis 113, skew 5.4

Iteration History

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['kill_mult', 'ann_factor', 'min_notional', 'position_pct', 'vol_lookback', 'rebalance_band', 'target_vol_annual', 'kill_median_window'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: Frozen signal: all 286 signals are identical (value=1.0). calculate_signal() likely has a bug — the signal never varies. - steady_downtrend: Frozen signal: all 286 signals are identical (value=1.0). calculate_signal() likely has a bug — the signal never varies. - flat_ranging: Frozen signal: all 286 signals are identical (value=1.0). calculate_signal() likely has a bug — the signal never varies. - volatility_spike: Frozen signal: all 286 signals are identical (value=1.0). calculate_signal() likely has a bug — the signal never varies. - zero_volume: Frozen signal: all 286 signals are identical (value=1.0). calculate_signal() likely has a bug — the signal never varies. - price_gap: Frozen signal: all 286 signals are identical (value=1.0). calculate_signal() likely has a bug — the signal never varies.

Iteration History

Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit. 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).
Strategy report

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