The Learning Library
Contents

Module 12 — Intraday Relative Value

Part III · Intraday Design, Alpha & Playbooks · Priority ⭐ Recommended Status: Draft v0.2 · Scope: commodity ETFs/ETPs + BTC/ETH spot & linear perps · Horizon: M1/M5 (M15 where appropriate), same-session flat Prerequisites: M2, M5, M6, M7, M8, M9, M22, M23


Overview

You start this module with the venue and the price you can actually trade, not with a correlation number.

A commodity ETP share trades in U.S. regular hours at a market price that drifts from its published NAV. Creation and redemption happen exclusively in large blocks through authorized participants SEC ETF bulletin. Physical trusts like GLD hold allocated bullion SPDR Gold Shares (GLD), while futures pools like PDBC roll contracts across dynamic curves where contango imposes drag and backwardation adds yield Invesco PDBC overview.

On the crypto lane, BTC and ETH linear perpetuals exchange periodic funding payments between longs and shorts to tether perpetual contracts to spot prices Coinbase perpetual funding and Coinbase on funding rates. The spread between perpetual and spot—the basis—reflects structural demand: perpetuals trade at a premium when leveraged longs pay for exposure and at a discount during liquidation cascades Sharpe.ai futures basis and BloFin spot-perp basis.

The preregistered hypothesis for this module is specific: intraday dislocations between economically linked pairs—commodity ETP spreads, BTC/ETH residuals, or same-venue spot-perp bases—close toward rolling equilibrium often enough to carry net expectancy after paying synchronized two-leg spreads, exchange fees, and conservative bar execution.

The economic intuition is grounded in cross-asset order flow:

  • Flow imbalances displace linked assets. Large institutional allocations into GLD push gold without immediately moving silver; index rebalancing impacts broad commodity pools unevenly; rotational crypto flows lift BTC before ETH.
  • Arbitrageurs restore equilibrium. As dislocations widen, market makers and statistical arbitrageurs step in, selling the overextended asset and buying the laggard.
  • Funding rates enforce convergence. On perpetuals, extreme basis spreads generate heavy funding transfer costs that incentivize arbitrageurs to collapse the premium BloFin spot-perp basis.

Who sits on the other side of your fill?

  1. The unhedged macro allocator trading single-asset mandates.
  2. The levered retail trader paying wide perpetual premiums for directional leverage.
  3. The index rebalancer mechanically executing basket constituents regardless of cross-asset valuation.

Evidence status: hypothesis, mechanics-supported. Wrapper structures, roll mechanics, funding schedules, and basis relationships are documented facts. However, whether any intraday spread strategy captures net alpha after double-leg spreads remains an empirical question answered only by disciplined replay. Note that while theoretical cointegration is widely assumed, daily empirical tests on BTC/ETH often fail to reject non-stationarity (ADF -2.11) BTC/ETH cointegration ADF -2.11—meaning intraday stationarity must be continuously audited.

The primary failure mode is the broken leash. A hedge ratio drifts, an economic relationship dissolves under fundamental divergence, and a supposedly market-neutral pair becomes two unhedged directional losses. Crucially, every relative-value trade pays a double toll (spreads on both legs), meaning the price dislocation must be substantially wider to achieve profitability.

💡 The Elastic Leash & Double Toll: Think of relative-value trading as two dogs on an elastic leash attached to the same owner (GLD vs. SLV, or BTC spot vs. BTC perp). When one dog lunges ahead, the leash stretches (high z-score). You bet that the tension pulls them back together. Crucially, you pay a double toll (spreads and fees on both legs), so the stretch must be twice as wide before you open your wallet.

📌 Data Contract Convention: This module operates strictly on two synchronized OHLCV + observed spread series. Decisions form on completed bar t and execute at the open of bar t+1 simultaneously across both legs. Spreads are deducted on both legs on entry and exit. Higher-timeframe bars (H1/D1) serve purely as causal context gates. All positions flatten before the session close.


How It Works

