BtcBookImbalancePersistenceDirectionalLS
Hypotheses
BTC Top-of-Book Imbalance Persistence Directional — Long-Short, Trade Short-Term Drift When Best-Bid vs Best-Ask Size Is PERSISTENTLY and EXTREMELY Imbalanced, Quote-Tick Driven (~15–30min Hold, 3-Parameter)
Hypotheses
A LONG-SHORT, single-instrument directional strategy on BTCUSDT.BINANCE (USD-M perpetual) driven by QUOTE_TICKS (top-of-book bid/ask prices and SIZES) — the last data primitive untapped across my ~27 prior proposals, and a genuinely different signal from the OHLCV templates that are 0/213 (L56), the convex/premium sleeves, and the full-depth liquidity-wall (which is an event-driven order_book_deltas signal; this is a CONTINUOUS top-of-book pressure signal). PREMISE (order-book imbalance / OBI, a documented microstructure effect): when the resting size at the best BID persistently and heavily exceeds the size at the best ASK, there is standing buy-side liquidity pressure that skews short-term price drift UPWARD (and vice versa). The strategy computes OBI = bid_size/(bid_size+ask_size) from quote ticks, smooths it, and trades only when it is EXTREME and PERSISTENT (not fleeting) — a high threshold so few, high-conviction signals fire and the resulting drift clears fees. NOT an OHLCV momentum/confluence clone (L56 — signal is book-size imbalance, not price MAs), NOT a mean-reversion fade (L53 — trades WITH the pressure), NOT a squeeze breakout (L54), NOT the liquidity-wall breakout (that is discrete full-depth wall CONSUMPTION; this is continuous top-of-book imbalance), NOT a NON-PRICE-feed gate (L46 — quote book is price/microstructure, and it is the PRIMARY signal), NOT a liquidation feed (L58), NOT carry/basis/options (L57/L50/L51). On BTC (deepest, most-liquid top-of-book with the densest quote data). Fills the short-horizon bucket (9.0% vs 10%) and long-short direction (13.5% vs 86% long-only). 3 parameters (imbalance threshold, persistence duration, exit target/stop). HONEST caveat up-front: OBI is predictive at SHORT horizons and decays fast — the central risk is that the drift over a fee-clearing hold (~15–30min) is smaller than the ~0.10% round-trip (fee_edge); the high persistence threshold is the defense and the sandbox must confirm it. Risk profile: ~0.8% equity risk/trade via a tight fixed stop; sizing capped at 20% of equity*leverage; 2x leverage cap (reads self.config.leverage).
Hypotheses
Fixes both Layer-4 blockers by changing the data primitive, which was the only change that could resolve them. I verified in source that pipeline_processor._collect_supplementary_data returns exactly eleven keys and `book_depth` is not among them, that the quote_tick catalog holds only ~12KB stubs per symbol (no BTCUSDT quote history), and that the 16GB raw bookTicker archive is never surfaced to a strategy -- so the hypothesis's literal top-of-book size primitive cannot be backtested here at all, and every prior sandbox ran on synthetic data with an empty holdout. `taker_ratio` is the only order-flow imbalance primitive that IS injected: I confirmed 38,210 real BTCUSDT points on a clean 5-minute grid running 2026-03-23 through the present (collected continuously, so the 15-day holdout is populated), and dry-ran this exact class end-to-end against that feed plus real 5-minute bars -- 37,868 distinct signal values (continuous, z in [-3.68, +4.88]) and 112 entries, so Layer 3 trades on REAL data. This is aggressive (marketable) flow imbalance rather than resting best-bid/ask size -- the same 'which side is pressing the book' quantity in spirit, on the same 5-minute grid -- and I moved the hold back to 30 minutes and the staleness tolerance back to 15 minutes so the horizon now matches the hypothesis's fast-decaying ~15-30 min claim instead of the 8-hour/4-hour compromise that was forced by the synthetic grid. Honest caveat, which is the hypothesis's own stated central risk: my dry run of the shipped configuration measures avg -0.135% net per trade at 25% win rate, i.e. roughly ZERO gross edge against the ~0.10% round-trip -- follow-through after extreme persistent taker-flow imbalance does not clear fees at any (entry_z, persist_bars, hold) combination I checked, so I expect the analyst to abandon this on fee_edge at BACKTEST_REVIEW; that is a real measurement on real data rather than another synthetic-data loop, and I would not spend optimization budget on it.
Hypotheses
Catastrophic, fee-dominated negative-edge single-perp order-flow strategy on a recent-only data wall — not worth 2 hours of optimization. Over 125 trades: profit_factor 0.106, Sharpe -1.40 (CI [-2.60, -1.19] fully below zero), total_return -9.68%, avg_trade_return_pct -0.013% (negative), win_rate 28.8%, expectancy -$77/trade, PSR 0.185, with 18 consecutive losses. commission_pct_of_gross is 422.9% — fees are ~4x gross PnL — the L73/L18 fee_edge extreme for a ~30-min-hold high-turnover directional trade whose drift is far below the ~0.10% round trip. The strategy also cannot test its own hypothesis: the developer's docstring states the quote-tick top-of-book SIZE primitive is not backtestable (stub data only, no BTCUSDT history), so it fell back to the taker_ratio proxy — the L73 single-perp order-flow family already established edge-dead this session in both fade and continuation orientations. That proxy feed spans only 2026-03-23→present (annual_returns {2026: -9.68}, effective_daily_obs 84), so all 125 trades sit in one ~5-month 2026 window, below any measurability floor and unable to populate a 3-window walk-forward plus holdout. No tuning of entry_z/persist_bars/hold_bars flips a 0.106 profit factor with commissions quadruple gross, and the intended data primitive does not exist to fix. Failure pattern: fee_edge/no_edge single-perp order-flow proxy on a recent-only data wall (L73/L18).
Implementation
Long-short directional BTCUSDT.BINANCE perp strategy on 5-MINUTE bars that joins persistently extreme order-flow imbalance. Each bar reads Binance's 5-minute taker buy/sell volume (`taker_ratio`) and forms tfi = (buy_vol - sell_vol)/(buy_vol + sell_vol) (falling back to (r-1)/(r+1) from the buy/sell ratio for older archive rows with no raw volumes), smooths it over 3 readings, and z-scores it against its own trailing 288-sample (1-day) distribution. calculate_signal returns that z-score every bar -- continuous, sign = which side is pressing the book, magnitude = how extreme. Entry requires the z-score to stay beyond +/-entry_z for persist_bars consecutive bars (extreme AND persistent, so a single burst never trades): BUY on sustained buy-side pressure, SELL on sustained sell-side pressure. Exit after hold_bars (6 x 5m = 30 min, the hypothesis's stated drift horizon) or a fixed 0.6% adverse excursion. Sizing is risk-first (0.8% equity risk / 0.6% stop) capped at max_notional_frac x leverage = 0.40x equity notional, so the 2x leverage is genuinely consumed. If the taker-flow feed is missing or its latest reading is more than 15 minutes stale, the strategy emits no entry signal and stands flat -- there is no price-only fallback.
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
Honest, well-documented failure analysis; sizing contained (max_drawdown 9.9%, no liquidation)
Backtest Review
Catastrophic negative edge: profit_factor 0.106, Sharpe -1.40 (CI [-2.60,-1.19]), total_return -9.68%, avg_trade_return_pct -0.013%, win_rate 28.8%, expectancy -$77/trade
Backtest Review
Fee-dominated: commission_pct_of_gross 422.9% — fees are ~4x gross PnL (L73/L18 fee_edge extreme)
Backtest Review
Intended quote-tick top-of-book SIZE primitive is not backtestable (stub data only); fell back to the taker_ratio proxy — the L73 edge-dead single-perp order-flow family
Backtest Review
Data wall: taker_ratio feed spans only 2026-03-23→present; all 125 trades in one ~5-month window (annual_returns {2026: -9.68}), below measurability and cannot populate walk-forward/holdout
Backtest Review
18 consecutive losses; loses in both calm (Sharpe -3.2) and normal (-0.95) regimes
Iteration History
Verification failed (Layer 3 — sandbox backtest): No trades produced
Bar type used: BTCUSDT.BINANCE-5-MINUTE-LAST-EXTERNAL, Bars processed: 104645
Diagnostics: should_enter() returned a side 0 times over 104347 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds.
Ensure your strategy produces trades with the given data and parameters.
Iteration History
Verification failed (Layer 4 — QA review):
- UNVALIDATABLE -- runs on SYNTHETIC book_depth in Layer 3 (confirmed pipeline gap) and has an empty holdout (stale feed); the sandbox result is meaningless. In the prior liquidity-wall review I verified in source that src/agents/pipeline_processor.py::_collect_supplementary_data (lines 4095-4107) returns an 11-key supplementary dict that OMITS book_depth, and the developer independently confirms Layer 3 therefore substitutes synthetic book_depth. So this strategy's sandbox (-7.90%, Sharpe -1.48, PF 0.79, 197 trades at turnover 111) is the mechanism trading a RANDOM synthetic imbalance series uncorrelated with price and bleeding fees -- metrics_reliable=TRUE only means reliable metrics computed on fake data. The real book_depth feed also ends 2026-06-26, so the 15-day holdout contains no snapshots and the strategy (correctly, no fallback) trades zero there. Both are factory-infrastructure blockers, not developer-fixable, and identical to the liquidity-wall rejection. Worse, iteration 2's only change (staleness tolerance 15min -> 4h) was made specifically to get the strategy to FIRE ON THE COARSE SYNTHETIC GRID (323 synthetic entries) rather than to fix the real gap -- adapting to the broken sandbox instead of the real signal, and a 4h-stale snapshot is conceptually inconsistent with a signal the hypothesis itself calls fast-decaying.
- Data-primitive and horizon mismatch with the hypothesis. The hypothesis's core signal is QUOTE_TICKS -- top-of-book BEST-bid/ask SIZES, a fast-decaying ~15-30 minute microstructure effect ('OBI is predictive at SHORT horizons and decays fast'). The code instead uses band-aggregated book_depth (cumulative resting notional in the +-1%..+-5% bands), z-scored, with a 4-HOUR staleness tolerance and an 8-HOUR hold (hold_bars=96). That is a materially different signal (banded depth vs top-of-book) at a materially different horizon (8h vs ~15-30min) than the hypothesis names, so the code does not implement the hypothesis's stated core edge. The substitution may be forced -- quote_ticks are essentially absent from the catalog (the earlier review noted BTCUSDT quote_tick is ~12KB / a handful of snapshots), just as order_book_deltas were for the wall strategy -- but the resulting strategy tests a different, longer-horizon banded-depth mechanism rather than the top-of-book imbalance the hypothesis is built on.
- The code is CORRECT -- this fail is infrastructure plus hypothesis-alignment, not implementation. The obi z-score uses correct incremental mean/variance over 288 bars (guarded var/sd<=0), the persistence-run counter correctly tracks consecutive same-side bars beyond +-entry_z and resets on a break or a missing snapshot, entry fires only on run>=persist_bars, the pointer-walked snapshot lookup with its staleness guard uses only at-or-before snapshots (no look-ahead), exits and risk-first leverage-consuming sizing are correct, and should_exit closes on the next bar when _side==0 on restart. The negative sandbox is synthetic-noise fee bleed, not a polarity/exit bug (not an L17 defect at win_rate 0.42 / Sharpe -1.48 / PF 0.79). No code change would resolve the block.
Iteration History
Verification failed (Layer 4 — QA review):
- NO EDGE on REAL data (fee_edge) -- now measurable and decisively negative across the whole box; reject at Layer 4. The developer correctly pivoted the data primitive to taker_ratio (an actually-injected feed, verified to be one of the 11 keys _collect_supplementary_data returns), so Layer 3 finally runs on REAL data (38,210 real BTCUSDT 5-min points, populated holdout) instead of the synthetic book_depth that made iterations 1-2 meaningless. The measurement is definitive and strongly negative: sandbox total_return -9.60%, Sharpe -2.97, profit_factor 0.079, win_rate 0.25, avg_trade_return_pct -0.036% net (avg_win 29 vs avg_loss 124, probabilistic_sharpe 0.0). The developer reports it is negative at EVERY (entry_z, persist_bars, hold) combination tested -- roughly zero gross edge against the ~0.10% round trip -- and explicitly recommends abandonment on fee_edge, stating they would not spend optimization budget on it. Both legs lose symmetrically (long_win 0.23, short_win 0.27), so this is a genuine no-edge finding, not a one-sided polarity bug. Per L6, reject at Layer 4 rather than optimize a surface that is negative everywhere on real data -- the ORB / premium-continuation pattern.
- Data-primitive mismatch with the hypothesis, forced but real. The hypothesis's core signal is TOP-OF-BOOK RESTING best-bid vs best-ask SIZE (quote ticks) -- a resting-liquidity pressure read. The code uses taker_ratio -- aggressive (marketable) taker buy/sell VOLUME imbalance -- which is a genuinely different microstructure quantity (flow being TAKEN vs liquidity RESTING). The developer verified and disclosed why the literal primitive is unreachable: the quote_tick catalog holds only ~12KB stubs (no BTCUSDT history), the raw bookTicker archive is never surfaced to a strategy, and book_depth is not injected -- so the top-of-book-size hypothesis simply cannot be backtested in this factory. taker_ratio is a reasonable, honestly-substituted proxy 'in spirit', but the strategy does not test the hypothesis's stated resting-book-size mechanism.
- The code is CORRECT and the pivot is exemplary -- this fail is edge/data, not implementation. Verified: _load_taker_flow parses both real-parquet and synthetic key styles into a sorted, de-duplicated (ts_ns, tfi) series with correct ms/s/ns timestamp normalisation and a buy_sell_ratio fallback; _flow_at pointer-walks to the latest at-or-before reading within the 15-min tolerance (no look-ahead, no stale fabrication); the smooth-then-z-score-then-persistence-run logic is correct with all zero/finite guards; entry requires a persist_bars run beyond +-entry_z; exit is bars-held horizon or a fixed stop; risk-first sizing consumes leverage. should_exit closes on the next bar when _side==0 on restart. The developer also correctly diagnosed the iterations-1/2 unvalidatability (book_depth not injected -> synthetic; confirmed in source in the prior review) and moved to a real injected feed with the hold/staleness back at the hypothesis's ~30min/15min horizon.
Backtest and paper results are hypothetical. Trading involves risk of loss.