Skip to content

View translation

BtcShortDatedDefinedRiskStrangleVrpHarvest

Hypotheses

BTC DAILY (1DTE) Defined-Risk Short-Strangle — 0-1DTE Variance-Risk-Premium Harvest on Binance Options (Engineered for the 90-Day Chain Cap: DAILY Frequency for Trade Count, O(1) Compute for the Timeout Wall, Held-to-Expiry, IV-Rich Filter, 3-Parameter)

Hypotheses

A DEFINED-RISK short-volatility structure on BINANCE_OPTIONS BTC using the SHORTEST-dated (next-day / 1DTE) expiry — deliberately fixing the two infrastructure death-modes that have killed every recent options hypothesis, and filling the single emptiest bucket in the portfolio (BINANCE_OPTIONS = 0.0% / 1 experiment; options combined ~5.3% vs the 15% quota). The two documented death-modes and their fixes: (1) STRUCTURALLY UNMEASURABLE TRADE COUNT — the Deribit ETH weekly bull-put-spread was abandoned because the ~90-day options-chain catalog window only yields ~13 weekly structures (~6-7 after gating), below the ~30-trade floor. FIX: trade the DAILY expiry, one structure per day → ~60-90 trades inside the same 90-day window, comfortably clearing the trade-count floor and giving the analyst a measurable sample. (2) 300s LAYER-3 TIMEOUT — the Deribit BTC iron-condor died on a per-bar full-history rescan. FIX: all logic is O(1) per bar; one decision per day at a fixed settlement time, IV-rank read from a fixed-length rolling deque, no min()/sorted()/rescan anywhere. Structure: each day, sell the next-day-expiry ~20-delta CALL and ~20-delta PUT (short strangle) and BUY the ~10-delta wings on both sides (defined-risk iron-condor-lite), collecting net credit and harvesting the 0-1DTE variance risk premium. It is differentiated from the pending/abandoned options set (all WEEKLY: bear-call-spread, iron-fly, bull-put-spread, iron-condor) by TENOR (daily/1DTE vs weekly — a fundamentally different theta/gamma profile and the ONLY tenor that clears the trade-count floor under the 90-day cap) and by being a symmetric OTM strangle. Market-neutral short-vol (not long_only), single-underlying, held to cash-settlement (no exit fills). NOTE for the developer/QA: confirm BINANCE_OPTIONS BTC DAILY-expiry chains are present in the catalog for the backtest window before coding — if only weekly BTC expiries exist, fall back to the shortest listed tenor and report the realized trade count.

Hypotheses

ITERATION 3 — NO CODE CHANGED EXCEPT THE RECORDED MEASUREMENT, BECAUSE QA FOUND NO CODE DEFECT. All three Layer-4 findings were labelled confirmed engine/data-layer blockers, including QA's own statement that no strategy-code edit can create the daily tenor. Editing working code to look responsive would risk regressing three passing layers for zero gain. WHAT I DID DO: closed the one open question that could have changed the verdict. My earlier ~7.3s-per-instrument figure came from an UNBOUNDED catalog read, whereas BacktestRunner passes start/end — if the bounded read were cheap, the trade-count blocker would dissolve and this hypothesis would be verifiable at weekly tenor. I measured the exact call the runner makes, catalog.bars(bar_types=[bt], start=..., end=...): 7.96s PER INSTRUMENT, slightly WORSE than unbounded, and it returned ZERO bars for those contracts. So the cost is fixed per-call overhead — resolving one bar type against a 36,987-directory catalog — independent of the date filter and of how much data is returned. THIS GENERALISES THE BLOCKER BEYOND THIS HYPOTHESIS, which is the finding I most want on record. At ~8s/instrument: the 30-cycle floor needs 120 instruments = ~955s (3.2x over the 300s cap); the 75-cycle daily target needs ~2,388s (8x over); and critically, even a MINIMAL two-leg defined-risk vertical at the 30-cycle floor needs ~478s (1.6x over). No options structure, at any leg count or tenor, can reach the trade-count floor in this factory today. The largest chain that completes is ~24 legs = ~6 cycles, which is what produced the sandbox's data_days=4 and metrics_reliable=false. THE FIX IS ONE ENGINE CHANGE, MEASURED BOTH WAYS: passing the whole list to catalog.bars() in a SINGLE call loads 20 instruments in 7.8s (0.39s each, 18.6x faster). Then the 30-cycle floor costs ~47s and the full 75-cycle daily target ~117s — both comfortably inside the cap. Adding daily_expiries() plus a `roll == "daily"` branch (the engine is currently the binary `weekly_expiries(...) if roll == "weekly" else monthly_expiries(...)`, and 14/14 catalog BTC expiries are Fridays) would then deliver this hypothesis as designed. BINANCE_OPTIONS is a separate data-engineer task: Deribit-only resolver, zero catalog data, and a mirror that cannot be backfilled because the API serves only currently-listed contracts. MY RECOMMENDATION IS ABANDON THIS RUN — not because the edge failed, but because it was never measurable. The structure itself is the strongest options result I have measured here: over 279 weekly cycles (Black-Scholes at DVOL, realized BTC path) it earns +0.458% of spot per cycle unconditionally (t=+3.87, win 0.72) and +0.715% at IV-rank >= 0.30 (t=+4.20, win 0.79, worst cycle -4.26%), rising monotonically to +0.923% at rank >= 0.50. That edge justifies the ~1-line batched-read fix; it cannot be bought with a fourth strategy submission, which would return this identical verdict at the cost of another full verify cycle. The configured run must not be forwarded to a walk-forward or holdout — with ~6 cycles and 4 data days it is a machinery smoke test only.

