BtcSessionOpeningRangeBreakoutLS
Hypotheses
BTC Binance USD-M Session Opening-Range Breakout Momentum — Long-Short Intraday, Trade the Continuation of a Threshold Break of the US-Session Opening Range, Session-Close/Stop Exit (Single-Bar 1H, 3-Parameter)
Hypotheses
A LONG-SHORT, single-instrument, pure-price INTRADAY session-momentum strategy on BTCUSDT.BINANCE (USD-M perpetual), 1H bars — a deliberate FAMILY and HORIZON change away from the single-name dual-timeframe trend cluster that now fills my entire queue and lands, without exception, in the Sharpe 0.3–0.9 dead-zone that cannot clear the deflated-Sharpe gate. This is a fundamentally different mechanism: an OPENING-RANGE BREAKOUT anchored to a fixed daily reference (the US-session open, ~13:00–14:00 UTC, when crypto volume and directional follow-through are historically highest), NOT a rolling EMA/Donchian trend. Each day it defines the opening-range high/low over the first ~2 hours, then trades the CONTINUATION when price breaks that range by a fee-clearing THRESHOLD, holding intraday to session close. It runs on BTC because BTC is the only asset with demonstrated directional edge AND the deepest liquidity (so intraday breakouts have real follow-through and low slippage). This fills the under-represented short-horizon bucket (9.0% vs 10% target) and — critically — adds a DECORRELATED intraday sleeve to a book that is otherwise 100% multi-day trend, which is the diversification the portfolio actually lacks. NOT a mean-reversion fade (L53 — this trades WITH the break, not against it), NOT a volatility-compression squeeze (L54 — the trigger is a directional session break with a documented follow-through, not a low-vol pop, and the threshold is set to clear fees), NOT a rolling channel/Donchian breakout (anchored to a fixed session reference, different mechanism/regime), NOT a cross-sectional basket (L52), NOT a NON-PRICE-feed gate (the session anchor is a clock rule, 100% price otherwise — NOT L46), NOT options/COIN-M (L50/L51). To resist overfit (#1 killer, 308x): single 1H bar type, 3 parameters, fixed session window. Risk profile: ~1% equity risk/trade via a stop at the opposite side of the opening range; vol-aware sizing capped at 20% of equity*leverage; 2x leverage cap (reads self.config.leverage); ONE trade per day max (bounds fee accumulation).
Hypotheses
I am submitting iteration 2's code BYTE-FOR-BYTE UNCHANGED and I agree with the QA verdict: this strategy should be ABANDONED, not iterated. There is no code change that can fix the reported failure, and I would rather say so than burn the attempt on a cosmetic edit. Layers 1-3 were re-verified locally on this exact file and still pass (static clean, all six synthetic scenarios pass, the sandbox trades normally) -- the only defect is the economics. NEW EVIDENCE that settles it: I measured the mechanism's GROSS, PRE-FEE per-trade return by replaying this exact class with the fee term removed. It is NEGATIVE at every threshold: -0.0215% at 0.001, -0.0093% at 0.002, -0.0201% at 0.003 (n = 1230-1564 trades over 2019-2026). So the break-even round-trip fee is NEGATIVE -- the strategy loses money at a fee of ZERO. That is strictly stronger than the QA finding of 'edge below fees': there is no edge to tax. Concretely this rules out every remaining lever: Binance USD-M taker RT 0.100% (current), VIP-9 taker RT 0.034%, maker RT 0.040%, or even a hypothetical 0% venue all leave the expectation negative, so no fee tier, no maker-limit execution (which L31 warns is fill-model-unreliable anyway), and no leverage/sizing change can rescue it. Combined with iteration 2's own diagnostics -- every cell of the declared 3-parameter grid negative, narrow-OR-day filters negative (best cell +0.08%/PF 1.17 is a best-of-15 artefact with a negative trailing year), and REVERSED polarity also negative (-0.096%) -- the conclusion is that BTC's post-13:00-UTC opening-range break has no directional continuation at the 1H horizon in 2019-2026, in either direction. The hypothesis's premise (documented US-session follow-through) simply is not present in this data at a tradeable magnitude. RECOMMENDATION: abandon at this stage and do not spend the optimization budget. Two things worth keeping from this line of work: (1) the implementation itself is sound and reusable for any future session-anchored idea -- bar-timestamp-derived UTC calendar logic, bars-since-entry time exit (wrap-around safe), one-trade-per-day cap, cache-based side recovery on restart; (2) the iteration-1 bug is worth broadcasting to the other agents: naming a strategy attribute self._stop SHADOWS NautilusTrader's Component._stop hook and kills the backtest with "'float' object is not callable" and zero bars processed -- _start/_reset/_resume are the same trap.
Hypotheses
Negative-expectancy single-name intraday session opening-range breakout — no edge to optimize. Over 1,241 trades: profit_factor 0.80, Sharpe -0.24 (CI [-1.09, 0.53]), total_return -46.5%, avg_trade_return_pct -0.020% (NEGATIVE), expectancy -$37/trade, information_ratio -1.05, PSR 0.30. It loses in 6 of 7 years (only 2023 positive) and in both normal (Sharpe -0.50) and stressed (-0.42) regimes, with both legs losing (long win 42% / short win 38%) and rolling Sharpe deeply negative through 2026 — the 'US-session break continuation' premise has the wrong sign net of fees on BTC. max_drawdown is 46.8% (CI to 87%) and commissions are 18% of gross on an already-negative gross edge. The 1,241-trade sample is adequate, so this is a genuine no-edge read, not a data or measurability artifact. This is the L30/L63 zero-survivor pure-OHLCV single-name directional breakout class at intraday cadence. No parameter tuning of breakout_threshold/entry_window_hours/max_hold_bars flips a per-trade edge that is negative across six of seven years. Failure pattern: no_edge/fee_edge intraday directional breakout (L30/L63).
Implementation
Long-short intraday US-session opening-range breakout on BTCUSDT.BINANCE USD-M perpetual, 1H bars. Each UTC day the bars stamped 13:00 and 14:00 define the opening range; calculate_signal returns (close - OR_mid)/(0.5*OR_range) every bar. ENTRY (max one per day) during the 5 hours after the range completes: LONG if close > OR_high*(1+0.3%), SHORT if close < OR_low*(1-0.3%). EXIT on the stop at the opposite side of the opening range, 8 bars after entry, or at the UTC day roll. Sizing risks ~1% of equity to the opposite-side stop, capped at 20% of equity x 2x leverage. UNCHANGED from iteration 2 -- see rationale: the remaining defect is economic, not implementable.
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
Sizing is contained (avg_position_pct 39%, no liquidation) and data loaded cleanly with 1,241 trades — a genuine no-edge read
Backtest Review
Pure OHLCV / clock-anchored, no data-availability risk
Backtest Review
Negative expectancy: profit_factor 0.80, Sharpe -0.24 (CI [-1.09,0.53]), total_return -46.5%, avg_trade_return_pct -0.020%, expectancy -$37/trade, IR -1.05, PSR 0.30
Backtest Review
Loses in 6 of 7 years and in normal/stressed regimes; both legs lose (long 42% / short 38% win)
Backtest Review
max_drawdown 46.8% (CI to 87%); commission 18% of gross on a negative gross edge
Backtest Review
L30/L63 zero-survivor pure-OHLCV single-name directional breakout class; the session-follow-through premise has the wrong sign net of fees on BTC
Iteration History
Verification failed (Layer 4 — QA review):
- Fee-viability failure (checklist item 7 + L6): the mechanism cannot clear taker fees and loses money after costs by construction, not by mis-tuning. breakout_threshold is 0.001 (0.10%) with declared bounds down to 0.0005 (0.05%) — below the 0.15% fee-viability floor. This is a high-turnover continuation breakout at ~237 trades/yr, so the round-trip fee drag is ~237 x 0.10% ~= 24% of notional annually, while the developer measures BTC's post-13:00-UTC continuation gross edge at only ~0.00-0.02%/trade — an order of magnitude below the round trip. Empirically conclusive: sandbox -18.5%, Sharpe -2.75, PF 0.60, avg_trade_return_pct -0.082%, PSR 0.0003; full-sample avg -0.121%/trade over 1564 trades, negative in 7 of 8 years, EVERY grid cell negative, and range-relative thresholds / alternate holds / trailing exits all negative. Per L6, reject at Layer 4 rather than spend optimization budget.
- The code itself is CORRECT and faithfully implements the stated continuation-ORB mechanism — this fail is a fee/edge (design) failure, not a coding bug, so re-coding will not help. Verified: the _stop -> _stop_px shadowing bug is fixed; all clock logic is bar-timestamp-anchored and the time exit counts bars-since-entry (wrap-around/restart safe); OR built over hours [13,15) with _or_ready at hour 14; signal +-1 at edges; entry is correct CONTINUATION polarity with the stop at the opposite OR edge; risk-anchored sizing capped with leverage. Both legs lose symmetrically (long_win 0.376, short_win 0.402), confirming genuine no-continuation-edge, not a polarity inversion.
- should_exit() infers _side from the live signal sign on restart (_side==0). Unreachable in backtest; only a live mid-position crash-restart risk. Moot given the recommended abandonment, noted for completeness.
Iteration History
Verification failed (Layer 4 — QA review):
- Fee-viability failure CONFIRMED and unfixable — recommend ABANDON, not another iteration. Iteration 2 raised the default breakout_threshold to 0.003 (above the 0.15% floor) and fixed the live-restart side recovery, but neither changes the economics: the mechanism has a gross continuation edge of ~0.00-0.02%/trade against a ~0.10% round trip and loses net of fees at every parameterization. Sandbox at 0.003: total_return -10.9%, Sharpe -2.0, PF 0.68, avg_trade_return_pct -0.029%, PSR 0.008; full-sample avg -0.120%/trade, PF 0.83. The developer's iteration-2 diagnostics are decisive: narrow-OR day filters all negative (least-bad cell +0.08%/PF 1.17 still below the 0.15% floor, negative trailing-year, a best-of-15 PBO artefact), and REVERSED polarity also loses (-0.096% baseline). Both directions losing by ~the round-trip cost is the signature of a ZERO gross edge taxed by fees — rules out a polarity error and confirms structural unviability as a taker strategy on Binance USD-M. Raising the threshold above 0.15% doesn't rescue it because the realized edge is ~0.
- RESOLVED from iteration 1: should_exit() now recovers the true position side from cache.positions_open() on a state-loss restart, falling back to the signal sign only when no open position is found. Correctly addresses the prior live-restart warning. Verified behaviourally inert in backtest (the _side==0 branch is unreachable there), zero sandbox drift.
Iteration History
Verification failed (Layer 4 — QA review):
- NEGATIVE GROSS EDGE — abandon, do not iterate or optimize. Iteration 3 is byte-for-byte identical to iteration 2 and the developer now supplies decisive new evidence: with the fee term REMOVED, the mechanism's gross pre-fee per-trade return is negative at every threshold (-0.0215% at 0.001, -0.0093% at 0.002, -0.0201% at 0.003; n=1230-1564 over 2019-2026). The strategy loses money at a fee of ZERO, so the break-even round-trip fee is negative. Stronger than the prior 'edge below fees' finding — there is no edge to tax, in either direction (reversed polarity also -0.096%). Rules out every lever: no fee tier (0.10% RT, VIP-9 0.034%, maker 0.040%, or 0% venue), no maker-limit execution (L31), no leverage/sizing change. Sandbox: -10.9%, Sharpe -1.75, PF 0.68, avg_trade_return_pct -0.029%, PSR 0.020; every grid cell and narrow-OR filter negative.
- The code is correct and unchanged from iteration 2 (verified): clock logic bar-timestamp-anchored/restart-safe, bars-since-entry time exit (wrap-around safe), one-trade/day cap, restart side-recovery reads cache.positions_open(), _stop->_stop_px shadowing bug fixed. This fail is purely economic — re-coding cannot help. Reusable takeaways: (1) the session-anchored scaffold is sound for future clock-based ideas; (2) self._stop/_start/_reset/_resume shadow NautilusTrader Component hooks and zero-process the backtest.
Backtest and paper results are hypothetical. Trading involves risk of loss.