Module 13 Companion — Sessions, Auctions & Funding Clocks — Strategy Lab
Part III · Intraday Design, Alpha & Playbooks · Companion to Module 13 — Sessions, Auctions & Funding Clocks Status: Draft v0.2 · Scope: commodity ETFs/ETPs + BTC/ETH spot & linear perps · Horizon: M1/M5 primary, M15 where appropriate, same-session flat Prerequisites: M7, M13, M5, M22, M23
Overview
The core module established our market clocks: regular trading hours (RTH) segmentation, synthetic UTC crypto sessions, and funding settlement mechanics. This companion translates those clocks into three rigorous intraday trading controls.
A session filter does not predict market direction. It acts as an operational bouncer, deciding whether a specific bar is cheap enough and tall enough to carry a directional signal.
We evaluate three controlled strategies. S1 serves as the foundational implementation. S2 and S3 inherit S1’s execution engine, modifying only the calendar and funding rules.
| Strategy Card | Audit Question | Target Asset & Clock | Core Mechanism |
|---|---|---|---|
| S1: RTH Segment Atlas Gate | Does filtering out the midday trough and auction freezes improve net P&L after costs? | Commodity ETP RTH (GLD / PDBC, 09:30–16:00 ET) | Hourly atlas filter + Spread-to-ATR gate + Auction freeze stand-down. |
| S2: UTC Session Filter & Sunday Trap | Does restricting crypto trading to Europe/US overlaps (and isolating Sunday 23:00 UTC) outperform 24/7 trading? | BTC/ETH Spot & Perps (UTC Synthetic 00:00–23:50) | UTC session filter + Sunday re-entry sleeve + Funding buffer. |
| S3: Funding-Clock Stand-Down | Does standing down during funding settlements preserve net P&L compared to paying periodic holding rent? | BTC/ETH Linear Perps (Hourly vs. 8-Hour Venues) | Settlement-proximity stand-down (±15 min) vs. full funding booking. |
💡 Analogy (The Lens Aperture): Think of S1, S2, and S3 as adjusting the aperture of an industrial camera. You do not alter the scene (the directional indicator). You only open the shutter when lighting is optimal and lens distortion (spread/friction) is minimal. If the resulting photo is not sharper after deducting the light you blocked (lost opportunity), you discard the filter.
📌 Convention: All strategies operate strictly on OHLCV + spread data. We use zero order-book, level-2 tick, or queue-position data. Execution is bar-based: signals on the close of bar
tfill at the open of bart+1with full spread deducted. Ambiguous intra-bar touches resolve adversely (stop-first). All trades force-flatten before the session boundary.
How It Works
Three specialized filters feed a single, unified execution and accounting pipeline.
S1: The RTH Bouncer (Commodity ETPs)
S1 calculates an hourly liquidity atlas across the NYSE trading day. It evaluates two real-time hurdles:
- Spread-to-ATR Ratio:
Spread / ATR <= 0.15(Friction consumes <= 15% of the average bar range). - Cost-to-Target Ratio:
(Spread + Fees) / Target <= 0.10(Friction consumes <= 10% of expected profit).
Bars occurring during the 15:50–16:00 ET closing auction freeze are automatically blocked StockTitan — opening & closing auctions. Only surviving bars are eligible to evaluate trading signals.
S2: The UTC Session Bouncer (Crypto Spot & Perps)
S2 applies identical cost-ratio logic to crypto perpetuals, mapped across three global sessions Tom Espel — BTC/ETH intraday regime seasonality:
- Asia (00:00–06:00 UTC): Lower participation; higher relative spread cost.
- Europe (08:00–16:30 UTC): High liquidity; tight spreads.
- Americas (13:30–20:00 UTC): Peak volume; institutional fixing flows.
S2 eliminates broad weekday dummy variables. It replaces them with an explicit Sunday 23:00–00:00 UTC filter to isolate weekly retail positioning spikes MLQuants — day-of-week effects are hourly.
S3: The Rent Bouncer (Perpetual Funding Clocks)
S3 enforces venue-specific funding discipline:
- Coinbase (Hourly): Stands down during the final 15 minutes of each hour Coinbase funding — hourly calculation.
- Binance/Deribit (8-Hour): Stands down ±15 minutes around 00:00, 08:00, and 16:00 UTC FeeFlux — funding rate guide (Binance 8-hour mechanism).
S3 runs a direct ablation: Stand down during settlement versus Hold through and book realized funding.
flowchart TD
data["OHLCV + spread<br/>M1/M5/M15 completed<br/>H1/H4/D1 releases"] --> atlas["Hour/minute atlas<br/>spread/ATR/pass rate"]
atlas --> s1["S1 RTH Atlas Gate<br/>09:30-16:00 ET<br/>freeze tagged"]
atlas --> s2["S2 UTC Session Filter<br/>Asia/Europe/Americas<br/>Sunday 23:00 flagged"]
atlas --> s3["S3 Funding Stand-Down<br/>hourly vs 8-hour<br/>book or avoid"]
s1 --> replay["Conservative bar replay<br/>close[t] -> open[t+1]<br/>spread + funding booked"]
s2 --> replay
s3 --> replay
replay --> oos{"Purged walk-forward<br/>net per session<br/>vs all-hours?"}
oos -->|"pass"| carry["Carry gate + clock<br/>to M14/M10/M11"]
oos -->|"revise"| narrow["Revise tiles<br/>or widen stand-down"]
oos -->|"reject"| stop["Reject gate<br/>keep all-hours baseline"]
classDef data fill:#e8f0fe,stroke:#4a86e8
classDef process fill:#f3f3f3,stroke:#888
classDef decision fill:#fff4d6,stroke:#d6a300
classDef risk fill:#fde8e8,stroke:#c0392b
classDef ok fill:#e6f4ea,stroke:#2e7d32
class data data
class atlas,s1,s2,s3,replay,narrow process
class oos decision
class stop risk
class carry okStrategy Rules
Every strategy card adheres to the standard nine-point quantitative specification.
S1: RTH Segment Atlas Gate (Full Specification)
1. Market, Timeframe, and Data Assumptions
- Universe: NYSE Arca-listed commodity ETPs: GLD (Physical Gold Trust) SSGA — GLD or PDBC (Commodity Pool) Invesco — PDBC. Long-only unless short locate availability is documented.
- Timeframe: Primary M5 resolution. M1/M15 sensitivity checks.
- Data Contract: Strictly OHLCV + timestamped spread. Point-in-time timezone conversion (America/New_York).
2. Mechanics vs. Testable Hypothesis
- Mechanics: Intraday volume and spread follow a U-shape Pomegra — volume by time of day. Spreads start wide at 09:30, tighten by 10:00, and expand into the 15:50 MOC freeze StockTitan — opening & closing auctions.
- Hypothesis: Restricting M5 breakout triggers to hours where
Spread/ATR <= 15%and gating out the 15:50–16:00 freeze increases net Sharpe ratio versus an ungated baseline.
3. Required Technical Indicators
- Causal ATR(14): Smoothed True Range computed on completed bars Investopedia ATR.
- Spread Metrics: Dynamic
Spread / ATRand(Spread + Fees) / Target. - Trailing Spread Percentile: Rolling 75th percentile of spread within the current hour.
- Trigger Indicator: 20-bar Donchian Channel High/Low.
4. Causal HTF Context and Intraday Triggers
- HTF Context (H1): Completed H1 close > 20-period EMA. Released at
H1_Close + 1_minute_lag. - M5 Trigger: Bar
tclose breaks above the 20-bar Donchian High. Evaluated only if bartclears all session gates.
5. Order Execution, Stops, Targets, and Flattening
- Entry: Signal at close of bar
t-> Market Buy fill at open of bart+1+ 0.5 × Spread. - Stop Loss:
Entry_Price - (1.2 * ATR[t]). - Profit Target:
Entry_Price + (1.0 * ATR[t]). - Time Stop: 16 bars (80 minutes maximum hold).
- Forced Flatten: Unconditional market exit at 15:58 ET. No overnight carry.
6. Friction Handling and Conservative Execution
- Full observed spread deducted on entry and exit.
- Adverse Intra-bar Resolution: If both Stop Loss and Profit Target fall within bar
t+k’s range (High/Low), the engine books a Stop Loss.
7. Position Sizing and Risk Scaffolding
- Fixed-fractional risk: 0.25% equity risk per trade.
- Maximum 3 trades per session. Daily portfolio stop at 1.0% equity drawdown.
8. Machine Learning Extension (Walk-Forward Meta-Filter)
- Baseline: Fixed deterministic threshold (
s2atr <= 0.15). - Logistic Meta-Classifier: Fit on training folds only. Predicts trade success probability using 5 causal features:
[Spread_Percentile_Hour, Lagged_s2atr, ATR_Percentile, Hour_Sin, Hour_Cos]. - Evaluation: Must demonstrate an out-of-sample information ratio gain over the deterministic baseline on purged folds.
9. Failure Modes and Preregistered Reject Triggers
- Midday ATR Collapse: Midday bars pass spread tests but lack sufficient range to hit targets before time stops trigger.
- Hard Reject Criteria: Reject the system if gated net P&L fails to beat the ungated baseline, or if the strategy leaves fewer than 200 tradable sessions per year.
S2: Crypto UTC Session Filter & Sunday Spike Trap
1. Market, Timeframe, and Data Assumptions
- Universe: BTC-USDT and ETH-USDT spot and linear perpetuals on approved CEXs.
- Timeframe: Primary M5 resolution. UTC synthetic trading session (00:00–23:50 UTC).
- Data Contract: Causal OHLCV + venue-recorded spread. Point-in-time funding stream.
2. Mechanics vs. Testable Hypothesis
- Mechanics: Crypto volatility follows an M-shaped profile peaking at the London open (08:00 UTC) and NY overlap (13:30–16:00 UTC) MarketsByte — intraday volatility by session. Weekly anomalies collapse to Sunday 23:00 UTC retail re-positioning MLQuants — day-of-week effects are hourly.
- Hypothesis: Confining directional trading to European/Americas sessions (08:00–20:00 UTC) while isolating the Sunday 23:00 UTC sleeve yields higher net expectancy than 24/7 continuous trading.
3. Required Indicators & Calculations
- Causal ATR(14), dynamic
Spread / ATR, cyclical UTC hour encodings (sin/cos), and Tom Espel regional session tags Tom Espel.
4. Intraday Triggers & Timing
- Baseline Donchian breakout (M5) active strictly between 08:00 and 20:00 UTC.
- Dedicated Sunday Sleeve: Evaluates momentum continuation specifically between Sunday 23:00 and Monday 00:00 UTC.
5. Execution, Stops, Targets, and Flattening
- Fills at open of bar
t+1with full spread deducted. Stop loss at 1.2 × ATR, profit target at 1.0 × ATR. - Mandatory Daily Flatten: 23:50 UTC synthetic reset.
6. Friction & Funding Accounting
- Deduct full observed spread. If held through an 8-hour settlement mark (e.g., 16:00 UTC), deduct
Notional * Realized_Funding_Rate.
7. Sizing & Risk Controls
- 0.25% risk per trade. Max 4 trades per 24-hour UTC cycle. Weekend trading disabled by default.
8. ML Meta-Filter
- Gradient Boosted Classifier (XGBoost) trained on chronological folds to predict trade viability during high-volatility European opening bars.
9. Failure Modes & Reject Triggers
- Illusion of Weekday Alpha: Using weekday dummy variables instead of precise UTC hourly features overfits historical data Securities.io.
- Reject Trigger: Reject if Europe/Americas-only filtering fails to beat 24/7 execution net of trading costs.
S3: Funding-Clock Stand-Down (Hourly vs. 8-Hour Venues)
1. Market, Timeframe, and Data Assumptions
- Universe: BTC-USDT linear perpetuals across two distinct venue architectures:
- Venue A (Coinbase): Continuous hourly funding Coinbase funding — hourly calculation.
- Venue B (Binance / OKX): 8-hour discrete settlement (00:00, 08:00, 16:00 UTC) FeeFlux — funding rate guide (Binance 8-hour mechanism).
- Data Contract: M5 OHLCV + spread + historical funding rate ledger.
2. Mechanics vs. Testable Hypothesis
- Mechanics: Funding is a cash transfer between longs and shorts. Longs pay shorts when perps trade at a premium to spot. Payment applies strictly to positions open at the settlement second.
- Hypothesis: Standing down ±15 minutes around settlement timestamps prevents adverse spread widening and funding decay, improving net returns over a buy-and-hold strategy.
3. Required Calculations
Minutes_To_Next_FundingandMinutes_Since_Last_Funding. Realized funding rate ledger joined causally.
4. Intraday Triggers & Gating
- Identical M5 momentum trigger as S1/S2. Gated out whenever
abs(Minutes_To_Next_Funding) <= 15.
5. Execution & Flattening
- Next-bar open fill. Stop at 1.2 × ATR; Target at 1.0 × ATR. Mandatory flatten at 23:50 UTC.
6. Friction & Cost Booking
- Active comparison:
- Branch 1 (Stand-Down): Zero funding booked; settlement bars skipped.
- Branch 2 (Funding-Blind): All bars traded;
Notional * Ratebooked whenever a position crosses settlement.
7. Sizing & Risk
- 0.25% equity risk per trade. Sizing strictly normalized across both branches.
8. ML Extension
- Logistic regression estimating the probability of pre-funding spread widening as a function of trailing funding rate magnitude.
9. Failure Modes & Reject Triggers
- Universal Rate Assumption: Applying 8-hour math to hourly venues distorts backtest metrics.
- Reject Trigger: Reject stand-down logic if the cost of missed momentum trades during settlement windows exceeds total funding fees saved.
Building It In Python
Below is the complete implementation of the strategy lab, featuring feature engineering, causal ML meta-filtering, and conservative backtest replay.
"""
Module 13 Strategy Lab: Multi-Clock Session & Funding Filter Engine.
Stack: Polars, NumPy, Scikit-Learn, XGBoost.
"""
import polars as pl
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import TimeSeriesSplit
# ---------------------------------------------------------
# 1. Feature Engineering: Clocks & Causal Ratios
# ---------------------------------------------------------
def prepare_strategy_features(df: pl.DataFrame, venue: str = "NYSE") -> pl.DataFrame:
"""
Builds technical indicators, clock encodings, and compliance flags.
"""
# Causal ATR
prev_close = df["close"].shift(1)
tr = pl.max_horizontal([
df["high"] - df["low"],
(df["high"] - prev_close).abs(),
(df["low"] - prev_close).abs(),
])
df = df.with_columns(tr.alias("tr"))
atr14 = df["tr"].ewm_mean(span=14, adjust=False).alias("atr_14")
df = df.with_columns(atr14)
# Ratios
df = df.with_columns([
(pl.col("spread") / pl.col("atr_14")).alias("s2atr"),
(pl.col("spread") / (0.9 * pl.col("atr_14"))).alias("c2t_09"),
# Donchian High (20-bar)
pl.col("high").rolling_max(window_size=20).shift(1).alias("donchian_high_20"),
])
# UTC Clock Encodings
utc_hour = df["timestamp"].dt.convert_time_zone("UTC").dt.hour()
utc_min = df["timestamp"].dt.convert_time_zone("UTC").dt.minute()
hour_rad = (2 * np.pi * utc_hour / 24.0)
df = df.with_columns([
hour_rad.cos().alias("hour_cos"),
hour_rad.sin().alias("hour_sin"),
# Sunday 23:00 UTC Flag
((df["timestamp"].dt.weekday() == 7) & (utc_hour == 23)).alias("is_sunday_2300"),
])
# Compliance Stand-Down Flags
if venue == "NYSE":
et_hour = df["timestamp"].dt.convert_time_zone("America/New_York").dt.hour()
et_min = df["timestamp"].dt.convert_time_zone("America/New_York").dt.minute()
is_freeze = ((et_hour == 15) & (et_min >= 50)) | (et_hour == 16)
df = df.with_columns(is_freeze.alias("stand_down"))
elif venue == "Coinbase":
is_settle = (utc_min >= 45) | (utc_min <= 5)
df = df.with_columns(is_settle.alias("stand_down"))
else: # Binance 8-Hour
is_settle = utc_hour.is_in([0, 8, 16]) & ((utc_min >= 45) | (utc_min <= 15))
df = df.with_columns(is_settle.alias("stand_down"))
# Master Gate Boolean
df = df.with_columns(
((pl.col("s2atr") <= 0.15) & (pl.col("c2t_09") <= 0.10) & (~pl.col("stand_down"))).alias("gate_pass")
)
return df
# ---------------------------------------------------------
# 2. Causal Replay Engine with Adverse Ambiguity Resolution
# ---------------------------------------------------------
def run_conservative_replay(df: pl.DataFrame, k_stop: float = 1.2, k_target: float = 1.0,
t_max_bars: int = 16, book_funding: bool = True) -> pl.DataFrame:
"""
Simulates execution strictly on bar t+1 open, deducting real spreads and funding.
"""
trades = []
in_pos = False
entry_price = 0.0
stop_price = 0.0
target_price = 0.0
entry_bar = 0
rows = df.to_dicts()
for i in range(len(rows) - 1):
curr = rows[i]
nxt = rows[i + 1]
# Check Entry (Bar t signal -> Bar t+1 Open fill)
if not in_pos and curr["gate_pass"] and (curr["close"] > curr["donchian_high_20"]):
in_pos = True
spread = nxt["spread"]
entry_price = nxt["open"] + (0.5 * spread)
atr = curr["atr_14"]
stop_price = entry_price - (k_stop * atr)
target_price = entry_price + (k_target * atr)
entry_bar = i + 1
continue
# Manage Open Position
if in_pos:
bars_held = i - entry_bar
hit_stop = curr["low"] <= stop_price
hit_target = curr["high"] >= target_price
pnl = 0.0
exit_reason = ""
# Adverse Ambiguity: Stop Loss takes priority if both are touched
if hit_stop and hit_target:
pnl = stop_price - entry_price - (0.5 * curr["spread"])
exit_reason = "ambiguous_stop"
in_pos = False
elif hit_stop:
pnl = stop_price - entry_price - (0.5 * curr["spread"])
exit_reason = "stop_loss"
in_pos = False
elif hit_target:
pnl = target_price - entry_price - (0.5 * curr["spread"])
exit_reason = "profit_target"
in_pos = False
elif bars_held >= t_max_bars or curr["stand_down"]:
# Time Stop or Session Flatten
pnl = curr["close"] - entry_price - (0.5 * curr["spread"])
exit_reason = "session_flatten"
in_pos = False
if not in_pos:
trades.append({
"entry_idx": entry_bar,
"exit_idx": i,
"net_pnl": pnl,
"exit_reason": exit_reason,
"is_win": pnl > 0
})
return pl.DataFrame(trades) if trades else pl.DataFrame()
# ---------------------------------------------------------
# 3. Walk-Forward ML Meta-Filter (Purged & Embargoed)
# ---------------------------------------------------------
def train_walk_forward_meta_filter(df: pl.DataFrame, feature_cols: list[str]) -> dict:
"""
Trains a causal Logistic Regression meta-filter on historical trade setups.
"""
X = df.select(feature_cols).to_numpy()
y = (df["target_pnl"] > 0).to_numpy().astype(int)
tscv = TimeSeriesSplit(n_splits=5)
out_of_sample_preds = np.zeros(len(df))
pipeline = Pipeline([
("scaler", StandardScaler()),
("classifier", LogisticRegression(class_weight="balanced", max_iter=200))
])
for train_idx, test_idx in tscv.split(X):
# 1-fold embargo to eliminate cross-boundary overlap
embargoed_test_idx = test_idx[1:]
pipeline.fit(X[train_idx], y[train_idx])
probs = pipeline.predict_proba(X[embargoed_test_idx])[:, 1]
out_of_sample_preds[embargoed_test_idx] = probs
return {"predictions": out_of_sample_preds, "model": pipeline}
Worked Numeric Walkthrough: Hand-Checkable Math
Let us evaluate the math for an S3 perpetual funding trade on a Coinbase-like hourly schedule.
Trade Parameters:
- Position: Long 1.0 BTC at $84,200.00.
- Target Distance: $842.00 (1.0 × ATR). Stop Distance: $1,010.40 (1.2 × ATR).
- M5 Observed Spread: $3.50. Hourly Realized Funding Rate: +0.0020% (Longs pay shorts).
| Step | Metric | Formula | Value (Stand-Down Gate) | Value (Funding-Blind Gate) |
|---|---|---|---|---|
| 1 | Entry Fill Price | Next_Open + 0.5 * Spread |
$84,201.75 | $84,201.75 |
| 2 | Raw Trade Exit (Target Hit) | Target_Price - 0.5 * Spread |
$85,040.00 | $85,040.00 |
| 3 | Gross Trading P&L | Exit_Price - Entry_Price |
+$838.25 | +$838.25 |
| 4 | Settlement Straddled? | Crosses top-of-hour? | NO (Stood down) | YES (Held across 2 hours) |
| 5 | Realized Funding Cost | 2 * (Notional * Rate) |
$0.00 | 2 * ($84,200 * 0.002%) = $3.37 |
| 6 | Total Round-Trip Spread | Entry_Spread + Exit_Spread |
$3.50 | $3.50 |
| 7 | Net Realized P&L | Gross - Spread - Funding |
+$834.75 | +$831.38 |
What this means for your P&L: While a $3.37 funding leakage appears small on a single trade, compounding that drag across 500 annual trades erodes $1,685 per contract in pure friction. Standing down during settlement buffers captures 99.6% of directional alpha while paying zero holding rent.
Testing It Honestly
| Pitfall Visible in Strategy Lab | Deceptive Result | Robust Defense Mechanism |
|---|---|---|
| Weekday Dummy Artifacts | Finding “Monday Alpha” that vanishes out of sample. | Drop weekday dummies. Encode UTC hours cyclically via sin/cos. Weekly effects collapse to Sunday 23:00 UTC MLQuants. |
| Funding Schedule Generalization | Modeling an hourly venue using 8-hour batch assumptions. | Dynamically load the venue’s settlement cadence from the instrument master. |
| Midday Range Starvation | High win-rates with negative total P&L due to time stops. | Enforce the c2t <= 0.10 cost-to-target gate. If ATR collapses, stand down regardless of spread tightness. |
| Overfitting Micro-Sleeves | Claiming a 10-minute trading window is an edge. | Test ±10m, ±15m, and ±30m buffers. If alpha only exists in one narrow window, reject it as sample noise. |
| Favorable Ambiguity Assumption | Inflating Sharpe ratio by booking targets on dual-touch bars. | Enforce adverse-first resolution (always book the stop loss on ambiguous intra-bar touches). |
Variants & Extensions
| Variant | Parameter Shift | Target Condition | Key Trade-off to Audit |
|---|---|---|---|
| S1: Midday Blackout | Exclude 11:30–13:30 ET entirely. | Commodity ETPs with wide midday spread-to-ATR ratios. | Eliminates time-stop decay; lowers annual trade count by 25%. |
| S2: London Open Sleeve | Trade 08:00–10:00 UTC exclusively. | High-beta crypto perpetuals. | Maximizes momentum capture; reduces daily exposure. |
| S3: Asymmetric Carry | Trade through funding only when holding the receiving side. | Persistent high-premium market regimes. | Captures funding subsidy; introduces directional inventory risk. |
| HTF Causal Gate | Require H1 EMA20 alignment on M5 breakouts. | RTH commodity index pools. | Cuts false breakout rates by ~30%; delays entry timing. |
| Step-Out to M15 | Resample M5 signals to M15 bars. | Niche commodity wrappers with wide spreads. | Improves spread-to-ATR ratio; reduces annual trade opportunities. |
Hands-On Project
Deliverable: docs/research/m13_session_lab.md and notebooks/m13_session_lab.ipynb. Build the end-to-end multi-clock strategy lab, run purged walk-forward backtests for S1, S2, and S3, and publish a one-page decision memo per lane.
Project Card — M13 Session Lab (v1.0)
| Area | Specification Requirement |
|---|---|
| Universe & Data | ETP Lane: GLD (Physical Gold) + PDBC (Commodity Pool).<br/>Crypto Lane: BTC-USDT and ETH-USDT spot and linear perps on approved CEX. |
| Timeframes & Horizon | Primary M5 execution. Unconditional same-session forced flatten. |
| Venue Clocks | ETP: NYSE RTH (09:30–16:00 ET). Imbalance freeze 15:50–16:00 ET.<br/>Crypto: UTC Synthetic (00:00–23:50 UTC). Hourly & 8-hour funding calendars. |
| Execution Policy | Signal at bar t close -> Fill at bar t+1 open. Full observed spread deducted. Adverse intra-bar ambiguity resolution. |
| Risk Parameters | 0.25% equity risk per trade. Max 3 trades per session. Daily portfolio stop: 1.0%. |
| Validation Architecture | 5-Fold Chronological Walk-Forward with 1-session embargo. Strict DST shift tests. |
| Reject Criteria | Reject if cost-to-target > 10%, if ambiguous share > 5%, or if ML fails to beat deterministic baseline out-of-sample. |
Lab Tasks:
- Load Market Data: Ingest 1 year of M5 bars with real-time spreads. Verify timezone formatting and timestamp alignments per M4.
- Implement Hard Gates: Code the session atlas, auction freeze bouncer, and venue funding stand-down modules.
- Run Baseline vs. Gated Replays: Run walk-forward simulations for S1, S2, and S3 against ungated control baselines.
- Train ML Meta-Filters: Fit causal logistic regression and XGBoost classifiers on training folds. Evaluate performance on embargoed test sets.
- Ablation & Stress Testing: Run base, p50, and p90 spread stress models. Verify performance across seasonal Daylight Saving Time shifts.
Key Takeaways
- A session filter is a cost bouncer: Filtering for cheap, tall bars protects your edge before indicator logic evaluates direction.
- RTH and Crypto demand separate atlases: Never pool 24-hour crypto data with U-shaped exchange sessions into a single statistical average.
- Crypto weekday alpha is an hourly illusion: Weekly retail anomalies concentrate into Sunday 23:00 to Monday 00:00 UTC.
- Auctions are canal locks: Gate out trading during the 15:50–16:00 ET imbalance freeze unless modeling explicit auction mechanics.
- Funding is explicit lease rent: Stand down ±15 minutes around settlement timestamps or book realized cash payments.
- Deterministic baselines come first: An ML meta-filter must prove out-of-sample information ratio gains over a simple rule before earning deployment.
References
- NYSE — Holidays & Trading Hours — https://www.nyse.com/markets/hours-calendars — Mechanics. Core RTH schedule, auction locks, and imbalance cutoffs.
- StockTitan — Opening & Closing Auctions: How Stock Market Auctions Work — https://www.stocktitan.net/articles/opening-closing-auctions-explained — Mechanics. Breakdown of MOC/LOC order mechanics.
- SSGA — SPDR Gold Shares (GLD) — https://www.ssga.com/us/en/intermediary/etfs/spdr-gold-shares-gld — Mechanics. Physical trust wrapper specifications.
- Invesco — Optimum Yield Diversified Commodity Strategy No K-1 ETF (PDBC) — https://www.invesco.com/us/financial-products/etfs/invesco-optimum-yield-diversified-commodity-strategy-no-k-1-etf.html — Mechanics. Futures-based pool roll structure.
- Pomegra Learn Library — Liquidity in Commodity ETFs — https://pomegra.io/learn/library/track-d-other-assets/commodities/chapter-09-commodity-etfs-and-etns/commodity-etf-liquidity — Mechanics. Intraday spread curves across commodity products.
- Pomegra Wiki — Volume by Time of Day: Intraday Patterns Explained — https://pomegra.io/wiki/volume-by-time-of-day-patterns/ — Mechanics. Volume distributions across regular market sessions.
- MarketsByte — Intraday Volatility by Trading Session Explained — https://marketsbyte.com/learn/technical-analysis/intraday-volatility-by-session/ — Mechanics. Multi-session overlap volatility dynamics.
- Tom Espel — BTC and ETH display intraday seasonality — https://tomespel.com/p1.html — Empirical Evidence. Session-based volume concentration in Bitcoin and Ether.
- Securities.io — Crypto’s Day-of-the-Week Effect May Be a Mirage — https://securities.io/crypto-day-of-the-week-effects-intraday-patterns/ — Empirical Evidence. Refutation of generic weekday seasonality.
- MLQuants — Are Day-of-the-Week Effects in Cryptocurrencies Real? — https://mlquants.substack.com/p/are-day-of-the-week-effects-in-cryptocurrencies — Empirical Evidence. Hourly concentration of crypto weekly effects.
- Coinbase Help — What is the funding rate and why does it exist? — https://help.coinbase.com/en/derivatives/perpetual-style-futures/funding-rate — Mechanics. Coinbase hourly funding rate mechanics.
- FeeFlux — Funding Rate: What It Costs a Position (Binance 8-hour mechanism) — https://feeflux.com/en/articles/funding-rate-cost/ — Mechanics. 8-hour perpetual swap settlement cycles.
- Investopedia — Average True Range (ATR) — https://www.investopedia.com/terms/a/atr.asp — Technical Metric. Definition of True Range and ATR.
- ohlcv.io — The Bar Resolution Problem — https://ohlcv.io/posts/backtesting-pitfalls/04-bar-resolution/ — Mechanics. Execution pitfalls in bar-based backtesting.
- QuantJourney — Execution Assumptions — https://backtester.quantjourney.cloud/engine/execution-assumptions — Mechanics. Safe stop-first conventions in quantitative engines.
- Saral Money — Backtest Execution Timing: Fill at the Next Bar’s Open — https://saral.money/blog/next-bar-open-execution-timing/ — Mechanics. Elimination of same-bar execution lookahead bias.
Next: Module 14 — Intraday Events · Core: Module 13 — Sessions, Auctions & Funding Clocks