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).
Backtest and paper results are hypothetical. Trading involves risk of loss.