Module 7 Companion — Scalping/Intraday Frequency & Feasibility Experiments
Part III · Intraday Design, Alpha & Playbooks · Companion to Module 7 Prerequisites: M7, M5, M22, M23
Overview
The core module established the feasibility framework: evaluating Average True Range (ATR) against observed spreads, calculating cost-to-target ratios, building hourly atlases, and applying conservative same-session execution rules.
This companion provides three structured experiments designed to answer one central question: Is this specific timeframe and session window tradable after costs, or should it be stepped slower, restricted to liquid hours, or rejected entirely?
None of these experiments claims to prove alpha. Each is an empirical feasibility audit with preregistered cost ceilings, explicit metrics, and objective rejection criteria.
| Experiment | Core Question | Target Lane & Clock | Primary Gate |
|---|---|---|---|
| E1 — ATR-to-Spread Frontier | Do median moves at M1, M5, and M15 cover transaction costs net of spread? | One commodity ETP (RTH) + one BTC/ETH perp (UTC synthetic) | Spread-to-ATR ≤ ceiling and Cost-to-Target ≤ ceiling |
| E2 — Session Clock Atlas | Which specific hours of the trading day offer high ATR and narrow spreads? | ETP RTH (09:30–16:00 ET) vs. Crypto synthetic (00:00–23:50 UTC) | Hourly pass rate across cost and volatility filters |
| E3 — Causal HTF Gating | Does higher-timeframe alignment improve net viability, or does it merely starve trade frequency? | Same two lanes across candidate execution timeframes | Aligned net pass rate and opportunity count vs. ungated baseline |
💡 The Wage vs. Toll Analogy: Feasibility is an accounting audit, not a prediction. You are comparing the broker’s invoice (spread + fees) against the market’s gross wage (ATR) under a strict calendar that tells you when both are active.
📌 Data Contract: All experiments use OHLCV + spread data only. Technical calculations are bar-based; no order book or tick data is assumed. Signals on the close of bar
tfill at the open of bart+1. Ambiguous bars resolve stop-first. All positions are forced flat before the session close. Completed H1/H4/D1 bars serve as causal context only.
How It Works
The three experiments follow a sequential decision pipeline.
E1 — The Frequency Frontier
Resample completed bars to M1, M5, and M15. Calculate median ATR, median observed spread, Spread-to-ATR, and Cost-to-Target across each timeframe. Apply your preregistered cost ceilings and opportunity floors. Timeframes that fail basic arithmetic are eliminated immediately.
E2 — The Clock Atlas
Take the surviving timeframe from E1 and break it down by hour of the day. Map median spread, median ATR, and cost pass rates across each hourly tile. This isolates structural liquidity sweet spots (narrow spreads, tall bars) from expensive dead zones (wide spreads, flat bars).
E3 — The Causal HTF Gate Test
Add a completed higher-timeframe filter (such as an H1 20 EMA trend or H4 volatility regime) to the surviving timeframe. Compare the gated strategy directly against the ungated baseline. An HTF gate is only justified if it improves net expectancy per session without crushing overall trade opportunity.
Figure: The experimental workflow. E1 screens timeframes, E2 maps tradable hours, and E3 audits higher-timeframe gating.
flowchart TD
data["OHLCV + spread<br/>completed M1/M5 + H1/H4/D1 releases"] --> e1["E1 Frontier<br/>M1 vs M5 vs M15"]
e1 -->|"best TF + target"| e2["E2 Clock Atlas<br/>RTH vs UTC synthetic"]
e1 --> e3["E3 HTF-Gated Feasibility<br/>gated vs ungated"]
e2 --> e3
e3 --> decision{"Revise<br/>or reject?"}
decision -->|"pass"| carry["Carry horizon + clock + gate<br/>to M8/M10/M11"]
decision -->|"revise"| e1
decision -->|"reject"| stop["Reject TF or clock<br/>document & stop spend"]
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 e1,e2,e3 process
class decision decision
class stop risk
class carry okStrategy Rules
Each experiment follows our standardized nine-point protocol.
E1 — ATR-to-Spread & Cost-to-Target Frontier (M1 vs. M5 vs. M15)
1. Market, Timeframe, and Data Assumptions
- Lanes: One U.S. commodity ETP (e.g., GLD physical trust or PDBC futures pool) and one BTC or ETH linear perpetual on an approved exchange.
- Clocks: ETP operates on RTH (09:30–16:00 ET); Crypto operates on an explicit UTC synthetic session (00:00–23:50 UTC).
- Data: Clean OHLCV + timestamped spread per bar. Resampled strictly from completed M1 bars.
2. Mechanics vs. Testable Hypothesis
- Mechanics: ETF share creation/redemption SEC ETF bulletin, futures roll costs Fidelity on contango/backwardation, and perpetual funding rates Coinbase perpetual funding dictate product friction.
- Hypothesis: At least one timeframe in {M1, M5, M15} generates sufficient median ATR relative to spread such that
Spread-to-ATR ≤ 15%andCost-to-Target ≤ 10%while satisfying the session opportunity floor.
3. Required Indicators & Calculations
- True Range and ATR(14) via exponential moving average.
- Timestamped spread and rolling session spread percentiles.
- Derived ratios:
Spread ÷ ATRand(Spread + Fees + Slippage) ÷ Target.
4. Causal HTF Context & LTF Trigger
- E1 evaluates raw baseline feasibility without HTF gating.
- Signals evaluate at the close of bar
tand execute at the open of bart+1.
5. Entry, Stop, Target, Time Stop, and Forced Flatten
- Simulated Entry: Open of bar
t+1paying the ask (entry price + half-spread). - Hypothetical Target: $0.9\times$ to $1.2\times$ ATR from entry.
- Hypothetical Stop: $1.0\times$ to $1.5\times$ ATR from entry.
- Forced Flatten: Unconditional exit at the final eligible bar of the session. Zero overnight positions.
6. Cost Filters & Conservative Execution
- Cost Ceilings: Median Spread-to-ATR ≤ 15%; Cost-to-Target ≤ 10%.
- Path Ambiguity: If a bar touches both stop and target, record as stop-first (worst case) or exclude from expectancy.
7. Position Sizing & Risk Limits
- Feasibility triage phase: Sizing is fixed at 1 hypothetical unit to audit gross vs. net move distribution.
8. Machine Learning Extension (Walk-Forward Meta-Filter)
- Baseline: Deterministic cost-gate rule.
- Model: Train a regularized Logistic Regression classifier on rolling chronological folds.
- Features (Strictly Trailing): Trailing spread percentile, lagged Spread-to-ATR, rolling ATR percentile, and cyclical hour encodings.
- Target: Predict whether an eligible bar yields a net positive return under full cost deduction.
- Validation: Purged rolling walk-forward with an embargo period. All scalers fit on training folds only.
9. Failure Modes & Rejection Criteria
- M1 Toll Trap: Spread-to-ATR exceeds 20% across all hours. Verdict: Reject M1; step out to M5.
- Sample Starvation: Cost filters pass, but fewer than 3 trades occur per session. Verdict: Reject timeframe.
- Rejection Trigger: If median Cost-to-Target exceeds 10% after fees, discard the horizon.
E2 — RTH vs. UTC-Synthetic Clock Atlas
1. Market, Timeframe, and Data Assumptions
- Evaluates the winning timeframe from E1 (typically M5 or M15).
- Same dual-lane scope: Commodity ETP on RTH vs. Crypto perp on UTC synthetic.
2. Mechanics vs. Testable Hypothesis
- Mechanics: Intraday volume and liquidity cluster around specific market openings and session overlaps Pomegra on commodity ETF liquidity.
- Hypothesis: Restricting trading to high-liquidity hourly tiles brings session-level Cost-to-Target below 10% without dropping total session opportunity below the statistical floor.
3. Required Indicators & Calculations
- Hourly median ATR, median spread, Spread-to-ATR, and 90th percentile spread spikes.
4. Causal HTF Context & Trigger
- Prior completed Daily ATR rank or H1 volatility regime determines whether tomorrow’s session is eligible for trading.
5. Execution & Flatten Contract
- Standard contract: Signal on close of bar
t→ fill at open of bart+1. Mandatory forced flatten at session end.
6. Cost Filter & Execution
- Hourly tiles are flagged as tradable only if their median Spread-to-ATR ≤ 15%.
7. Sizing & Risk
- Concentrating trades into fewer liquid hours does not justify increasing leverage. Standard risk limits apply.
8. ML Extension (Hourly Tile Classifier)
- Train a shallow XGBoost or Decision Tree model against a Logistic Regression baseline on chronological folds.
- Predict hourly profitability regimes using trailing volume, spread z-scores, and prior-day range metrics.
9. Failure Modes & Rejection Criteria
- Calendar Overfitting: Micro-slicing data into arbitrary 15-minute windows. Fix: Restrict analysis to full 1-hour blocks.
- Rejection Trigger: Reject the clock if no contiguous 2-hour window clears the 10% Cost-to-Target ceiling.
E3 — Causal HTF-Gated Feasibility (H1/H4 Context)
1. Market, Timeframe, and Data Assumptions
- Same lanes and execution timeframes as E1 and E2.
- Adds completed H1 and H4 bars joined strictly at their close timestamp.
2. Mechanics vs. Testable Hypothesis
- Mechanics: Higher-timeframe bars summarize institutional flow. Filtering against HTF trend reduces counter-trend chop.
- Hypothesis: Requiring M5 trades to align with completed H1 20 EMA trend direction increases net session expectancy after spreads compared to an ungated baseline.
3. Required Indicators & Calculations
- Completed H1 20 EMA slope, H1 ADX(14), and prior completed Daily high/low levels.
4. Causal Synchronization
- An H1 feature stamped at 10:00 is only tradable starting at the 10:05 M5 open. The forming 10:00–11:00 bar is completely invisible.
5. Entry, Stop, and Flatten Rules
- Same M5 entry rules, filtered by H1 trend permission. Mandatory session flatten remains unchanged.
6. Cost Filter
- Same per-bar spread ceilings applied inside and outside the HTF gate.
7. Sizing & Risk
- Standard ATR-based risk sizing. Gated setups do not receive larger capital allocations.
8. ML Extension (Regime Routing)
- Fit a 2-state Hidden Markov Model (HMM) or GMM on standardized H1 volatility and spread metrics to dynamically route between trend and stand-aside regimes.
9. Failure Modes & Rejection Criteria
- Opportunity Collapse: HTF gate boosts win rate by 2% but eliminates 80% of trades. Verdict: Reject gate.
- Rejection Trigger: Reject the HTF gate if gated net return per session fails to exceed the ungated baseline on out-of-sample folds.
Building It In Python
Here is the complete Polars implementation for E1, E2, and E3.
1. Intuition: The E1 Frequency Frontier
We resample M1 data to M5 and M15, compute completed-bar ATR, and calculate feasibility ratios.
# E1: Timeframe feasibility frontier in Polars
# Q: Which timeframe's gross wage comfortably covers its transaction toll?
import polars as pl
def calculate_true_range(frame: pl.DataFrame) -> pl.Series:
prev_close = frame["close"].shift(1)
return pl.max_horizontal([
frame["high"] - frame["low"],
(frame["high"] - prev_close).abs(),
(frame["low"] - prev_close).abs(),
])
def build_feasibility_frontier(
m1_frame: pl.DataFrame,
ceilings: dict = None,
target_mult: float = 0.9
) -> pl.DataFrame:
ceilings = ceilings or {"spread_to_atr": 0.15, "cost_to_target": 0.10}
summary_rows = []
for tf, every in [("M1", "1m"), ("M5", "5m"), ("M15", "15m")]:
# Resample completed bars
resampled = (
m1_frame.group_by_dynamic("timestamp", every=every)
.agg([
pl.first("open").alias("open"),
pl.max("high").alias("high"),
pl.min("low").alias("low"),
pl.last("close").alias("close"),
pl.mean("spread").alias("spread"),
])
.sort("timestamp")
)
# Calculate ATR and Ratios
resampled = resampled.with_columns(
calculate_true_range(resampled).ewm_mean(span=14, adjust=False).alias("atr14")
)
resampled = resampled.with_columns([
(pl.col("spread") / pl.col("atr14")).alias("spread_to_atr"),
(pl.col("spread") / (target_mult * pl.col("atr14"))).alias("cost_to_target"),
])
# Filter by cost ceilings
passed = resampled.filter(
(pl.col("spread_to_atr") <= ceilings["spread_to_atr"]) &
(pl.col("cost_to_target") <= ceilings["cost_to_target"])
)
summary_rows.append({
"timeframe": tf,
"total_bars": resampled.height,
"median_atr": resampled["atr14"].median(),
"median_spread": resampled["spread"].median(),
"median_s2atr": resampled["spread_to_atr"].median(),
"median_c2t": resampled["cost_to_target"].median(),
"passed_bars": passed.height,
"pass_rate": passed.height / max(1, resampled.height),
})
return pl.DataFrame(summary_rows)
What this means for your P&L: This table tells you immediately whether M1 or M5 is mathematically viable. If median_s2atr is 0.22 at M1, you are paying 22% of every bar in friction—meaning M1 should be rejected before you design a single indicator.
2. Intuition: The E2 Hourly Clock Atlas
We map cost and volatility across the 24 hours of the day to locate optimal trading windows.
# E2: Hourly clock atlas
# Q: Which hours offer narrow spreads and tall bars?
def build_clock_atlas(frame: pl.DataFrame) -> pl.DataFrame:
return (
frame.with_columns(pl.col("timestamp").dt.hour().alias("hour"))
.group_by("hour")
.agg([
pl.col("spread").median().alias("spread_p50"),
pl.col("spread").quantile(0.90).alias("spread_p90"),
pl.col("atr14").median().alias("atr_p50"),
pl.col("spread_to_atr").median().alias("s2atr_p50"),
(pl.col("cost_to_target") <= 0.10).mean().alias("pass_rate_target10"),
pl.len().alias("bar_count"),
])
.sort("hour")
)
3. Intuition: The E3 Causal HTF Gate Join
We join completed H1 trend features onto M5 bars using a strictly causal as_of join.
# E3: Causal H1 trend gate joined to M5 bars
# Q: Does aligning with completed H1 trend improve net feasibility?
def apply_causal_h1_gate(m5_frame: pl.DataFrame, h1_frame: pl.DataFrame) -> pl.DataFrame:
# Compute H1 20 EMA on completed bars only
h1_processed = h1_frame.with_columns([
pl.col("close").ewm_mean(span=20, adjust=False).alias("ema20_h1")
]).with_columns([
((pl.col("close") > pl.col("ema20_h1")) &
(pl.col("ema20_h1") > pl.col("ema20_h1").shift(1))).alias("h1_bullish")
])
# Ensure H1 timestamp reflects bar close (right-labeled)
# Perform causal as-of join: M5 bar only sees H1 that completed at or before M5 open
m5_gated = m5_frame.join_asof(
h1_processed.select(["timestamp", "h1_bullish"]),
on="timestamp",
strategy="backward"
)
return m5_gated.with_columns(pl.col("h1_bullish").fill_null(False))
4. Intuition: ML Walk-Forward Meta-Filter
We fit a Logistic Regression meta-filter strictly on rolling training windows.
# Walk-forward ML meta-filter
# Q: Can a model learn which cost-passing bars actually follow through?
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
def evaluate_ml_meta_filter(frame: pl.DataFrame, feature_cols: list, target_col: str = "profitable_move"):
features = frame.select(feature_cols).to_numpy()
labels = frame[target_col].to_numpy()
tscv = TimeSeriesSplit(n_splits=5)
model = Pipeline([
("scaler", StandardScaler()),
("classifier", LogisticRegression(C=0.1, penalty="l2"))
])
out_of_sample_preds = []
for train_idx, test_idx in tscv.split(features):
X_train, y_train = features[train_idx], labels[train_idx]
X_test, y_test = features[test_idx], labels[test_idx]
# Fit ONLY on training window
model.fit(X_train, y_train)
probs = model.predict_proba(X_test)[:, 1]
out_of_sample_preds.append((test_idx, probs, y_test))
return out_of_sample_preds
Testing It Honestly
Honest backtesting enforces the following invariants:
- Next-Bar-Open Execution: Signals generated on the close of bar
tfill at the open of bart+1. Filling at the signal close is look-ahead bias Saral on next-bar-open execution. - Spread Deduction: Observed timestamped spreads are deducted from both entry and exit legs.
- Worst-Case Ambiguous Resolution: When a single bar touches both stop loss and take profit, book the stop loss. Never assume favorable intrabar pathing ohlcv.io on bar resolution.
- Purged Walk-Forward Splits: Test folds are session-aligned and embargoed to eliminate information overlap.
- Cost Stress Testing: Evaluate strategies under median spread, p90 spread spikes, and additional fee/slippage stress.
Troubleshooting Diagnostic Table
| Symptom | Probable Cause | Corrective Action |
|---|---|---|
| M1 shows high win rate in backtest but collapses in live paper trading | Backtest filled at signal-bar close or mid-price | Enforce open[t+1] execution and deduct full bid-ask spread |
| Backtest profitability disappears under p90 spread stress | Strategy trades during illiquid spread-spike hours | Restrict trading via the E2 Hourly Atlas |
| HTF gate raises win rate but destroys total P&L | Gate eliminates 80% of eligible trades | Evaluate strategy by net return per session, not per trade |
| Machine learning model beats baseline in-sample but fails OOS | Feature scaler was fit across the entire dataset | Re-fit scalers strictly within each walk-forward training fold |
Variants & Extensions
| Variant | Modification | Intended Benefit | Key Metric to Report |
|---|---|---|---|
| Target Ladder ($0.7\times$ to $1.5\times$ ATR) | Vary profit target multiple | Identifies the optimal trade duration for the asset | Cost-to-Target ratio across targets |
| p90 Spread Stress Scan | Re-run triage using p90 spread surface | Audits strategy survival during volatile liquidity droughts | Pass rate under p90 spread stress |
| Prior-Day Range Filter | Condition trading on prior D1 ATR percentile | Avoids trading during compressed, low-range days | Opportunity count by volatility regime |
| Funding Spike Exclusion | Exclude 15 minutes before/after crypto funding | Avoids spread widening caused by funding arbitrage | Net return with vs. without funding windows |
Hands-On Project
Deliverable: docs/research/m7_feasibility_experiments.md and runnable notebook notebooks/m7_feasibility_experiments.ipynb.
Project Card — M7 Feasibility Experiments (v1.0)
| Specification Area | Project Requirement |
|---|---|
| Assets & Lanes | One commodity ETP (GLD or PDBC) and one crypto perp (BTC or ETH on an approved CEX). |
| Timeframes | Scan M1, M5, and M15; select the dominant timeframe for atlas and HTF gating experiments. |
| Session Calendars | ETP: RTH 09:30–16:00 ET; Crypto: UTC 00:00–23:50 synthetic session (forced flatten at 23:50 UTC). |
| Execution Model | Signal on close of bar t → fill at open of bar t+1; deduct full timestamped spread; worst-case ambiguous resolution. |
| Cost Ceilings | Spread-to-ATR ≤ 15%; Cost-to-Target ≤ 10%; pass rate ≥ 40% of session bars. |
| Validation Design | 5-fold chronological walk-forward with training-only scalers and an untouched holdout dataset. |
| Decision Triggers | Clear verdict required: Pass (carry to M8), Revise (restrict hours/step TF), or Reject (unviable). |
Step-by-Step Instructions
- Resample clean M1 data to M5 and M15. Compute ATR, spreads, and feasibility ratios for both assets.
- Generate the E1 Feasibility Frontier table and record pass/reject verdicts for each timeframe.
- Take the surviving timeframe and construct the E2 Hourly Clock Atlas. Identify the top liquid hours.
- Implement the E3 causal H1 trend gate using backward as-of joins. Run gated vs. ungated ablations.
- Train a walk-forward Logistic Regression meta-filter and measure out-of-sample lift over the baseline.
- Write a one-page decision memo summarizing the tradable parameters for each lane.
Key Takeaways
- Frequency triage is an accounting check: Spread-to-ATR and Cost-to-Target determine viability before alpha logic is tested.
- Hourly atlases prevent trading illiquid traps: Spreads and volatility vary wildly throughout the day. Restrict trading to liquid session windows.
- HTF gates must earn their keep: A gate that improves win rate but starves trade frequency can reduce overall session P&L.
- Enforce causal joins: HTF features must be stamped at bar close and joined backward. Never peek at forming bars.
- ML must serve as a meta-filter: Train small, regularized models strictly on walk-forward folds to filter deterministic setups.
References
- U.S. Securities and Exchange Commission — Exchange-Traded Funds (ETFs) Investor Bulletin — https://www.sec.gov/investor/alerts/etfs.pdf — Mechanics. ETF trading, NAV premiums/discounts, creation/redemption.
- Fidelity — Commodity ETFs — Contango and Backwardation — https://www.fidelity.com/learning-center/investment-products/etf/commodity-etfs-contango-backwardation — Mechanics. Roll cost mechanics in commodity pools.
- SSGA — SPDR Gold Shares (GLD) — https://www.ssga.com/us/en/intermediary/etfs/spdr-gold-shares-gld — Mechanics. Physical gold trust structure.
- 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. Dynamic contract rolling methodology.
- Coinbase — Perpetual Funding Rate Documentation — https://help.coinbase.com/en/derivatives/perpetual-style-futures/funding-rate — Mechanics. Perpetual funding rate mechanics.
- Investopedia — Average True Range (ATR) — https://www.investopedia.com/terms/a/atr.asp — Mechanics / Transfer Support. Standard True Range calculation.
- 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 / Transfer Support. Bid-ask spread dynamics in commodity wrappers.
Next: Module 8 — Low-Timeframe Trading Lab (Tick to M15) · Core: Module 7 — Frequency & Feasibility