DeribitBtcWeeklyDeltaHedgedAtmStraddleVrp
Hypotheses
Delta-Hedged Short-Straddle Variance-Risk-Premium Harvest — Deribit BTC Weekly ATM Straddle Hedged with Binance Perp, IV>RV Gated, Cross-Venue Market-Neutral (~7-Day Roll, 3-Parameter)
Hypotheses
A MARKET-NEUTRAL, CROSS-VENUE, options-native strategy that harvests the crypto variance risk premium (IV persistently exceeds subsequent RV) the clean way — by SHORTING a near-ATM weekly straddle on Deribit BTC and DYNAMICALLY DELTA-HEDGING it with the Binance BTCUSDT USD-M perp so the position stays directionally flat and isolates the vol spread. This is deliberately DISTINCT from the already-pending static short-strangle (which relies only on strike-selection neutrality and drifts directional intra-week); here neutrality is ACTIVELY maintained by rehedging the perp leg whenever accumulated delta breaches a band. It targets the three most under-represented buckets at once: options (~5% vs ≥15% quota), cross-venue (7.1% vs ≥15%), and market-neutral direction (long-only is 86% vs ≤55%). It is NOT an OHLCV momentum/trend composite (0/213 dead class, L56), NOT funding-differential carry (L57), NOT a liquidation/quarterly feed (L58), and NOT a sub-fee microstructure fade. Only 3 tunable parameters: the IV−RV gate threshold, the delta rehedge band, and the buy-back loss stop (as a multiple of premium collected). Risk controls: cap short-straddle notional so a worst-case unhedged gap risks ≤2.5% of equity; one straddle open at a time; the perp hedge is sized exactly to −(net option delta) so gross directional beta ≈ 0; hard stop closes both legs on a runaway loss.
Hypotheses
Iteration 3 fixes exactly the reported Layer-2 failure and nothing else. Root cause: FactoryStrategy._bar_ts is a STATICMETHOD, and the Layer-2 proxy re-binds every callable it finds via types.MethodType(func, instance); a staticmethod comes back from getattr as a plain function, so re-binding makes it a BOUND method and any self._bar_ts(bar) call arrives as (self, bar) against a one-argument signature -- 'TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given' in all six scenarios. The fix is a three-line instance-method shadow, def _bar_ts(self, bar): return _ts_ns(bar), which is correct under BOTH bindings (the proxy's and NautilusTrader's), so no base-class code path can reintroduce the crash; the class's own timestamp reads were additionally routed through an unambiguously named module-level helper (_bar_ts -> _ts_ns, three call sites) so the shadow can never be confused with the helper it delegates to. I verified locally against the real verifier before submitting: Layer 1 passes and all six synthetic scenarios (steady_uptrend, steady_downtrend, flat_ranging, volatility_spike, zero_volume, price_gap) now pass with no exception. IMPORTANT PIPELINE NOTE, flagged rather than silently worked around: the brief's previous_code for this run was NOT this strategy -- it contained SolEthBetaHedgedResidualMeanReversionPair (an unrelated SOL/ETH pairs strategy), whose self._bar_ts calls are what produced the reported TypeError, while the parameter list in the same feedback (rolling_options, hedge_instrument, iv_rv_gate_vp, hedge_band_frac, loss_stop_mult, straddle_notional_frac...) is this straddle's. The pairs code was written to this run's strategy file (src/strategies/generated/DeribitBtcWeeklyDeltaHedgedAtmShortVolVrp_v1.py) by a routing mix-up. I therefore restored the straddle implementation that matches this hypothesis and this run's config, and applied the _bar_ts fix to it, so code, config and hypothesis are coherent again. Nothing else changed: the DVOL IV source, the IV-RV continuous signal, incremental O(1) RV state, the roll/gate latch, the loss stop, the band- and cadence-limited perp delta hedge and all sizing are byte-identical to the version that already cleared Layer 1.
Hypotheses
data_wall: Not worth 2 hours of optimization: the weekly Deribit BTC ATM option chain only spans ~June-Sep 2026, giving ~12 straddle cycles over 82 days (24 option trades). That is far too thin for the 3-phase walk-forward (≈4 straddles/window) + holdout to produce anything but overfit noise, and deflated_sharpe is uncomputable. The strategy is well-formed and the trades match the hypothesis (paired short call+put, perp delta-hedge), so this is NOT a code or premise flaw — it is a DATA limitation. The impressive headline stats are untrustworthy: realized equity moved only +2.3% ($200k->$204.6k) yet Sharpe 5.10 / Sortino 22 / max_drawdown 78.6% are reported, and the 78.6% DD is a metrics artifact (equity moved ~0.8% at that timestamp; the equity curve rows are non-chronological). Because option cadence + limited chain history means iteration cannot raise the sample, revive and re-run the identical mechanism once the weekly Deribit BTC chain accumulates ~1.5-2+ years of history so a real walk-forward and holdout have an adequate number of cycles. abandon_class=data_wall/unmeasurable (a DATA verdict, not an edge verdict).
Implementation
Market-neutral, cross-venue variance-risk-premium harvest. Each weekly Deribit BTC expiry (entered ~7 DTE) the strategy compares forward implied vol (Deribit DVOL) with trailing realized vol over rv_window_hours and, when IV exceeds RV by at least iv_rv_gate_vp vol points, SELLS the ATM straddle (one call + one put, same strike/expiry, both legs together or neither). Directional exposure is not assumed away by strike symmetry, it is actively removed: every hourly bar the net Black-Scholes delta of the open legs is computed from each leg's strike, time-to-expiry and prevailing IV, and the BINANCE BTCUSDT USD-M perp is traded to -(net delta), only when the gap exceeds hedge_band_frac x one leg's contract size and at most once per hedge_min_interval_hours; with no options open the perp is flattened immediately (that path is exempt from the cadence limit). Risk: structure notional capped at 25% of equity, one straddle at a time, stopped periods latched, and a buy-back stop that closes both legs when open loss reaches loss_stop_mult x premium collected. 3 tunables (iv_rv_gate_vp, hedge_band_frac, loss_stop_mult) with clamps declared in _param_bounds; leverage 1.0.
Verification Results
Verification failed (Layer 4 — QA review) [class=not_measurable]:
- [edge_concern] Even setting coverage aside, the headline sandbox metrics (Sharpe 7.11, PF 2.25, avg_trade_return_pct +13.92%) are computed over ~4-5 weekly straddle cycles and are not trustworthy — classic tiny-sample artifacts. If Deribit options history later deepens, the analyst should re-evaluate edge on the full sample, not these numbers.
- NOT MEASURABLE — insufficient Deribit options history. The sandbox ran over only data_days=31, despite a 1-HOUR primary bar whose sandbox budget is ~833 days (a sibling 1-HOUR BTC run this batch got 831 days). The binding constraint is the rolling Deribit option chain, whose history spans only ~31-34 days (also stated verbatim in a sibling hypothesis this session). This strategy rolls WEEKLY, so across ALL available options history it opens only ~4-5 straddle cycles; the 58 'trades' are inflated by per-bar perp hedge rebalances. A weekly-roll VRP harvest needs dozens of expiries to measure edge; ~4-5 cannot, and walk-forward/holdout cannot partition so few. Will die 'unmeasurable' downstream after burning a full backtest + optimization.
- on_stop() does not explicitly flatten the Binance perp hedge or force-close open Deribit legs across venues (checklist item 13). Backtest-cosmetic only.
Verification Results
Analyst to run the full multi-year backtest, inspect performance in high-vol stress_windows, and confirm delta-hedge cost + short-gamma losses do not erase the VRP premium; check realized skew/tail on the full sample.
Verification Results
The delta hedge rehedges at most once per hedge_min_interval_hours (4h) on 1H bars, so intra-interval gamma can leave residual directional exposure between rehedges, with the loss stop / notional cap the only backstops against a gap. Invisible in the benign 91-day window (max_drawdown 0.8%) but materially larger over a full window with vol spikes. Not a code defect — the hedge is correctly signed and band/cadence-limited by design.
Backtest Review
Mechanism is correctly implemented and matches the hypothesis: it sells the ATM call+put together (never a naked directional short), delta-hedges with the BTCUSDT perp, and the trade log confirms both legs enter/exit paired with the perp chasing net option delta.
Backtest Review
Targets under-represented buckets (options, cross-venue, market-neutral) and only 3 tunables.
Backtest Review
Per-cycle option P&L is generally positive (theta capture visible), so the VRP structure is doing roughly what it should on the cycles it saw.
Backtest Review
Fatal sample-size problem: the Deribit weekly BTC ATM option chain only exists in the catalog from ~June 2026, so despite the 2018-start perp history the strategy could only trade ~12 weekly straddle cycles over ~82 days (24 option trades). A 3-phase walk-forward would fit ~4 straddles per window — noise. deflated_sharpe is null (uncomputable).
Backtest Review
Headline metrics are implausible/unreliable and cannot support promotion or optimization: the account actually moved only +2.3% ($200,000 -> $204,607) over 3 months, yet Sharpe is reported 5.10, Sortino 22, annualized vol 195%, and max_drawdown 78.6%. The 78.6% DD is a computation artifact — around its 2026-08-20 timestamp equity only moved ~0.8% — because the equity-curve rows are non-chronological, corrupting the drawdown/return series.
Backtest Review
Option cadence (one weekly straddle at a time) plus the ~3-month chain history means iteration cannot raise the trade count; there is nothing to optimize toward on 12 cycles without curve-fitting.
Iteration History
Verification failed (Layer 4 — QA review):
- STRUCTURALLY UNMEASURABLE short-volatility options strategy (L26), even more acute than its already-failed short-strangle sibling. The developer states lookback_days=84 (~12 weekly cycles, 24 option bar types) is a hard infrastructure ceiling: each bar type costs ~9s of catalog query against the 300s Layer-3 wall clock, and a longer history 'needs the catalog file-list caching fix, not a change to this strategy' — the window CANNOT be expanded by re-coding. Worse, the sandbox actually ran only 33 data_days (~4-5 weekly straddle cycles, further thinned by the IV>RV gate). The 65 reported 'trades' are dominated by perp RE-HEDGES, not independent straddle bets, so the number of genuine short-vol events is single-digit. This is a strategy whose entire risk lives in the tail (the expiry where spot gaps through the ATM strike faster than the perp can hedge), and 4-5 cycles cannot sample it. The metrics are the exact small-sample mirage L26/L17 warn about: Sharpe 5.68 (>5), Sortino 34.8, PF 1.71 — yet largest_loss -2199 already exceeds avg_win 369, so one bad expiry erases the record. sharpe_ci spans [1.01, 9.94], uninformative.
- Feasibility mismatch with the optimization pipeline. The implementation is pinned to an 84-day window (in practice 33 days of data), but Phase 2 walk-forward requires 3 IS/OOS windows and Phase 3 a 15-day holdout tested at >= 70% of WF OOS Sharpe. From ~5-12 weekly straddle cycles this cannot be populated — a 3-way walk-forward leaves ~1-4 cycles per window and the holdout ~2. The strategy cannot clear the gates it would be routed into, independent of whether the VRP edge is real.
- Cross-venue teardown (checklist #13): on_stop() logs a summary and calls super().on_stop() but does not explicitly flatten the Binance BTCUSDT.BINANCE perp hedge leg. If RollingOptionsStrategy.on_stop() only closes the option legs, the perp hedge could be left open at run end on the second venue. Harmless to metrics here (end_unrealized_pct null, metrics_reliable true), but in paper/live a residual naked perp is exactly the directional exposure the thesis exists to avoid.
Iteration History
DeribitBtcWeeklyDeltaHedgedAtmShortVolVrp
Iteration History
Verification failed (Layer 2 — synthetic scenarios):
Parameters used: ['leg_sides', '_param_bounds', 'contract_step', 'iv_rv_gate_vp', 'min_contracts', 'loss_stop_mult', 'risk_free_rate', 'hedge_band_frac', 'rolling_options', 'rv_window_hours', 'hedge_instrument', 'roll_buffer_hours', 'min_hedge_notional', 'hedge_qty_precision', 'straddle_notional_frac', 'hedge_min_interval_hours']
Check that __init__ sets all attributes from self.parameters.get().
- steady_uptrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000)
- steady_downtrend: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000)
- flat_ranging: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000)
- volatility_spike: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000)
- zero_volume: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000)
- price_gap: TypeError: FactoryStrategy._bar_ts() takes 1 positional argument but 2 were given (bar timestamp: 1735689600000)
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.