The Learning Library
Contents

Module 12 Companion — Intraday Relative Value Playbook

Part III · Intraday Design, Alpha & Playbooks · Companion to Module 12 — Intraday Relative Value Prerequisites: M2, M5, M6, M7, M8, M9, M22, M23


Overview

The core module established our unified relative-value contract: completed bars only, close-on-t signal to synchronized opens-on-t+1 on both legs, observed spread deducted per leg, ambiguous bars resolved adversely, and mandatory same-session flattens. This companion provides three concrete, reproducible statistical arbitrage experiments:

Strategy Card Spread Family Target Venues & Clocks Core Empirical Question
S1 — Commodity-ETF Pair Spread Rolling OLS y - beta*x + residual z (GLD vs. SLV / PDBC vs. DBC) Commodity ETP RTH (09:30–16:00 ET, flatten at 15:58 ET), M5 primary Does a volatility-scaled residual dislocation between two ETPs revert when the economic link is intact?
S2 — BTC/ETH Cross-Asset Residual Rolling BTC $\rightarrow$ ETH residual z on spot pairs Approved CEX Spot (00:00–23:50 UTC, flatten at 23:50 UTC), M5 primary Does the BTC-stripped ETH residual revert when rolling ADF confirms stationarity?
S3 — Same-Venue Spot-Perp Basis Basis perp - spot + basis z, funding-aware BTC/ETH Spot vs. Perp on same CEX (00:00–23:50 UTC), M5 primary Does an extreme spot-perp basis dislocation revert when funding acts as the tether?

💡 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 on both legs), so the stretch must be twice as wide before you open your wallet.

📌 Data Contract Convention: All strategies operate strictly on two synchronized OHLCV + observed spread series. No tick data, order-book depth, or partial fills are assumed. Signals generated at close[t] fill at open[t+1] simultaneously on both legs with full observed spreads deducted. Higher-timeframe bars (H1/D1) serve purely as causal context gates. All trades flatten before session close.


How It Works

Three relative-value spreads share a modular decision architecture and identical execution constraints:

  1. S1 (ETP Pair Spread): Synchronizes two ETP series (e.g., GLD and SLV). A rolling OLS regression ($W_{\beta} = 80$) dynamically calculates the hedge ratio $\beta_t$. The spread $S_t = y_t - \beta_t x_t$ is standardized into a z-score ($W_z = 60$). When $|z_t| \ge 2.0$ and rolling correlation $r_t \ge 0.65$, the engine enters a mean-reverting spread trade.
  2. S2 (BTC/ETH Residual): Strips BTC beta from ETH spot prices using rolling regression. Because crypto cross-asset relationships are episodic, S2 enforces a mandatory Augmented Dickey-Fuller (ADF) stationarity gate ($p \le 0.05$) before allowing entries BTC/ETH cointegration ADF -2.11.
  3. S3 (Same-Venue Basis): Trades the direct basis ($\text{Perp} - \text{Spot}$) for the same asset on a single CEX BloFin spot-perp basis. Extreme basis z-scores are faded toward zero, with strict stand-down rules during funding settlement windows.

All setups must pass two-leg combined cost gates (combined_spread / target <= 0.12) before execution.

Figure: Relative-value playbook execution architecture. S1 serves as the commodity baseline, S2 tests cross-crypto residuals, and S3 evaluates basis convergence.

