{
  "protocol_version": "2026-08-13.1",
  "locked_before_full_run": true,
  "experiment": "multivariate OHLCV + volatility + lagged cross-market context",
  "universe": "same 17 target markets as Pattern Lab",
  "data": {
    "provider": "Yahoo Finance via yfinance",
    "prices": "auto-adjusted daily OHLC; raw histories remain private",
    "volume_rule": "volume channel only for ETF, commodity and crypto target classes; index/FX volume is omitted",
    "cross_market_context": {
      "sp500": "^GSPC",
      "us_dollar_index": "DX-Y.NYB",
      "vix": "^VIX"
    },
    "context_lag": "for each target bar, every external context value must come from a strictly earlier calendar date; exact-date matches are forbidden",
    "context_tolerance_calendar_days": 7
  },
  "features": {
    "close_shape": "log adjusted-close level, z-normalized inside each candidate/query window",
    "candle_body": "causal 252-bar z-score of log(close/open)",
    "intraday_range": "causal 252-bar z-score of log(high/low)",
    "overnight_gap": "causal 252-bar z-score of log(open/previous_close)",
    "volatility_regime": "causal 252-bar z-score of log(realized_vol_5/realized_vol_20)",
    "volume": "causal 252-bar z-score of log1p(volume), where enabled by class",
    "sp500_context": "strictly lagged causal 252-bar z-score of S&P 500 daily log return",
    "dxy_context": "strictly lagged causal 252-bar z-score of US Dollar Index daily log return",
    "vix_context": "strictly lagged causal 252-bar z-score of log VIX level"
  },
  "feature_scaling": "all non-close channels are point-in-time causal z-scores clipped to +/-6; close shape is local z-score; equal channel weights",
  "analogue_search": {
    "descriptor_points": 16,
    "descriptor": "equally spaced samples of every scaled channel; Euclidean prefilter",
    "prefilter_candidates": 120,
    "rerank": "aeon multivariate DTW",
    "dtw_sakoe_chiba_window": 0.10,
    "max_analogs": 40,
    "minimum_analogs": 12,
    "separation_bars": "max(5, pattern_window/4)",
    "strict_non_overlap": "analogue window plus the maximum 20-bar continuation must finish before the current query window begins"
  },
  "walk_forward": {
    "minimum_training_bars_after_feature_availability": 1000,
    "anchor_step_bars": 63,
    "pattern_windows_bars": [20, 60, 120],
    "forward_horizons_bars": [1, 5, 20],
    "probability_estimator": "Jeffreys-smoothed empirical P(up)",
    "minimum_matched_controls": 60
  },
  "benchmarks": {
    "close_only": "existing STUMPY MASS + tslearn DTW close-shape algorithm rerun on the exact same multivariate OOS anchors",
    "matched_control": "same-market historical windows nearest in momentum and realized-volatility feature space; no geometric shape"
  },
  "primary_metrics": [
    "paired Brier skill vs close-only = Brier(close-only) - Brier(multivariate)",
    "paired Brier skill vs matched-control = Brier(matched) - Brier(multivariate)"
  ],
  "inference": {
    "test": "one-sided Newey-West/HAC mean paired Brier skill > 0",
    "multiple_testing_family": "all valid target-market x pattern-window x forward-horizon x benchmark comparisons pooled together",
    "benjamini_hochberg_fdr": [0.10, 0.05],
    "holm_familywise_alpha": 0.05
  },
  "trading_diagnostic": {
    "long_if_p_up_at_least": 0.55,
    "short_if_p_up_at_most": 0.45,
    "otherwise": "flat",
    "round_trip_cost_bps": {
      "fx": 2.0,
      "index_proxy": 4.0,
      "etf": 4.0,
      "commodity": 6.0,
      "crypto": 20.0
    },
    "stress": "2x base cost",
    "status": "secondary diagnostic only; cannot override the Brier/inference result"
  },
  "decision_rule": "do not call an edge confirmed unless corrected significance survives the preregistered family; report negative results unchanged"
}
