#!/usr/bin/env bash # Walk-forward CV for the Phase E.4.A.T10 compose backtest. # # Slides a fixed-size window across the fxcache. Each fold trains DQN # from scratch on the front of the window and evaluates on the back. # Fold C is the cleanest stacker-OOS test (eval bars 1.62M..1.9M lie # entirely past the stacker training cut at 1.57M). # # Outputs per-fold JSON to /tmp/cv_fold_*.json. Run from repo root. set -euo pipefail FXCACHE="${FXCACHE:-/home/jgrusewski/Work/foxhunt/test_data/feature-cache/9297017b6db6795f75e57be8aefb03e45e6427513f42c08e22521e58fa025d5e.fxcache}" ALPHA="${ALPHA:-config/ml/alpha_logits_cache.bin}" FILL="${FILL:-config/ml/alpha_fill_coeffs.json}" BIN="${BIN:-./target/release/examples/alpha_compose_backtest}" WINDOW=700000 TRAIN_FRAC=0.6 # 420K train, 280K eval per fold declare -a FOLDS=( "A:0" "B:600000" "C:1200000" ) for fold_spec in "${FOLDS[@]}"; do name="${fold_spec%%:*}" offset="${fold_spec##*:}" out="/tmp/cv_fold_${name}.json" echo "====================================================================" echo "Fold ${name}: offset=${offset} window=${WINDOW} train_frac=${TRAIN_FRAC}" echo "====================================================================" SQLX_OFFLINE=true RUST_LOG=info "$BIN" \ --fxcache-path "$FXCACHE" \ --alpha-cache "$ALPHA" \ --fill-coeffs "$FILL" \ --data-start-offset "$offset" \ --max-snapshots "$WINDOW" \ --train-frac "$TRAIN_FRAC" \ --c51 --temporal --window-k 16 --isv-continual \ --out-path "$out" done echo echo "====================================================================" echo "Walk-forward summary (best Sharpe_ann per cost, per fold)" echo "====================================================================" python3 - <<'PY' import json, statistics folds = ["A", "B", "C"] rows = [] for f in folds: with open(f"/tmp/cv_fold_{f}.json") as fh: j = json.load(fh) by_cost = {} for b in j["bins"]: c = b["cost"] if c not in by_cost or b["sharpe_annualised"] > by_cost[c][1]: by_cost[c] = (b["threshold"], b["sharpe_annualised"], b["win_rate"], b["avg_n_trades"]) rows.append((f, by_cost)) costs = sorted(rows[0][1].keys()) print(f"{'cost':>8} " + " ".join(f"fold-{f}" for f, _ in rows)) for c in costs: cells = [] for _, by_cost in rows: tau, sa, wr, tp = by_cost[c] cells.append(f"τ={tau:.2f} S={sa:+6.2f} ({wr*100:.0f}%/{tp:.0f})") print(f"{c:>8.4f} " + " ".join(cells)) print() print("Per-cost mean Sharpe_ann ± stddev across folds:") for c in costs: sas = [by_cost[c][1] for _, by_cost in rows] m = statistics.mean(sas) sd = statistics.stdev(sas) if len(sas) > 1 else 0.0 print(f" cost={c:.4f} mean Sharpe_ann = {m:+7.2f} ± {sd:5.2f}") PY