flowchart TD
    data["OHLCV + spread per leg<br/>M5 completed bars<br/>synchronized pairs / same-venue spot+perp"] --> s1["S1 ETP Pair<br/>rolling OLS -> residual z"]
    data --> s2["S2 BTC/ETH Residual<br/>BTC->ETH hedge -> residual z"]
    data --> s3["S3 Spot-Perp Basis<br/>perp-spot -> basis z"]
    s1 -->|"frozen band & funding-aware"| ablate["Same-engine ablation<br/>pair vs 1:1 vs static beta<br/>vs cost-stress vs paper"]
    s2 --> ablate
    s3 --> ablate
    ablate --> decision{"Link-health lift +<br/>net lift +<br/>opportunity floor +<br/>ambiguous share?"}
    decision -->|"pass"| carry["Carry to paper<br/>as one-lane spread playbook"]
    decision -->|"revise"| narrow["Revise: tighten corr/ADF<br/>swap M5/M15<br/>or re-window hedge"]
    decision -->|"reject"| reject["Reject family<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 s1,s2,s3,ablate,narrow process
    class decision decision
    class reject risk
    class carry ok

Strategy Rules

Every strategy card adheres to the standard 9-point research template. S1 details the full baseline implementation; S2 and S3 specify structural deltas.

S1 — Commodity-ETP Pair Spread (Full Implementation)

1. Market, Timeframe, and Data Assumptions

  • Instruments: GLD vs. SLV or PDBC vs. DBC (NYSE Arca ETPs).
  • Timeframe: M5 primary decision bars.
  • Clock: ETP RTH 09:30–16:00 ET (forced flatten at 15:58 ET).
  • Data Basis: Synchronized OHLCV + observed spread per leg. Zero missing bars permitted.

2. Mechanics vs. Testable Hypothesis

Mechanics literature documents ETP creation/redemption and precious metals correlation SPDR Gold Shares (GLD) and Invesco PDBC overview.

  • Hypothesis: Entering mean-reverting spread positions when rolling OLS residual z-scores exceed $|z_t| \ge 2.0$, subject to active correlation ($r_t \ge 0.65$) and two-leg cost filters, yields positive net expectancy after paying spreads on both legs on purged walk-forward splits.

3. Required Technical Indicators

  • Hedge Ratio: Rolling OLS slope $\beta_t$ over 80 completed M5 bars.
  • Spread & Z-Score: $S_t = y_t - \beta_t x_t$; $z_t = (S_t - \mu_{S, 60}) / \sigma_{S, 60}$.
  • Diagnostics: Rolling 60-bar correlation, Engle-Granger cointegration p-value, and Ornstein-Uhlenbeck half-life.
  • Cost Ratio: Combined two-leg spread divided by intended convergence profit ($1.5\sigma$).

4. Causal HTF Context & Trigger

  • HTF Context: Completed H1 trend and volatility regime filters.
  • Trigger: Bar $t$ closes with $z_t \le -2.0$ (long spread: buy $y$, sell $\beta x$) or $z_t \ge +2.0$ (short spread).
  • Execution: Filled at open[t+1] simultaneously on both legs + half observed spread per leg.

5. Exits & Trade Management

  • Target: Convergence to $|z_t| \le 0.35$ or spread crossing rolling mean $\mu_t$.
  • Stop Loss: Dislocation widens to $|z_t| \ge 3.20$ or $2.0 \times \text{ATR}_{\text{spread}}$.
  • Breakdown Stop: Immediate liquidation if rolling correlation drops below $0.50$.
  • Time Stop: 20 bars (100 minutes); hard session flatten at 15:58 ET.

6. Cost Filters & Execution Assumptions

  • Pre-Trade Gate: Stand aside if combined spread cost exceeds $12%$ of expected convergence profit.
  • Path Resolution: Adverse stop-first resolution on ambiguous bars ohlcv.io bar resolution.

7. Position Sizing & Risk Limits

  • Dollar-neutral volatility sizing based on ATR stop distance across both legs M23.

8. Machine Learning Meta-Filter Extension

  • Role: Meta-filter predicting spread convergence probability.
  • Features: Dislocation z-score, rolling correlation, Engle-Granger p-value, combined spread ratio, and Ornstein-Uhlenbeck half-life.
  • Model: Logistic Regression baseline vs. shallow XGBoost classifier.
  • Validation: Purged rolling walk-forward with 20-bar embargo.

9. Failure Modes & Rejection Criteria

  • Reject if net expectancy is negative after deducting two-leg observed spreads.
  • Reject if performance collapses under 90th-percentile spread stress.
  • Reject if breakdown stops account for $>25%$ of all exits.

S2 — BTC/ETH Cross-Asset Residual (Delta Card)

1–4. Core Adjustments

  • Instruments: BTC/USDT Spot and ETH/USDT Spot on the same CEX.
  • Hedge Model: Dynamic rolling OLS slope of ETH on BTC over 60 completed M5 bars.
  • Mandatory Stationarity Filter: Entry prohibited unless Augmented Dickey-Fuller p-value $\le 0.05$ BTC/ETH cointegration ADF -2.11.

5–9. Risk & Validation

  • Exits: Target $|z_t| \le 0.25$; Stop $|z_t| \ge 2.80$; Time stop of 14 bars (70 minutes); hard flatten at 23:50 UTC.

S3 — Same-Venue Spot-Perp Basis (Delta Card)

1–4. Core Adjustments

  • Instruments: BTC Spot vs. BTC Linear Perpetual on the same CEX.
  • Basis Metric: $\text{Basis}_t = \text{Perp_Close}_t - \text{Spot_Close}_t$ BloFin spot-perp basis.
  • Trigger: Fade extreme basis dislocations ($|z_t| \ge 2.20$) targeting basis mean convergence.
  • Funding Window Gate: Block new entries within 30 minutes of funding timestamps unless funding is explicitly booked.

5–9. Risk & Validation

  • Exits: Target basis convergence to mean; hard flatten at 23:50 UTC.

Building It In Python

The executable script below demonstrates the complete S1 ETP Pair Spread pipeline in Polars:

import polars as pl
import numpy as np

def run_pair_spread_pipeline(
    df_y: pl.DataFrame,
    df_x: pl.DataFrame,
    beta_window: int = 80,
    z_window: int = 60,
    entry_z: float = 2.0,
    exit_z: float = 0.35,
    stop_z: float = 3.20,
    corr_floor: float = 0.65,
) -> pl.DataFrame:
    """Execute causal S1 Pair Spread logic with strict two-leg cost gating."""

    y = df_y["close"].to_numpy()
    x = df_x["close"].to_numpy()
    n = len(y)

    # 1. Compute Causal Rolling OLS Beta
    betas = np.full(n, np.nan)
    for t in range(beta_window - 1, n):
        y_win = y[t - beta_window + 1 : t + 1]
        x_win = x[t - beta_window + 1 : t + 1]
        denom = np.sum(x_win * x_win)
        if denom > 1e-12:
            betas[t] = np.sum(x_win * y_win) / denom

    spread = y - betas * x

    # 2. Compute Rolling Z-Score and Correlation
    z_scores = np.full(n, np.nan)
    corrs = 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 = s_win[~np.isnan(s_win)]
        if len(valid_s) >= z_window:
            mu = np.mean(valid_s)
            sigma = np.std(valid_s, ddof=1)
            if sigma > 1e-12:
                z_scores[t] = (spread[t] - mu) / sigma

        y_win = y[t - z_window + 1 : t + 1]
        x_win = x[t - z_window + 1 : t + 1]
        if len(y_win) == z_window:
            r = np.corrcoef(y_win, x_win)[0, 1]
            corrs[t] = r if not np.isnan(r) else 0.0

    res = pl.DataFrame({
        "timestamp": df_y["timestamp"],
        "y_close": y,
        "x_close": x,
        "beta": betas,
        "spread": spread,
        "z_score": z_scores,
        "rolling_corr": corrs,
        "y_spread": df_y["spread"],
        "x_spread": df_x["spread"],
    })

    # 3. Apply Two-Leg Cost Gates
    res = res.with_columns([
        (pl.col("y_spread") + pl.col("beta").abs() * pl.col("x_spread")).alias("combined_spread"),
        pl.col("spread").rolling_std(z_window).alias("spread_std"),
    ]).with_columns(
        (pl.col("combined_spread") / (pl.col("spread_std") * 1.50)).alias("cost_to_target")
    ).with_columns(
        (
            (pl.col("cost_to_target") <= 0.12)
            & (pl.col("rolling_corr") >= corr_floor)
        ).alias("gate_pass")
    )

    # 4. Generate Causal Trading Signals
    res = res.with_columns([
        (pl.col("gate_pass") & (pl.col("z_score") <= -entry_z)).alias("signal_long_spread"),
        (pl.col("gate_pass") & (pl.col("z_score") >= entry_z)).alias("signal_short_spread"),
    ])

    return res

What This Means For Your P&L: Strategy Comparison Table

Metric S1 ETP Pair Spread (GLD/SLV) S2 BTC/ETH Residual S3 Same-Venue Basis (BTC)
Trade Frequency 1–2 trades / session 2–3 trades / session 1–2 trades / session
Double Toll Friction Moderate (tight ETF spreads) High (crypto spot spread on 2 legs) Moderate (spot + perp taker fees)
Tether Strength High (physical commodity demand) Episodic (crypto market beta) High (enforced by perp funding)
Primary Failure Mode Structural metal divergence Cointegration breakdown Extreme basis liquidation cascade
Recommended Action Deploy during active RTH sessions Deploy strictly with active ADF gate Deploy during high-basis funding regimes

Testing It Honestly

Honest evaluation requires strict adherence to our causal validation protocol:

  1. Synchronized Next-Open Fills: Signals at close[t] fill simultaneously at open[t+1] on both legs Saral next-bar-open.
  2. Two-Leg Cost Deduction: Always deduct full observed spreads across both legs on entry and exit.
  3. Conservative Intrabar Exits: Spread barrier ambiguity is resolved stop-first (ambiguous_stop_first) ohlcv.io bar resolution.
  4. Purged Walk-Forward Splits: Re-estimate rolling hedge ratios strictly inside training windows with 20-bar embargo buffers.

Variants & Extensions

  • Kalman Filter Dynamic Hedging: Evaluate recursive Kalman state-space tracking against rolling OLS.
  • Fixed 1:1 Spread Baselines: Benchmark rolling beta models against simple price ratios for identical assets (GLD vs. IAU).
  • Funding-Adjusted Basis Models: Subtract expected forward funding from raw basis spreads.

Hands-On Project

Deliverable: Build docs/research/m12_relative_value_lab.md comparing S1, S2, and S3 across GLD/SLV and BTC spot/perp.

Implementation Checklist

  • Implement S1, S2, and S3 in Polars using strict synchronized next-open fills.
  • Enforce combined two-leg cost gates (cost_to_target <= 0.12).
  • Run 5-fold purged walk-forward cross-validation.
  • Evaluate performance under baseline and p90 spread stress.
  • Audit breakdown stops during historical decorrelation shocks.

Key Takeaways

  • Relative Value Trades the Spread: You are betting on cross-asset convergence, not single-asset directional trend.
  • The Double Toll is Decisive: Spreads and fees paid on both legs require dislocations to be twice as wide to cover friction.
  • Dynamic Hedge Ratios Prevent Drag: Always re-estimate rolling betas causally on completed bars.
  • Enforce Breakdown Stops: Liquidate immediately when correlation breaks down, regardless of residual z-score.
  • Flatten Hard Daily: Eliminate overnight carry and unmodeled funding risks before session close.

References