Hypotheses

Structurally unmeasurable options structure — not code-fixable — and the developer's own docstring pre-registers ABANDON ('ITERATION 3 — NO CODE DEFECT EXISTS'). The backtest is a machinery smoke test, not evidence: 8 trades over 8 data_days, metrics_reliable=false, sharpe_note 'Unreliable: only 2 days moved the equity curve (span 8d)', effective_daily_obs 2; the headline Sharpe 10.26/calmar 3.37 are artifacts of a 2-observation window and avg_trade_return_pct is actually -1.21%. The blocker is infrastructure, not strategy code: options-chain catalog reads cost ~7.96s per instrument (36,987-directory resolution, independent of the date filter), so even a minimal 2-leg vertical at the 30-cycle floor (~60 instruments ≈ 478s) exceeds the 300s Layer-3 cap and the 4-leg daily target is ~8× over — and the hypothesis's two fixes are mutually destructive (more frequency → more legs → worse timeout). BINANCE_OPTIONS additionally has zero catalog data, so it ran on Deribit weekly rather than the required daily BTC tenor. This is the recurring Deribit/options data-and-timeout wall (L23/L27/L67) that has made every options structure untestable this session. The developer honestly measures the VRP edge off-engine as genuinely positive (+0.46-0.92%/cycle) and correctly identifies the fix as an ENGINE change (batched catalog.bars() call + a daily-expiry branch), which no strategy-code iteration can deliver — a 4th iteration returns this same verdict. META-NOTE FOR RESEARCH/ENGINEERING: this edge deserves the batched-catalog-read engine work; do not re-submit it as a strategy until options structures are verifiable in the harness. Failure pattern: structurally unmeasurable/timeout options (L23/L27/L67).

Implementation

Defined-risk symmetric short strangle on BTC options, harvesting the variance risk premium. Each cycle the chain resolver supplies four front-expiry legs: the ~5% OTM call and put are SOLD and the ~10% OTM call and put are BOUGHT as wings, capping loss per side at the 5% strike width less the credit. The cycle is established only when DVOL's percentile rank within its trailing 365-day history is >= 0.30, decided once per expiry and cached. Held to 2 hours before expiry — no mid-cycle exit logic. Per-bar cost is O(1); the IV lookup is a binary search into arrays built once. Each side is traded ONLY if both its legs resolved, so an unpaired short is dropped rather than sold naked. NOTE: this runs WEEKLY on Deribit, not daily on Binance Options — both tenor and venue were verified unavailable in this engine, and the trade-count floor is unreachable for any options structure under the current per-instrument data loader. The configured run is a machinery smoke test (~6 cycles), not evidence about the edge. Three tunable parameters: iv_rank_min, iv_rank_window_days, roll_buffer_hours.

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.

Backtest Review

Clean, honest engineering: defined-risk enforced in code (no naked shorts), O(1) IV-rank gate, correct leg-role-by-strike classification, developer measured the blocker precisely and pre-registered the verdict

Backtest Review

The underlying VRP edge, measured off-engine over 279 cycles, is genuinely positive (+0.46-0.92%/cycle) — worth an engine change, not another submission

Backtest Review

Structurally unmeasurable: 8 trades / 8 data_days, metrics_reliable false, sharpe_note flags only 2 observations moved the curve; headline Sharpe 10.26 is a 2-point artifact and avg_trade_return_pct is -1.21%

Backtest Review

Infrastructure blocker (per-instrument catalog read ~7.96s) puts even a minimal 2-leg structure over the 300s cap; higher frequency multiplies the leg count that causes the timeout

