Module 7 — Scalping/Intraday Frequency & Feasibility
Part III · Intraday Design, Alpha & Playbooks · Priority 🎯 Core Status: Draft v0.2 · Scope: commodity ETFs/ETPs + BTC/ETH spot & linear perps · Horizon: M1/M5 (M15 where appropriate), same-session flat Prerequisites: M5, M6, M22, M23
Overview
Start every frequency decision with the venue and the price you can actually trade. Never start with an indicator.
A commodity ETP trades during U.S. regular hours. Its market price can drift away from its NAV, and you pay a bid-ask spread on every turn SEC ETF bulletin. A futures-based commodity pool rolls contracts continuously. When the futures curve slopes, performance diverges from spot Fidelity on contango/backwardation. A physical trust like GLD holds metal and publishes holdings daily SPDR Gold Shares (GLD). Meanwhile, a BTC or ETH linear perpetual never expires. It exchanges funding payments between longs and shorts on an exchange-specific schedule that you must declare before trading Coinbase perpetual funding.
Our core hypothesis is narrow: at M1, M5, and M15, the ratio of executable move to all-in cost decides feasibility before any alpha signal matters.
The economics are straightforward:
- Transaction costs are fixed per trade. You pay the spread and exchange fees on every entry and exit.
- Expected price moves grow with horizon. An M15 bar covers roughly three to four times more ground than an M1 bar ($ATR \propto \sqrt{\Delta t}$).
- The cost share falls as you step slower. Stepping out from M1 to M5 or M15 widens your gross profit target much faster than it widens the spread.
Evidence status: hypothesis, mechanics-supported. Venue and wrapper mechanics explain why costs behave this way. They do not prove that an intraday edge exists after costs. You must audit net expectancy empirically in your specific lane.
The primary pitfall is the cost mirage. Backtests that fill at mid-price, ignore timestamped spread data, or assume favorable fills at bar extremes create an illusion of profitability. That gross profit vanishes once real-world bid-ask spreads are deducted. This module replaces that mirage with an honest, spread-deducted, same-session audit.
💡 The Wage vs. Toll Analogy: Think of trading frequency as a wage-to-toll ratio. The bar’s ATR is the gross wage the market pays you for taking risk. The spread is the mandatory toll the broker collects at the turnstile. At M1, you pay a $1.00 toll to earn a $1.20 wage. At M15, you pay the same $1.00 toll, but the wage is $4.50.
📌 Data Contract: This module operates strictly on OHLCV + spread data. We assume no order book, tick data, or partial fills. Execution occurs at the open of bar
t+1following a signal on the close of bart. Spreads are deducted per round trip. Completed H1/H4/D1 bars serve as causal context only. No position is held overnight.
How It Works
Evaluating frequency feasibility requires three components operating on the same clock and calendar.
1. Measure the Gross Wage (ATR)
How much does the market actually move at this horizon? We use ATR (Average True Range) as our baseline yardstick. It measures the full trading range of completed bars including gaps. An M1 ATR represents the average gross wage paid per minute. An M15 ATR is three to four times larger because volatility scales with the square root of time.
2. Measure the Toll (Spread & Fees)
What does it cost to collect that wage? Under our OHLCV + spread contract, round-trip cost equals the observed spread at entry and exit plus stressed fees and slippage from M22. We track two decisive ratios:
- Spread-to-ATR:
Spread ÷ ATR. This measures trading cost as a percentage of a normal bar. - Cost-to-Target:
All-in Cost ÷ Profit Target. This measures cost as a percentage of your intended win.
3. Measure the Tradable Hours (Session Atlas)
When is the market actually cheap and active enough to trade? Trading during illiquid hours destroys capital. A U.S. commodity ETP trades 6.5 hours during Regular Trading Hours (RTH). A crypto perpetual trades 24/7, but requires an explicit synthetic session (e.g., UTC 00:00–23:50) with a mandatory forced-flatten timestamp.
Figure: The feasibility triage pipeline. Cost gates filter out unviable horizons before any compute is spent on strategy rules.
flowchart TD
bars["OHLCV + spread<br/>M1/M5/M15 per venue"] --> atr["Compute ATR<br/>per timeframe"]
bars --> spread["Observed spread<br/>timestamped per bar"]
bars --> clock["Session clock<br/>ETF RTH vs UTC synthetic"]
atr --> ratio1["Spread-to-ATR<br/>cost vs normal bar"]
spread --> ratio1
atr --> ratio2["Cost-to-target<br/>cost vs intended win"]
spread --> ratio2
clock --> atlas["Hour/minute atlas<br/>spread/ATR/volatility"]
ratio1 --> gate1{"Spread-to-ATR<br/>below ceiling?"}
ratio2 --> gate2{"Cost-to-target<br/>below ceiling?"}
atlas --> gate1
atlas --> gate2
gate1 -->|"no"| reject["Reject horizon<br/>step slower or fewer hours"]
gate2 -->|"no"| reject
gate1 -->|"yes"| count["Opportunity count<br/>bars passing gates per session"]
gate2 -->|"yes"| count
count --> decision{"Enough same-session<br/>opportunities?"}
decision -->|"yes"| viable["Horizon viable<br/>carry to honest backtest"]
decision -->|"no"| reject
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 bars,clock data
class atr,spread,ratio1,ratio2,atlas,count process
class gate1,gate2,decision decision
class reject risk
class viable okThe Step-by-Step Triage Process
- Calculate completed-bar ATR on M1, M5, and M15.
- Align observed timestamped spreads to each bar.
- Build an hourly atlas of median spread, median ATR, and realized range.
- Compute Spread-to-ATR and Cost-to-Target across each hour.
- Apply cost ceilings: Reject any timeframe or session window where cost exceeds limits.
- Count surviving bars: Verify that enough tradable opportunities remain per session to ensure statistical validity.
⚠️ Pitfall: Never pool 24-hour crypto data into a single average. Inactive overnight hours have wide spreads and tiny bars that distort the median. Always segment crypto by UTC hour before evaluating feasibility.
Strategy Rules
The rules in this module are feasibility filters and execution gates, not predictive alpha signals. Any alpha strategy tested later inherits these constraints unchanged.
Standard Feasibility Gate Set
| Gate | Definition | Default Ceiling | Impact of Breach |
|---|---|---|---|
| Spread-to-ATR | Observed Spread ÷ Bar ATR |
≤ 15% – 20% | A normal bar is too short to cover trading friction. |
| Cost-to-Target | All-in Cost ÷ Intended Profit Target |
≤ 10% | Winners start too far underwater to maintain positive expectancy. |
| Spread Percentile | Current Spread vs Trailing Session Percentile |
≤ p75 | The tape is currently illiquid; stand down. |
| Opportunity Floor | Eligible bars passing cost gates per session | ≥ 40% of session (or ≥ 3–5 trades/day) | Sample size is too small for statistical significance. |
| Forced Session Flatten | Maximum hold time in bars and session end time | Flatten at or before session close | Zero overnight risk; eliminate gap and funding exposure. |
🔧 Pipeline Implementation: These ceilings are project-card parameters, not hardcoded constants. You must declare them before running a scan. Adjusting a ceiling after seeing backtest results constitutes a new trial and must be logged in the trial ledger M5.
Higher-Timeframe (HTF) Conditioning
Completed H1, H4, or D1 bars can act as causal permission gates (e.g., only take M5 longs when the completed H1 close is above its 20 EMA).
- Release Contract: An HTF feature is only available after its bar closes.
- Execution Timing: A signal on the close of bar
tcan only execute at the open of bart+1. - Session Boundary: Slower HTF signals never delay a forced session flatten.
📌 Transfer Evidence Note: Heuristics borrowed from FX or equity index futures are transfer evidence only. Their microstructure differs fundamentally from physically backed commodity ETPs, futures-based rolling pools Invesco PDBC, and crypto perpetuals with variable funding Coinbase perpetual funding. Use transfer literature to establish prior ranges, never as proof of local profitability.
Building It In Python
Below is a production-ready Polars implementation. It assumes load_market_data(project_card) provides a timezone-aware DataFrame containing open, high, low, close, volume, spread.
1. Intuition: Calculate Completed-Bar ATR
We compute Average True Range exclusively from completed bars. True Range measures the maximum price excursion from the previous close.
# ATR calculation from completed bars only
# Q: How tall is a normal bar on this venue?
import polars as pl
def atr_from_ohlc(frame: pl.DataFrame, period: int = 14) -> pl.Series:
prev_close = frame["close"].shift(1)
tr = pl.max_horizontal([
frame["high"] - frame["low"],
(frame["high"] - prev_close).abs(),
(frame["low"] - prev_close).abs(),
])
return tr.ewm_mean(span=period, adjust=False).alias(f"atr_{period}")
# Reference: Standard True Range formula (Wilder, 1978)
What this means for your P&L: ATR defines the market’s gross wage. If ATR is $0.10 and round-trip spread is $0.03, the market is offering you 10 cents of volatility while charging you 3 cents to participate.
2. Intuition: Compute Decisive Feasibility Ratios
Next, we calculate the Spread-to-ATR and Cost-to-Target ratios per bar.
# Compute feasibility ratios per bar
# Q: Does the expected move justify the transaction toll?
def compute_feasibility_ratios(frame: pl.DataFrame, atr_col: str = "atr_14", target_mult: float = 1.0) -> pl.DataFrame:
return frame.with_columns([
(pl.col("spread") / pl.col(atr_col)).alias("spread_to_atr"),
(pl.col("spread") / (target_mult * pl.col(atr_col))).alias("cost_to_target"),
])
What this means for your P&L: If spread_to_atr exceeds 20%, you are giving away a fifth of every standard bar just to enter and exit. Your strategy must be unrealistically accurate to break even.
3. Intuition: Run the Multi-Timeframe Scan
We evaluate M1, M5, and M15 bars side by side against our preregistered cost ceilings.
# Multi-timeframe feasibility scan
# Q: Which timeframes survive our cost and opportunity filters?
def scan_timeframe_feasibility(frame_m1: pl.DataFrame, ceilings: dict = None) -> pl.DataFrame:
ceilings = ceilings or {"spread_to_atr": 0.15, "cost_to_target": 0.10}
results = []
# Scan M1, M5, and M15
for tf, every in [("M1", "1m"), ("M5", "5m"), ("M15", "15m")]:
resampled = (
frame_m1.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.sum("volume").alias("volume"),
pl.mean("spread").alias("spread"),
])
.sort("timestamp")
)
resampled = resampled.with_columns(atr_from_ohlc(resampled, 14))
resampled = compute_feasibility_ratios(resampled, "atr_14", target_mult=0.9)
# Filter by cost gates
passed = resampled.filter(
(pl.col("spread_to_atr") <= ceilings["spread_to_atr"]) &
(pl.col("cost_to_target") <= ceilings["cost_to_target"])
)
results.append({
"timeframe": tf,
"atr_p50": resampled["atr_14"].median(),
"spread_p50": resampled["spread"].median(),
"spread_to_atr_p50": resampled["spread_to_atr"].median(),
"cost_to_target_p50": resampled["cost_to_target"].median(),
"total_bars": resampled.height,
"passed_bars": passed.height,
"pass_rate": passed.height / max(1, resampled.height),
})
return pl.DataFrame(results)
4. Intuition: Build the Intraday Cost Atlas
We break down spreads and volatility by hour to locate optimal trading windows.
# Intraday hour atlas
# Q: Which specific hours are cheap and active?
def build_hourly_atlas(frame: pl.DataFrame, atr_col: str = "atr_14") -> 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(atr_col).median().alias("atr_p50"),
pl.col("spread_to_atr").median().alias("s2atr_p50"),
(pl.col("spread_to_atr") <= 0.15).mean().alias("pass_rate_15pct"),
])
.sort("hour")
)
Hand-Checkable Numeric Example
Suppose a gold ETP (e.g., GLD) and a BTC perpetual present the following median M5 statistics during their respective trading sessions (target = $0.9 \times \text{ATR}$):
| Asset & Session | M5 ATR | M5 Spread | Target ($0.9 \times \text{ATR}$) | Spread / ATR | Cost / Target | Feasibility Verdict |
|---|---|---|---|---|---|---|
| Gold ETP (RTH M5) | $0.18 | $0.030 | $0.162 | 16.7% | 18.5% | ❌ FAILS (Too expensive per bar) |
| Gold ETP (RTH M15) | $0.34 | $0.030 | $0.306 | 8.8% | 9.8% | ✅ PASSES (Move outpaces spread) |
| BTC Perp (UTC M5) | $42.00 | $2.50 | $37.80 | 6.0% | 6.6% | ✅ PASSES (Move easily pays toll) |
What this means for your P&L: At M5, trading the gold ETP is mathematically unviable under these cost ceilings. Stepping out to M15 expands the ATR from $0.18 to $0.34 while the spread remains $0.03. That simple shift cuts the cost toll in half and turns a failing horizon into a viable one.
Testing It Honestly
An honest test reflects what you would trust with real capital. We apply strict execution and data rules.
1. The Data & Causality Contract
- Completed Bars Only: Indicators are calculated strictly on closed bars.
- Execution Timing: A signal generated on the close of bar
texecutes at the open of bart+1. Never simulate fills at the signal bar’s close. - Timestamp Alignment: HTF features are joined using
as_oftimestamps reflecting when the source bar closed, including processing lag.
2. Full Cost Deduction
- Deduct Observed Spreads: Every simulated fill deducts the timestamped spread plus fee and slippage stress from M22.
- Unit Verification: Validate whether your spread column represents full-spread or half-spread, and price units or basis points. Deducting a half-spread as a full spread doubles transaction cost; treating basis points as dollars invalidates the test.
3. Conservative Bar-Path Resolution (Ambiguous Bars)
An OHLC bar proves only that price touched the high and low. It cannot prove which came first ohlcv.io on bar resolution.
- If a single bar touches both your stop loss and profit target:
- Rule: Assume the stop was hit first (worst-case assumption), or exclude the trade and report the ambiguous share.
- A backtest whose profitability depends on winning ambiguous bars is an illusion.
# Conservative exit resolver for ambiguous bars
def resolve_bar_exit(side: str, bar_high: float, bar_low: float, stop_loss: float, take_profit: float) -> str:
hit_stop = (bar_low <= stop_loss) if side == "long" else (bar_high >= stop_loss)
hit_target = (bar_high >= take_profit) if side == "long" else (bar_low <= take_profit)
if hit_stop and hit_target:
return "ambiguous_stop_first" # Always book the loss
if hit_stop:
return "stop"
if hit_target:
return "target"
return "none"
4. Mandatory Same-Session Flatten
- Every open trade must be closed at or before the final eligible bar of the session.
- ETP positions close at the RTH boundary (16:00 ET).
- Crypto perpetual positions close at the declared synthetic boundary (e.g., 23:50 UTC).
- No position carries overnight. Slower HTF signals cannot postpone a forced flatten.
Variants & Extensions
All variants preserve the core data and execution contract.
| Variant | What Changes | Practical Purpose | Trade-off |
|---|---|---|---|
| M1 → M5 → M15 Step-Out | Coarsen the trading bar | Rescues horizons where M1 Spread-to-ATR is prohibitive | Fewer trades; lower frequency |
| Session Window Slicing | Restrict trading to peak liquidity hours | Eliminates high-spread, low-ATR periods | Smaller eligible sample size |
| HTF Causal Filter | Require H1/H4 trend alignment | Filters out choppy, low-expectancy regimes | Reduces opportunity count |
| Spread Percentile Gate | Block trades above rolling p75 spread | Protects against sudden liquidity droughts | Adds lookback conditioning lag |
| Cost-to-Target Ladder | Test targets from $0.7\times$ to $1.5\times$ ATR | Discovers minimum viable profit target | Increases search trials; requires ledger logging |
📌 Transfer Evidence Note: Documented intraday patterns in foreign exchange or equity index futures represent transfer evidence. Do not assume thresholds transfer directly to commodity trusts or crypto perpetuals. Re-estimate all cost ceilings on your target lane.
Hands-On Project
Deliverable: docs/research/m7_feasibility_frontier.md and a reproducible notebook at notebooks/m7_feasibility_scan.ipynb.
Project Card — M7 Feasibility Frontier (v1.0)
| Area | Required Pre-Registration |
|---|---|
| Identity | Commodity ETP lane: One physical trust (e.g., GLD) and one futures-based pool (e.g., PDBC); Crypto lane: BTC spot and one linear perpetual on an approved CEX; record data retrieval timestamp and price basis (mid vs. last). |
| Horizon | Timeframes: M1, M5, M15; maximum hold duration; mandatory same-session forced flatten. |
| Clock | ETP: RTH 09:30–16:00 ET; Crypto: UTC 00:00–23:50 synthetic session (forced flatten at 23:50 UTC). |
| Execution | Signal on close of bar t → fill at open of bar t+1; deduct timestamped spread; ambiguous bars resolve stop-first; gaps fill at next open. |
| Costs | Full spread deducted per round trip plus exchange fee and slippage stress; import p50 and p90 spread surfaces from M22. |
| Information | Completed-bar HTF release timestamps; point-in-time instrument metadata. |
| Risk | Fixed stop/target multiples; max session trade cap; per-day loss limit per M23. |
| Validation | Purged rolling walk-forward cross-validation; embargo period; separate holdout test set. |
| Acceptance | Clear ceilings: Spread-to-ATR ≤ 15%, Cost-to-Target ≤ 10%, pass rate ≥ 40%; ambiguous trade share < 5%. |
Step-by-Step Execution Plan
- Declare the Project Card: Freeze all parameters, price bases, and spread units in writing before touching data.
- Run Timeframe Scans: Compute median ATR, median spread, Spread-to-ATR, and Cost-to-Target across M1, M5, and M15 for each asset.
- Generate Hourly Atlases: Map spreads, volatility, and pass rates by hour of the day.
- Apply Ceilings & Triage: Identify which asset-timeframe combinations clear all cost gates.
- Run Conservative Walk-Forward Replay: For surviving horizons, run an honest walk-forward test with next-bar-open fills and stop-first ambiguous resolution.
- Publish Decision Memo: Document whether each horizon is accepted, revised (e.g., restricted hours), or rejected.
Key Takeaways
- Costs decide feasibility before signals do: Spread-to-ATR and Cost-to-Target determine whether a timeframe is tradable before testing any indicators.
- The wage must cover the toll: M1 pays a tiny wage for a full-size toll. Stepping out to M5 or M15 expands the wage ($ATR \propto \sqrt{\Delta t}$) while keeping the toll constant.
- Never compare incompatible clocks: ETP RTH and crypto 24/7 are fundamentally different calendars. Segment crypto into an explicit UTC synthetic session with forced flattening.
- Build the hourly atlas first: An hourly cost and volatility atlas is the cheapest diagnostic you can run. It tells you which hours to skip before searching for alpha.
- Enforce honest execution: Fill at next-bar open, deduct full spreads, resolve ambiguous bars stop-first, and flatten every position before the session closes.
- A cheap horizon with no trades is useless: Opportunity count is a core feasibility gate. If cost filters remove 90% of your bars, the sample size is insufficient.
References
- U.S. Securities and Exchange Commission — Exchange-Traded Funds (ETFs) Investor Bulletin — https://www.sec.gov/investor/alerts/etfs.pdf — Mechanics. ETF share trading, NAV deviations, authorized participant creation/redemption.
- Fidelity — Commodity ETFs — Contango and Backwardation — https://www.fidelity.com/learning-center/investment-products/etf/commodity-etfs-contango-backwardation — Mechanics. Roll yield mechanics and divergence from spot in futures-based pools.
- SSGA — SPDR Gold Shares (GLD) Product Specifications — https://www.ssga.com/us/en/intermediary/etfs/spdr-gold-shares-gld — Mechanics. Physical trust structure, daily holdings disclosures, and NAV calculations.
- 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 roll methodology in futures-based commodity funds.
- Coinbase — Perpetual Funding Rate Documentation — https://help.coinbase.com/en/derivatives/perpetual-style-futures/funding-rate — Mechanics. Cash-flow exchange mechanism between longs and shorts in perpetual futures.
- Investopedia — Average True Range (ATR) Definition — https://www.investopedia.com/terms/a/atr.asp — Mechanics / Transfer Support. Foundation for bar volatility measurement.
- 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 and wrapper liquidity constraints.
Next: Module 8 — Low-Timeframe Trading Lab (Tick to M15) · Companion: Module 7 Strategies — Feasibility Experiments