Skip to content

View original

BtcPriceOpenInterestDivergenceReversalLS

Hypotheses

BTC Price–Open-Interest Divergence Reversal — Long-Short, Single-Instrument: Fade Price Moves That Committed Leverage REFUSES to Confirm (Rally on Falling OI = Short-Covering Exhaustion → Short; Selloff on Falling OI = Long-Liquidation Washout → Long), Stand Aside When Price and OI Agree (BINANCE BTCUSDT USD-M, DAILY Bars, 2-Parameter)

Hypotheses

A LONG-SHORT, SINGLE-INSTRUMENT, single-venue swing on BTCUSDT.BINANCE USD-M perpetual whose signal is the RELATIONSHIP between price change and OPEN-INTEREST change — a positioning/leverage tell, not a price-shape pattern and not an intraday flow-extreme fade. Open interest measures the stock of committed leveraged capital. A price move that is NOT confirmed by a matching build in open interest lacks fresh committed money behind it and statistically reverts; a move confirmed by rising OI has conviction and is left alone. The strategy classifies each daily bar into a price×OI quadrant using rolling multi-day changes and trades ONLY the two DIVERGENCE quadrants, contrarian: (1) price UP while OI is FALLING — a rally driven by short-covering / position closing rather than new longs, unsustainable → go SHORT; (2) price DOWN while OI is FALLING — a selloff driven by long-liquidation / deleveraging that exhausts forced sellers → go LONG (washout reversal). When price and OI move TOGETHER (both up = new longs with conviction; both down is already covered above) the strategy STANDS ASIDE and does not fight confirmed positioning. This is deliberately the OPPOSITE construction of a trend/OI-confirmation breakout (which trades price–OI AGREEMENT and is a known dead class here): the edge is specifically the divergence. It is NOT a taker-flow or mark-index-premium fade (different feed: stock of open interest vs per-bar aggressor flow / basis), NOT a cross-venue or basket construction, NOT a positioning L/S-account ratio divergence, and NOT an OHLCV-only mean-reversion (OI is the trigger; price change is only the sign). DAILY bars with 2-7 day holds mean round-trip fees (~0.10%) are a rounding error against multi-percent reversion targets, structurally sidestepping the fee_edge graveyard that kills fast strategies. Only 2 free parameters (OI-change lookback in days, divergence z-threshold) plus a fixed ATR stop and time stop, to stay clear of the overfit graveyard. All per-bar work is O(1) via incremental rolling change/z-score — no full-series rescans, sorts, or min()/max() over history — to avoid the smoke-test timeout.

Hypotheses

Implements the hypothesis's construction directly: rolling multi-day price and OI changes, trade ONLY the two falling-OI divergence quadrants contrarian, stand aside when price and OI agree, daily bars with 2-7 day holds, and exactly two free parameters (oi_lookback_days, entry_z) plus a fixed ATR stop and time stop. The stand-aside rule is expressed inside the continuous signal as min(oi_z, 0), so the returned value keeps its natural z units and grades conviction by |oi_z| in the traded quadrants instead of hiding the logic behind a boolean gate. Two data decisions I verified against the pipeline rather than assumed: (1) open interest is merged from BOTH `metrics` (Binance Vision 5-minute open_interest, 329k rows back to 2020-09) and `open_interest` (the open_interest_hist API series, which covers the recent months where the Vision metrics files lag) - these are two publication channels of the same Binance quantity, both returned by `_collect_supplementary_data()`, so the Layer-3 sandbox and the full backtest see identical real data; merging lifts daily coverage in the sandbox year from 187 to 221 of 365 days. (2) I use CONTRACT open interest, not open-interest value, because value = OI x price would make the divergence test self-referential. Field names are read with both the documented spelling (sumOpenInterest/timestamp) and the actual loaded parquet columns (open_interest/timestamp_ms). Measured offline on the real catalog with the exact incremental semantics implemented here and 0.10% round-trip taker cost deducted: full history 124 trades, +0.89% average net per trade, profit factor 1.49, 57% win rate; sandbox window 21 trades - so Layer 3 clears its >=1-trade gate with margin and per-trade capture is ~9x the round-trip fee. Neighbouring parameter cells keep the same sign (entry_z 0.4 -> PF 1.41, z_window 40 -> 1.12, 90 -> 1.31, oi_lookback 7 -> 1.26), a shallow plateau rather than a spike. One caveat for the Analyst: the binding constraint on this idea is DATA, not logic - Binance OI history is only collected forward, so the merged series covers 1,385 of 2,416 daily bars and the full-history trade count lands near the ~100-trade measurability bar rather than far above it; the strategy correctly stands flat on the uncovered days instead of inventing a proxy. Venue is BINANCE USD-M (MARGIN) because the book is long and short; leverage stays 1.0 since sizing is ATR-risk based.

Hypotheses

coding_stuck_3_timeouts

Implementation

BTCUSDT.BINANCE USD-M perpetual, DAILY bars, long-short single-instrument reversal driven by price/open-interest DIVERGENCE. Each bar the 5-day change in contract open interest is z-scored against a rolling 60-sample window (incremental running sum/sum-of-squares) and combined with the sign of the 5-day price change: signal = sign(price change) x min(oi_z, 0). The signal is therefore positive when price fell on falling OI (long-liquidation washout -> LONG), negative when price rose on falling OI (short-covering rally -> SHORT), and exactly 0 whenever OI is rising, i.e. price and positioning agree and the strategy stands aside. Entry is a single threshold on |signal| >= entry_z. Exits are a 2 x ATR(14) stop measured at entry and evaluated on the bar close, plus a 4-calendar-day time stop anchored on the position's own open timestamp - no third free parameter. Open interest is read from the merged `metrics` + `open_interest` supplementary channels (contract OI in coin units, never OI value, which price would mechanically move); a bar whose newest OI print is older than 36h yields signal 0 and no trade, with no price-only fallback. Sizing risks 1% of equity across the ATR stop, capped at 50% gross notional; leverage 1.0. Per bar the work is one O(log n) searchsorted plus fixed-size deque arithmetic.

Outcome Summary

BtcPriceOpenInterestDivergenceRevers-c846c4103c

Outcome Summary

A sound edge is worthless if the code can't be produced within the coding time budget.

Outcome Summary

Abandoned at the coding stage after three consecutive developer timeouts (coding_stuck_3_timeouts) across 2 iterations; it never reached verification or backtesting.

Outcome Summary

A long-short daily swing on BTCUSDT USD-M perpetual that fades price moves unconfirmed by open interest — shorting rallies on falling OI, buying selloffs on falling OI, standing aside when price and OI agree.

Outcome Summary

The pipeline never produced a backtest, optimization, or analyst verdict — all stage reports are empty. The only figures are the author's own offline docstring claims (124 trades, +0.89%/trade net, PF 1.49, 57% win rate), never verified by the factory.

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.