Skip to content

Paper Trading Stack (Phase 2g)

The forward-testing stack from Phase 2g: the same strategy code that ran the backtests, running on a paper account — first against replayed historical bars (deterministic, tested), then, with owner-provisioned credentials, against the Databento live feed. This page is the pre-registered record: what runs, since when, the adopt/kill criteria (written before the first fill, protocol 2), where the ledger lives, and how it's monitored.

Everything here is paper. Real capital, sizing beyond 1 contract, and any adoption decision are owner calls that happen after this phase reports (non-goals).

The stack

Declared in live/stack.py as a machine-readable manifest the runner and monitor share. Each stream runs at a fixed grid point — paper never re-fits (protocol 1).

StreamCandidateSymbol(s)RoleConfigJudge rank
h1_corepullback_reversionMES, MNQcoreN=5, M=3, 1 contract, via feature transport v21
stress_exit_shadowpullback_stress_exitMESshadow (signal-only, virtual P&L)N=5, M=31
overnight_mnqovernight_driftMNQsleevecondition="always"2
fomc_sleevefomc_hourlyMES, MNQsleeveK=13a

Not in the stack, by design: the MES overnight_drift leg (fee-destroyed — a non-goal; papering a leg we know fails on costs invites motivated re-litigation); the CPI/NFP candidates (backtests, not paper); and the hourly_momentum third sleeve (queued behind a clean month of the above — an owner call).

The diagnostic-power asymmetry (frame every status report this way)

Paper does not test the four streams equally:

  • H1 core — ~13 trades/yr/symbol. A year of paper is statistically non-diagnostic for the edge. What it validates is the plumbing: fills, feature transport, session handling, slippage vs the 1-tick prior. Frame it that way every time.
  • overnight_mnq — ~250 events/yr. The one sleeve where a 12-month paper record is genuinely informative, and the most exposed to fill-convention risk (16:00 / 10:00 ET closes) — exactly what paper measures well.
  • fomc_sleeve — ~8 events/yr. Paper buys operational readiness and event accumulation, not near-term significance; the parent-hourly backfill settles significance far faster.
  • stress_exit_shadow — diverges from H1 only on stress entries (a minority of ~13 trades/yr) → years to a verdict, but ~zero marginal cost beside H1.

Pre-registered expectations & adopt/kill criteria

Written before the first paper fill. No criterion may be revised after paper starts except by a disclosed, dated amendment (protocol 2).

h1_core (rank 1) — expectations, not an adoption test

Calibrated to the deep-history profile (regime-stress note), not the graduated micro numbers: ~0.6–0.75 Sharpe, a real ~5% drawdown in a sustained downtrend, low-beta conditional long equity. The burn-in is a plumbing validation, not an edge test:

  • Consistent-with-backtest = realized slippage ≤ the 1-tick prior; fills at the intended daily-close bar; live signals reproduce the backtest's to the bar (the signal-parity check green); live daily returns inside the backtest CI at the burn-in horizon.
  • Kill / triage = realized slippage > 2 ticks sustained; structural fill failures; any signal-parity divergence (a defect, per protocol 4).

stress_exit_shadow (rank 1) — adoption bar

Runs signal-only beside H1 on MES (logged intended entries/exits + virtual P&L). Adoption bar: the live delta vs H1 must be consistent with the backtest's +0.22 (MES 1.06 vs 0.84) before fleet-wide adoption of the VIX-latched exit is even discussed — and never on the strength of MNQ, where it degrades (stress-exit note). Expect years to a verdict; the value is that it rides along at ~zero cost.

overnight_mnq (rank 2) — the phase's real experiment

12-month burn-in (~250 events). It accumulates evidence ~20× faster than H1, so prioritize it once the core is stable.

  • Adopt signal = realized slippage within the 2-tick sensitivity band the backtest already survives, and live blend behavior consistent with the 0.86 → 0.99 point-estimate's direction (H1 + this sleeve).
  • Kill signal = sustained slippage beyond 2 ticks, or fills structurally missing the 16:00 / 10:00 ET closes (half-day handling is the sharp edge — the session scheduler skips an early-close 16:00 ET entry, mirroring the backtest).

fomc_sleeve (rank 3a) — operational readiness