Intraday relative value consists of four interconnected steps:

  1. Economic Linkage: Establishing an intuitive economic tether before running statistics (e.g., physical gold vs. physical silver, or BTC spot vs. BTC perp).
  2. Causal Rolling Hedge Ratio: Estimating the dynamic relationship $\beta_t$ using rolling OLS on completed bars ($y_t = \beta_t x_t + \epsilon_t$), ensuring zero look-ahead bias.
  3. Standardized Residual Z-Score: Constructing the spread $S_t = y_t - \beta_t x_t$ and standardizing it into a z-score: $z_t = (S_t - \mu_{S, t}) / \sigma_{S, t}$.
  4. Link-Health & Two-Leg Cost Gating: Verifying that rolling correlation exceeds minimum thresholds, ADF confirms residual stationarity, and the expected convergence profit exceeds twice the combined bid-ask spread.

Figure: The M12 relative-value engine. Every trade requires synchronized two-leg execution, active link-health monitoring, and pre-trade cost clearance.

flowchart TD
    bars["OHLCV + spread per leg<br/>M1/M5/M15 completed bars<br/>two synchronized series"]
    clock["Session clock<br/>ETP RTH vs UTC synthetic<br/>release & flatten rules"]
    pair{"Pair construction<br/>ETF pair / BTC-ETH /<br/>same-venue spot-perp"}
    hedge["Rolling hedge ratio<br/>OLS on trailing closes<br/>spread = y - beta * x"]
    diag{"Link intact?<br/>rolling corr / EG p /<br/>ADF / half-life stable?"}
    zcalc["Residual & z-score<br/>rolling mean & sigma<br/>on the spread itself"]
    gates{"Cost gates per bar<br/>spread/ATR & cost/target<br/>below ceiling?"}
    htf{"Completed H1/H4/D1<br/>bias & release check"}
    band{"Z beyond entry band?<br/>|z| >= 2 typical"}
    exec["Arm both legs<br/>signal on t -> opens t+1<br/>synchronized, spread deducted"]
    ambig{"Bar touches both<br/>stop and target?"}
    manage["Manage to target<br/>z near zero or<br/>time-stop or breakdown"]
    kill{"Breakdown detected?<br/>or session end?"}
    flatten["Forced flatten both legs<br/>at session boundary<br/>gap at next open"]
    block["Stand aside<br/>log & count<br/>pair stays monitored"]

    bars --> pair
    clock --> pair
    pair --> hedge
    hedge --> diag
    diag -->|"no: link broke"| block
    diag -->|"yes"| zcalc
    zcalc --> htf
    htf -->|"not released<br/>or regime fails"| block
    htf -->|"released & ok"| gates
    gates -->|"no"| block
    gates -->|"yes"| band
    band -->|"no"| block
    band -->|"yes"| exec
    exec --> ambig
    ambig -->|"both touched"| manage
    ambig -->|"clean"| manage
    manage --> kill
    kill -->|"flatten now"| flatten
    kill -->|"not yet"| manage

    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 data
    class pair,hedge,zcalc,exec,manage,flatten process
    class diag,gates,htf,band,ambig,kill decision
    class block risk

Step-by-Step Engine Walkthrough

  1. Synchronized Ingestion: Ingest completed M5 bars for both assets simultaneously. If either series contains a missing bar or halt, the entire pair stands aside.
  2. Rolling Hedge Calculation: Compute rolling OLS slope $\beta_t$ over the trailing window $W_{\beta}$ (e.g., 80 bars).
  3. Residual & Z-Score Computation: Generate spread $S_t = y_t - \beta_t x_t$ and calculate its rolling mean $\mu_t$ and standard deviation $\sigma_t$ over $W_z$ (e.g., 60 bars).
  4. Link-Health Verification: Confirm that rolling correlation $r_t \ge 0.65$ and ADF confirms residual stationarity.
  5. Two-Leg Cost Triage: Verify that combined spread costs sit below $12%$ of the expected z-score target.
  6. Synchronized Entry: When $|z_t| \ge 2.0$, enter both legs at open[t+1], going long the undervalued asset and short $\beta_t$ units of the overvalued asset.
  7. Convergence & Breakdown Management: Exit when $z_t$ converges to $\pm 0.30$, hits a hard stop at $|z_t| \ge 3.5$, or when correlation breaks down ($r_t < 0.50$).
  8. Hard Session Flatten: Liquidate both legs simultaneously at the session cutoff bar.