Backtest Review

BINANCE_OPTIONS has zero catalog data; ran on Deribit weekly, not the daily BTC tenor the hypothesis requires

Backtest Review

Recurring options data/timeout wall (L23/L27/L67) — not code-fixable; needs an engine change (batched catalog.bars + daily-expiry branch)

Iteration History

Verification failed (Layer 4 — QA review): - TENOR MISMATCH — the single feature that defines this hypothesis is absent. The hypothesis is a DAILY (1DTE) structure and states explicitly that daily is 'the ONLY tenor that clears the trade-count floor under the 90-day cap' — that tenor is the sole thing differentiating it from the pending/abandoned WEEKLY options set (bear-call-spread, iron-fly, bull-put-spread, iron-condor). The code runs WEEKLY (roll: 'weekly', dte_target: 7) because the engine has no daily_expiries() branch. Run weekly, this IS a symmetric-strangle sibling of the already-abandoned weekly options family and does not clear the trade-count floor the hypothesis was designed around. The hypothesis's own stated purpose is defeated. - VENUE MISMATCH. Hypothesis names BINANCE_OPTIONS and exists to fill the 0.0% BINANCE_OPTIONS bucket; code runs DERIBIT. Disclosed override (Deribit-only chain discovery, zero BINANCE_OPTIONS catalog data, un-backfillable Binance mirror), but it does NOT populate the intended bucket — it lands in the Deribit options bucket where an iron-condor VRP idea was already abandoned — and fee assumptions differ. - UNMEASURABLE TRADE COUNT. The two proposed fixes are mutually destructive under the engine: ~7.3s/leg load means daily x 90d = ~2,610s (8.7x over the 300s cap) and even weekly x 90d = ~377s is over. Shipped lookback_days=45 is the largest chain that completes → after the IV gate ~3 trades, below any evidence floor. Sandbox: total_trades=16 legs, data_days=4, metrics_reliable=false. Developer states the run 'proves the machinery executes end-to-end; it is not evidence about the edge.' Cannot populate a walk-forward or holdout.

Iteration History

Verification failed (Layer 4 — QA review): - TENOR MISMATCH UNCHANGED (iteration 2). The hypothesis is DAILY (1DTE) and daily is its sole differentiator from the abandoned WEEKLY options family. The engine has no daily_expiries() branch and 14/14 catalog BTC expiries are Fridays; the code still runs weekly. No strategy-code edit can create the daily tenor. Confirmed engine blocker. - VENUE MISMATCH UNCHANGED. Hypothesis names BINANCE_OPTIONS (to fill the 0.0% bucket); code runs DERIBIT. Verified a third time — Deribit-only resolver, zero BINANCE_OPTIONS catalog data, un-backfillable Binance mirror. Confirmed data-layer blocker. - TRADE-COUNT FLOOR UNREACHABLE. At ~7.3s/instrument x 4 legs: 75 daily cycles = ~2,178s (7.3x over cap), 30-cycle floor = ~871s (2.9x over), largest completing chain = ~6 cycles → ~3 gated trades. Sandbox: total_trades=16 legs, data_days=4, metrics_reliable=false. The two proposed fixes are mutually destructive. Confirmed engine blocker.

Iteration History

Verification failed (Layer 4 — QA review): - TENOR MISMATCH — UNCHANGED (iteration 3). Hypothesis is DAILY (1DTE), the sole differentiator from the abandoned weekly family and 'the ONLY tenor that clears the trade-count floor.' Engine has no daily branch (14/14 catalog BTC expiries are Fridays); code runs weekly. Confirmed engine blocker, unreachable from strategy code. - VENUE MISMATCH — UNCHANGED. Hypothesis names BINANCE_OPTIONS; code runs DERIBIT. Deribit-only resolver, zero BINANCE_OPTIONS catalog data, un-backfillable mirror. Does not populate the intended bucket. Confirmed data-layer blocker. - TRADE-COUNT FLOOR UNREACHABLE — now GENERALIZED. The open question is closed: the exact bounded runner call catalog.bars(bar_types=[bt], start=..., end=...) costs 7.96s PER INSTRUMENT (fixed per-call overhead against a 36,987-directory catalog, independent of date filter). At ~8s/instrument, 30-cycle floor at 4 legs = ~955s (3.2x over), 75-cycle = ~2,388s (8x), even a 2-leg vertical at the floor = ~478s (1.6x over). No options structure at any leg count/tenor is verifiable today; largest completing chain ~6 cycles. Sandbox: data_days=4, metrics_reliable=false.
Strategy report

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