~8 events/yr, ~7% exposure, fee cost ~0.02%/yr. Framed honestly: paper here buys operational readiness and event-count accumulation, not significance. Track events-observed / events-needed (see monitoring); let the parent-hourly backfill decide significance.

The ledger

Every order, fill, and daily mark appends to an append-only paper ledger (live/ledger.py), mirroring the runs.jsonl discipline. Paper metrics live entirely apart from the frozen candidate-ledger backtest rows — a paper result never edits a backtest record (protocol 3). Each fill records intended_px (the signal-bar reference) vs filled_px (reference plus realized slippage), so slippage vs the 1-tick prior is a first-class, queryable number. In replay, realized slippage is the pre-registered model (1 tick); live, filled_px is the broker's actual fill and the same schema records observed slippage.

Where it persists is an owner decision (a writable paper-ledger store, alongside the live Databento key). The runner is restart-safe: it resumes from the ledger's last mark per stream and only appends rows past it, so a re-run over the same or a longer window never duplicates history.

Monitoring

A daily job over the ledger (live/monitor.py, format_report) surfaces:

  • Per-stream attribution — realized P&L, cycle count, realized slippage vs the 1-tick prior (flagged if outside the 2-tick band).
  • Signal parity — re-runs the backtest per stream and compares entries/exits to the ledger; any divergence is a defect to triage, not a metric to average.
  • Cross-sleeve correlation — each sleeve's daily returns vs H1's, so the diversification thesis is tracked, not assumed.
  • Blend tracking — equity/Sharpe of the stacks the judge priced (H1 book → +FOMC → +overnight), so the forward test of the ~0.92 → ~1.14 stack has a running number from day one (hourly_momentum's rung is tracked here once that sleeve is papered).
  • Event counters — events observed vs the power target per event sleeve, so "are we there yet" has a number.

The live path (workstream 0)

  • Feature transport v2 (0a) — the daily features H1 needs (the 200-day trend gate and the stress-exit's VIX latch) are published as a custom Nautilus Data type on the message bus (feature_transport.py), so the same strategy code runs backtest and live. Acceptance (green): a gated backtest through the transport reproduces the date-map results exactly, to the bar (tests/test_feature_transport.py); the date-map path stays the tested fallback (default off).
  • Live data path (0b) — the Nautilus Databento adapter subscribed to GLBX.MDP3 for MES/MNQ daily + hourly bars, same Panama-adjusted continuous-contract semantics (<root>.v.0, rolls in data) as the backtests. The consistency cross-check flags divergence between the live continuous stream and the weekly-refreshed research cache on bar-to-bar price changes (offset-invariant for Panama series). Needs owner-provisioned Databento live credentials — see below.
  • Session scheduling (0c) — fixed ET session times from pandas_market_calendars (CME_Equity), half-day safe (an early close skips the 16:00 ET overnight entry, matching the backtest). Tested explicitly on the day after Thanksgiving, July 3, and Christmas Eve.
  • Paper execution + ledger (0d) and ops minimum (0e) — the runner above, plus a staleness guard (refuse to trade on a stale feature frame; exits never blocked) and a heartbeat the monitor can read.

Owner decisions (recommend, don't decide)

  1. Parent-hourly backfill (WS3b) — done ✅. Quoted at $1.90 total (uv run python -m vibe_trader.data.cost_quote), approved, and ingested (ES/NQ ohlcv-1h, 2010→2026). The fomc_hourly re-run on the parents (~115 OOS events vs 42 on the micros) moved both bootstrap CIs off zero — ES 0.66 [0.29, 1.02], NQ 0.47 [0.10, 0.89], corr-to-H1 0.04/0.14, PF 2.48/1.99, slippage-robust — settling rank 3: the pre-FOMC drift is a CI-verified, low-correlation edge on deep history (see the ledger). The same backfill also strengthens any future hourly parent candidate.
  2. Live credentials / venue (WS0 blocker). A Databento live key, the paper-account venue choice, and where the paper ledger persists (a writable store — this environment's R2 token may be read-only). Needed to point the tested replay stack at the live feed.
  3. Third sleeve (hourly_momentum MNQ, rank 5). Cheap to add once the stack exists; recommended to hold until the two event/session sleeves have a clean month of paper, then the owner decides.
  4. Warm-started test windows / slow commodity trend (rank 6). A protocol change; recommended as Phase 2h's opening review item, not bundled into this engineering phase.