Strategy Rules

All strategies inherit our strict relative-value execution contract:

Replay Execution Contract

Area Contract Specification Rationale for Intraday Trading
Price Basis & Synchronicity Mid vs. last defined per leg; synchronized timestamps mandatory Prevents artificial backtest fills from non-simultaneous quotes
Session Clock Fixed RTH window for ETPs; synthetic UTC window for crypto with hard flatten Eliminates overnight carry and uncontrolled structural divergence
Execution Timing Signal on close[t] $\rightarrow$ synchronized fills at open[t+1] on both legs Eliminates legging-in look-ahead bias Saral next-bar-open
Bar Ambiguity Adverse stop-first resolution if spread touches stop and target Guarantees conservative, honest backtest accounting ohlcv.io bar resolution
Two-Leg Cost Hurdles Combined spread friction $\le 12%$ of intended target distance Rejects spreads where double transaction costs consume edge
Breakdown Kill-Switch Immediate exit if rolling correlation flips sign or drops below floor Protects capital when the fundamental linkage dissolves
Position Sizing Beta-weighted dollar neutrality based on ATR stop distance Equalizes risk exposure across both legs of the spread
Gate Metric Mathematical Definition Default Ceiling / Floor Action on Breach
Leg Spread-to-ATR $\text{Spread}{i, t} / \text{ATR}{i, 14, t}$ $\le 0.15 - 0.20$ per leg Stand aside: single-leg friction is excessive
Combined Cost-to-Target $(\text{Spread}_y + \beta \text{Spread}_x + \text{Fees}) / \text{Target}$ $\le 0.10 - 0.12$ Stand aside: double toll consumes $>12%$ of profit
Rolling Correlation $\text{Corr}(R_y, R_x)$ over trailing 60 bars $\ge 0.65$ Stand aside: correlation is too weak to ensure tethering
Cointegration / ADF Augmented Dickey-Fuller p-value on residual $p \le 0.05$ Stand aside: spread series is non-stationary
Half-Life Alignment Ornstein-Uhlenbeck half-life $\tau$ on spread $T_{\text{max}} \approx 1.5 - 2.0\tau$ Stand aside if half-life is infinite or unstable

Core Relative-Value Families

Family A: Commodity-ETP Pair Spread (GLD vs. SLV / PDBC vs. DBC)

  • Pair Selection: GLD vs. SLV (Precious Metals) or PDBC vs. DBC (Broad Commodities).
  • Hedge Ratio: Rolling OLS slope $\beta_t$ over trailing 80 completed M5 bars.
  • Entry Trigger: Long spread when $z_t \le -2.0$; Short spread when $z_t \ge +2.0$.
  • Exit Target: Spread converges to $|z_t| \le 0.30$ or crosses rolling mean $\mu_t$.
  • Stop Loss: Dislocation widens to $|z_t| \ge 3.50$ or spread moves $> 2.0 \times \text{ATR}_{\text{spread}}$.
  • Breakdown Stop: Immediate liquidation if rolling correlation drops below $0.50$.
  • Session Flatten: Unconditional exit of both legs at 15:58 ET.

Family B: BTC/ETH Cross-Asset Residual (Crypto Spot/Perp)

  • Hedge Ratio: Rolling OLS slope of ETH on BTC over 60 completed M5 bars.
  • Residual Model: $S_t = \text{ETH}_t - \beta_t \text{BTC}_t$.
  • Mandatory Stationarity Gate: Requires ADF $p \le 0.05$ and correlation $r_t \ge 0.70$ before arming signals.
  • Exits: Target $|z_t| \le 0.25$; Stop at $|z_t| \ge 3.20$; Time stop of 16 bars (80 minutes).

