# PRE-REGISTRATION — Does relative-volume selection rescue the opening-range breakout on futures? **Frozen: 2026-08-25 19:30 MDT, BEFORE any result was computed.** Author: Desk Read research loop. Data: `/fp-data` (synced through 2026-08-25 23:59Z). Motivating library: `/fp-library/asset-selection/` (built 2026-08-25). --- ## 1. Why this test, and why now The asset-selection sweep produced one headline finding that every one of its seven briefs converged on independently: **selection dominates entry.** - Zarattini, Barbon & Aziz (2024) run an identical 5-minute opening-range breakout on the whole eligible US stock universe and get **Sharpe 0.48** — worse than buy-and-hold. They run the *same entry rule* on only the top-20 names by opening-bar relative volume and get **Sharpe 2.81, alpha 35.8 %, beta 0.00**. Per-trade PnL rises **monotonically** with the RVOL bin (−0.02R below 1× → +0.38R above 30×). Library grade **B** (`technical/scanner-criteria-and-ta-evidence.md` §3.1, §4.1). - Against that, this desk has already **refuted ORB on NQ/MNQ unconditionally**: Mesfin (2026) finds every OHLCV opening-range variant fails after 2-point friction on MNQ 2022–2024 (best t = 1.50, driven by a single strong year), and the desk's own practitioner-noise pre-reg marks ORB `refuted-adjacent`. **These two results are not in conflict — they test different things.** Mesfin tested the *unconditional* rule. Zarattini's claim is that the unconditional rule is *supposed* to be break-even, and that all the edge lives in the selection layer. Nobody has tested the futures analogue: **does RVOL conditioning rescue ORB on NQ?** This is the same logical structure as the study I actually wanted to run — whether dealer-gamma conditioning rescues intraday momentum on NQ (`00-taxonomy.md` §7 Q2) — but that one is **not testable today**: the GEX archive is forward-only and holds 23 trading days (2026-07-26 → 2026-08-24), which would leave ~10 days per gamma bucket. Deferred until n ≈ 200 sessions (≈ 2027-06). This RVOL test uses 8 instruments × 17 years instead. --- ## 2. Hypothesis **H1.** On NQ futures, opening-range-breakout trades conditioned on **elevated time-of-day-normalized relative volume in the opening range** have positive expectancy net of realistic friction, where the unconditional rule does not. **H0.** RVOL conditioning adds nothing: net expectancy in the top RVOL bucket is indistinguishable from zero, and/or shows no monotone ordering across buckets. --- ## 3. Data | Item | Spec | |---|---| | Source | `glbx//1m/.csv`, Databento OHLCV-1m (`ts_event,rtype,publisher_id,instrument_id,open,high,low,close,volume,symbol`) | | Primary instrument | **NQ** | | Replication set | ES, RTY, YM, CL, GC, ZN, 6E (7 instruments) | | Period | 2010-01-01 → 2026-08-25 (all available) | | Session | RTH 09:30–16:00 **ET**, DST-correct via `zoneinfo America/New_York` (never a fixed UTC offset) | | Contract selection | Per date, use the symbol with the most RTH bars (`.c.1` on quad-witching dates, `.c.0` otherwise). Verified: 2026-03-20 and 2026-06-18 have 390 RTH bars under `.c.1` and 29 under `.c.0`. **Never mix both symbols within one session.** | | Excluded | Sessions with < 300 RTH 1-minute bars (half-days, outages); sessions lacking a complete 09:30–09:34 opening range; the first 20 sessions of each instrument (RVOL baseline warm-up) | --- ## 4. Signal definitions (frozen) - **Opening range (OR)**: the five 1-minute bars 09:30–09:34 ET inclusive. `OR_high = max(high)`, `OR_low = min(low)`, `OR_vol = Σ volume`. - **RVOL** (time-of-day normalized — raw volume is explicitly forbidden per `statistical/ml-microstructure-selection.md` §6.1): `RVOL_d = OR_vol_d / median(OR_vol over the prior 20 sessions)`. Strictly backward-looking; no same-day or future information. - **Buckets**: quintiles of the in-sample RVOL distribution **computed per instrument on an expanding basis** (quintile edges from sessions strictly before d), so bucket assignment is never look-ahead. Q1 = lowest RVOL, Q5 = highest. ## 5. Trade rules (frozen) Direction = the **first** OR side broken after 09:35. Long if OR_high breaks first, short if OR_low. One position per session, one contract, no pyramiding, no overnight hold. - **Entry A (Zarattini/naive)**: fill at the OR level on the touch. - **Entry B (desk confirm rule — the shipped doctrine)**: require a **5-minute close** beyond the OR level, then fill at the **next 1-minute bar's open**. This is the desk's `nq-confirm-entry-rule`, SHIPPED 2026-07-27; Entry B is the **primary**. - **Stop**: opposite side of the OR range. - **Exit**: stop, or the 15:59 ET bar close, whichever comes first. - **Trigger window**: breaks only count 09:35–15:00 ET (no entries in the last hour). - **Friction**: base case **0.5 points round-trip** on NQ (MBP-10 fill audit 2026-07-26 measured ~0.2 pt slippage at 1–2 lots, plus ~0.25 pt commission). Sensitivity reported at 0.25 / 1.0 / 2.0 points; 2.0 is Mesfin's MNQ assumption. Per-instrument friction scaled to each contract's tick. - **Units**: index points per trade (NQ point = $20). Report points, not dollars. ## 6. Primary test — ONE pre-specified cell > **NQ · 5-minute OR · Entry B (confirm) · top RVOL quintile (Q5) · 0.5 pt friction.** > Statistic: mean net points per trade and its Newey-West t-statistic. > **Pass threshold: t > 3.0** (Harvey–Liu–Zhu multiple-testing standard, library grade A). Everything else below is secondary and explicitly discounted. ## 7. Secondary tests (reported, not confirmatory) 1. **Monotonicity** across Q1→Q5 — Spearman ρ of bucket rank vs mean net points. This is the *distinctive* Zarattini claim and is harder to fit than any single threshold. 2. Entry A vs Entry B. 3. The 7 replication instruments. 4. Friction sensitivity 0.25 / 1.0 / 2.0. 5. Year-by-year net for the primary cell — Mesfin's failure mode was one strong year masking flat ones, so a result driven by a single year is treated as failed regardless of pooled t. ## 8. Falsification criteria (decided in advance) H1 is **CONFIRMED** only if **all three** hold: 1. Primary cell t > 3.0 with positive mean net; 2. Monotonicity ρ > 0 across quintiles; 3. Replication in **≥ 4 of 7** other instruments at t > 2.0 in their own Q5. If (1) passes but (2) or (3) fails → **contested**, forward-only shadow grading before any capital. If (1) fails → **refuted**, recorded as such, and ORB stays refuted on this desk. A positive result in *any other* cell while the primary fails is **exploratory only** and must not be reported as a finding. ## 9. Multiple-testing accounting Trial count is fixed in advance: 8 instruments × 5 buckets × 2 entries × 4 frictions = **320 cells**. The primary is 1 pre-specified cell. Deflated Sharpe / PBO reasoning per `statistical/classical-econometric-selection.md` §3.25 — with 320 trials, an in-sample Sharpe near 1 is the *expected* maximum under the null and means nothing on its own. ## 10. Known limitations, stated before results - One entry per session; no intraday re-entry after a stop. - Stop-and-target fills are assumed available at the modeled price within the bar; 1-minute OHLC cannot resolve intrabar path, so **stop-then-target sequencing within a single bar is ambiguous**. Convention: if a bar's range spans both stop and exit, assume **stop first** (conservative). - No borrow/financing; futures, so not applicable. - RVOL uses a 20-session median; alternative windows are not tested (avoids a snooping dimension). - Results are **hypotheses**, never validated edge, per house rule. --- ## 11. AMENDMENT — 2026-08-25 19:45 MDT, still BEFORE any result was computed Mapping the existing desk harness (`fp-terminal/lib/scoreBrief.ts`, `fp-backtest/*.py`, `docs/close-read-study.md`) corrected four things in the spec above. Recorded as an amendment rather than a silent edit. **No backtest had been run at this point.** 1. **Friction was wrong.** §5 said 0.5 pt base for NQ. The desk's measured constant is **`COST_PTS = 1.0`** round trip (`lib/closeRead.ts:60`, MBP-10 fill audit 2026-07-26: 0.75–1.00 pt spread + ~0.17 pt slip at 1–2 lots). Per-symbol desk values: **ES 0.5, YM 2.0, RTY 0.3, NQ 1.0** (`docs/close-read-study.md`). **Base case is now 1.0 pt on NQ**; sensitivity 0.5 / 1.0 / 2.0. This makes the test strictly harder than originally written. 2. **Contract roll was wrong.** §3 assumed `.c.0` for all instruments. `manifest.json` is explicit: NQ/ES/RTY/YM/6E = `.c.0` (calendar roll), **ZN/CL/GC = `.v.0` (volume roll)**. 3. **RTH completeness threshold** aligned to the desk's existing filter: **≥ 330 cash bars** (not 300), matching `close_dataset.py`. 4. **Execution model** is not mine to invent — it must reuse `walkPlan` (`lib/scoreBrief.ts:161`) exactly, since that is what every shipped desk result is graded on: - 5-minute grid closes are bars with minute-of-open `mo >= 4 and mo % 5 == 4` (09:34, 09:39, …); - confirmed fill = **next 1-minute bar's open**, with stop/target distances re-projected from the actual fill; - **stop slippage = max(0.5 pt, 0.25 × the bar's excursion beyond the stop)**; - a target is filled only if the bar trades **through it by 0.25**; - a bar spanning both stop and target books the **stop first**; - $20/pt, whole points rounded before dollar conversion. **Additional pre-specified reporting**, to match the desk's own promotion bar (`docs/close-read-study.md`): IS/OOS split at **2020**, per-year sign consistency, and n ≥ 30. The confirmatory threshold stays **t > 3.0** (Harvey–Liu–Zhu, justified by 320 pre-counted cells); the desk's shipping bar (|t| ≥ 2 + OOS sign consistency + n ≥ 30 + positive after cost) is reported alongside but is *not* what decides H1 here. **Prior-art check before running** — `docs/close-read-study.md` already REFUTED "first-30m → last-30m momentum (Gao et al.)" on this desk. That is a *different* rule (a time-of-day momentum bet) from the one under test here (a range-break entry conditioned on opening relative volume). Confirmed this exact hypothesis is not among the desk's existing refutations before proceeding.