Family C: Same-Venue Spot-Perp Basis (BTC Spot vs. BTC Perp)

  • Basis Metric: $\text{Basis}_t = \text{Perp_Close}_t - \text{Spot_Close}_t$ BloFin spot-perp basis.
  • Standardization: $z_t = (\text{Basis}t - \mu{\text{Basis}, t}) / \sigma_{\text{Basis}, t}$.
  • Entry Trigger: Fade extreme basis when $|z_t| \ge 2.20$ (e.g., short perp + long spot when perp is overpriced).
  • Funding Rule: Stand aside within 30 minutes of funding settlements unless funding is explicitly booked.
  • Exits: Target basis convergence to mean; hard flatten at 23:50 UTC.

Building It In Python

Below is the complete, modular Polars and NumPy implementation of the relative-value engine.

import polars as pl
import numpy as np

def calculate_rolling_ols(
    y: np.ndarray, x: np.ndarray, window: int = 80
) -> np.ndarray:
    """Calculate causal rolling OLS hedge ratio beta through the origin."""
    n = len(y)
    betas = np.full(n, np.nan)
    for t in range(window - 1, n):
        y_win = y[t - window + 1 : t + 1]
        x_win = x[t - window + 1 : t + 1]
        denom = np.sum(x_win * x_win)
        if denom > 1e-12:
            betas[t] = np.sum(x_win * y_win) / denom
    return betas

def build_spread_zscore(
    df_y: pl.DataFrame, df_x: pl.DataFrame, beta_window: int = 80, z_window: int = 60
) -> pl.DataFrame:
    """Construct synchronized spread series and rolling z-scores."""
    y_close = df_y["close"].to_numpy()
    x_close = df_x["close"].to_numpy()

    betas = calculate_rolling_ols(y_close, x_close, window=beta_window)
    spread = y_close - betas * x_close

    # Calculate rolling mean and standard deviation of the spread
    n = len(spread)
    z_scores = np.full(n, np.nan)
    for t in range(beta_window + z_window - 1, n):
        s_win = spread[t - z_window + 1 : t + 1]
        valid = s_win[~np.isnan(s_win)]
        if len(valid) >= z_window:
            mu = np.mean(valid)
            sigma = np.std(valid, ddof=1)
            if sigma > 1e-12:
                z_scores[t] = (spread[t] - mu) / sigma

    return pl.DataFrame({
        "timestamp": df_y["timestamp"],
        "y_close": y_close,
        "x_close": x_close,
        "beta": betas,
        "spread": spread,
        "z_score": z_scores,
        "y_spread": df_y["spread"],
        "x_spread": df_x["spread"],
    })

def apply_two_leg_cost_gates(
    frame: pl.DataFrame,
    target_sigma_mult: float = 1.70,
    max_cost_to_target: float = 0.12,
) -> pl.DataFrame:
    """Enforce two-leg combined cost hurdles against intended convergence target."""
    combined_spread = pl.col("y_spread") + (pl.col("beta").abs() * pl.col("x_spread"))
    spread_std = pl.col("spread").rolling_std(60)
    target_dist = spread_std * target_sigma_mult
    cost_to_target = combined_spread / target_dist

    pass_gate = cost_to_target <= max_cost_to_target

    return frame.with_columns([
        combined_spread.alias("combined_spread"),
        cost_to_target.alias("cost_to_target"),
        pass_gate.alias("cost_gate_pass"),
    ])

What This Means For Your P&L: The Double Toll Impact

Let us evaluate an identical relative-value setup across different spread regimes:

  • Setup: Asset Y = $100, Asset X = $50 ($\beta = 2.0$), Spread $\sigma = $0.50$, Target Convergence ($1.7\sigma$) = $0.85.
  • Target Profit per Trade: $0.85 per unit spread.
Market Condition Spread Leg Y Spread Leg X Combined Toll Cost / Target Gate Verdict Realized P&L Impact
Liquid RTH (GLD/SLV) $0.020 $0.015 $0.050 $5.9%$ ACCEPTED Low double toll leaves $>94%$ of alpha intact
Midday Lull (GLD/SLV) $0.060 $0.040 $0.140 $16.5%$ REJECTED Double toll consumes $>16%$ of expected convergence
BTC/ETH Spot (Active) $2.00 $0.50 ($\beta=0.06$) $2.03 $4.8%$ ACCEPTED Tight relative spreads ensure high net expectancy

Testing It Honestly

Honest relative-value testing requires strict adherence to our simulation standards:

  1. Synchronized Next-Open Fills: Signals at close[t] fill simultaneously at open[t+1] on both legs. Never model unsynchronized legging Saral next-bar-open.
  2. Two-Leg Cost Deduction: Always deduct the full observed bid-ask spread on both legs for entry and exit.
  3. Conservative Spread Ambiguity: If spread path touches stop and target on the same bar, record an adverse stop hit ohlcv.io bar resolution.
  4. Purged Walk-Forward Splits: Re-estimate rolling hedge ratios strictly inside training windows with 20-bar embargo buffers.
  5. Breakdown Sensitivity: Audit the speed at which the engine liquidates broken pairs when rolling correlation collapses.

Variants & Extensions

Variant Configuration Implementation Adjustment Primary Benefit Operational Trade-off
Kalman Filter Hedge Dynamic state-space beta tracking Smoothly adapts to gradual structural drift Sensitive to noise; requires parameter tuning
Fixed 1:1 Baseline Direct price ratio or difference Zero parameter estimation risk; ultra-simple Only viable for identical assets (GLD vs. IAU)
Funding-Adjusted Basis $\text{Basis}_t - \text{Expected_Funding}_t$ Captures pure structural mispricing Requires accurate forward funding predictions
Half-Life Scaled Holds Set $T_{\text{max}} = 1.5 \times \text{Half-Life}$ Aligns holding duration to empirical speed Prematurely closes slow-reverting winners

Hands-On Project

Deliverable: Build docs/research/m12_relative_value_lab.md and implement the complete pair trading engine in notebooks/m12_relative_value.ipynb.

Project Card Specification

  • Identity: GLD vs. SLV (ETP lane) and BTC Spot vs. BTC Perp (Crypto lane). Explicitly define price basis and spread units per leg.
  • Horizon & Clock: M5 decision bars. ETP: 09:30–16:00 ET (flatten at 15:58 ET). Crypto: 00:00–23:50 UTC (flatten at 23:50 UTC).
  • Execution Engine: Synchronized fills at open[t+1]. Full observed spreads deducted on both legs. Adverse stop-first resolution.
  • Cost Ceilings: Combined Cost-to-Target $\le 0.12$; Rolling Correlation $\ge 0.65$.
  • Validation: 5-fold purged walk-forward cross-validation.

Preregistered Rejection Triggers

  • Strategy fails to produce positive net expectancy after deducting two-leg observed spreads.
  • Residual series exhibits non-stationarity ($p > 0.05$ on ADF test).
  • Performance collapses under 90th-percentile spread stress.
  • Breakdown stop fails to protect capital during historical decorrelation shocks.

Key Takeaways

  • Relative Value is a Relationship Bet: You trade the spread, not directional drift. Active link-health monitoring is mandatory.
  • The Double Toll Governs Viability: Because you pay bid-ask spreads on both legs, cost-to-target hurdles must be strictly enforced.
  • Hedge Ratios Must Be Dynamic: Static historical betas subsidize backtests and cause catastrophic live losses.
  • Breakdown Kills Protect Capital: When economic correlation breaks down, liquidate the position immediately regardless of z-score.
  • Flatten Hard Daily: Eliminate overnight carry and unmodeled funding risks by flattening both legs before session close.

References