Building a Production Quant Trading System¶
A practitioner's guide to the unglamorous 90% (validation, risk, plumbing, and operations) that decides whether a trading idea survives contact with a live market.
By Dr. Rayan Azhari · Source & framework on GitHub · About & licence (Parts I & II free; complete book paid; all rights reserved)
Revision 1.27 · last updated 2026-07-16
See the revision history at the foot of this page for what changed.
Most writing about quant trading is about finding edges. This book is about everything that happens after you think you've found one: proving it's real, wiring it to a broker without lying to yourself, sizing it so a bad month doesn't end you, and running it as a process that survives restarts, data outages, and your own future mistakes.
It is built around a single real system (a multi-strategy, broker-connected book we'll call Titan) used as the running case study. Titan is opinionated and battle-scarred: it has shipped look-ahead bugs, mis-sized a leg by a third on a currency assumption, crash-looped on its own data-quality gate, and had an entire quarter of "validated" results deleted because the methodology underneath them couldn't be trusted. Those scars are the point. You'll learn more from why each guardrail exists than from any clean architecture diagram.
What this book is, and isn't
It is a guide to the engineering and methodology of a production systematic-trading stack: research validation, portfolio construction, risk management, deployment, and operations. It is not a source of alpha. Specific parameters, instrument lists, and live performance are deliberately omitted or replaced with clearly-labelled illustrative values: the value here is the process, which is exactly what's safe to share. It is educational material, not investment advice.
The book and the code
A public companion repo, titan-quant, holds the sanitised framework and an educational demo: the validation, risk, and metrics modules the chapters describe, runnable on sample data, with strategy specifics redacted by design. Chapters reference real modules, but the book is read-along, not clone-and-copy: you can run the mechanisms (the gates, the bootstraps, the decision function), not lift a live edge. Appendix D: Run it yourself is the hands-on walkthrough.
Who this is for¶
A working engineer or quant-curious developer who can read Python and knows what a Sharpe ratio is, but hasn't yet built the full pipeline from "interesting backtest" to "thing that trades unattended." If you've ever had a strategy look amazing in a notebook and then quietly bleed in production, this book is the missing middle.
The concrete examples assume a specific stack (NautilusTrader + Interactive Brokers + Docker + Python), but the methodology transfers if your broker or framework differs: the discipline is the point, not the brand.
The one idea, if you read nothing else¶
Suspicion over celebration. When a result looks too good, the correct first reaction is not excitement; it's "where's the leak?" Out-of-sample tests, deflated statistics, held-out windows, and parity checks all exist to answer one question: is this real, or am I fooling myself? Every chapter is, in some sense, a different way of not fooling yourself.
The lifecycle this book follows¶
The whole book is organised around one loop. A strategy is never "done"; it moves around this cycle continuously, and most of the engineering exists to make each arrow trustworthy.
flowchart LR
R[Research<br/>find a candidate edge] --> V[Validate<br/>prove it's real]
V --> D[Deploy<br/>wire it to a broker]
D --> O[Operate<br/>run it unattended]
O --> L[Learn<br/>capture what broke]
L --> R
V -. "reject / retire" .-> R
L -. "retire a decayed edge" .-> R
How it's organised¶
| Part | You'll learn to… |
|---|---|
| I, Foundations & Architecture | Lay out a system whose structure prevents whole classes of bugs. |
| II, Research & Validation | Run a backtest you can actually trust, and decide go/no-go with a function, not a feeling. |
| III, Data Engineering | Source and store data, and gate the system against silently-regressed data. |
| IV, From Research to Production | Turn a validated idea into a live strategy that provably computes the same thing the backtest did. |
| V, Portfolio & Risk | Combine strategies, size positions, and build the layer that keeps a bad day from being a fatal one. |
| VI, Deployment & Operations | Walk one strategy end-to-end, containerise the stack and run it (deploy, redeploy, monitor, halt, recover), reconcile against the broker, and detect and retire a decayed edge. |
| VII, Reflections | What's still unfinished, what we'd do differently, and where to read next. |
How to read this book¶
It is 45 chapters across seven parts (plus a runnable appendix), roughly 90,000 words, a few evenings front-to-back, or an afternoon for a single part. The weight is not even: Parts II (research & validation) and VI (deployment & operations) are the longest and densest, half a day each if you work the exercises; Parts I and VII are short framing reads you can do in a sitting. Read it as a build log, or take one of three paths:
- Validation-first (you have an edge and you don't trust it): Part II → Part V → Part IV.
- Ship-it (you have a strategy and you need it live and safe): Part I → Part VI → Part IV.
- Reference: the left-hand nav is the index; each chapter ends with Exercises (collapsible answers) and a forward link to the next.
The parts build on each other (Part V assumes Part II's validation vocabulary), so a reference reader jumping mid-book may need to back-fill. And if you read only one chapter, read A backtest you can trust: it contains the discipline the rest of the book depends on. Once that discipline has sunk in, the recommended second read is One strategy, end to end, the build-log capstone that threads a single illustrative sleeve through the whole loop, so the separate disciplines become one chain rather than seven parts. Want to run something? Appendix D walks you through cloning the companion framework and watching the gates fire.
Conventions
Code blocks are sanitised, runnable-shaped patterns, not copy-paste alpha. Callouts flag the things that bite: !!! warning for anything that can corrupt a result or a risk calculation, !!! danger for anything that touches live capital. Numbers in examples are illustrative unless explicitly stated otherwise. This matters more than it sounds, because mistaking an illustrative figure for a real one is the exact self-deception the book exists to prevent. Illustrative values are flagged in-text (e.g. "a Sharpe near +2.0 (illustrative)", "M = 20, illustrative"); a number carrying no such flag and no cited source should be read as illustrative, never as live edge.
Revision history¶
The book tracks the live system, so it gets revised as Titan does. Each revision is dated; the footer of every page carries the current revision number. Found an error? The book is revised as the system changes: open an issue on the companion repo or reach the author via About.
| Revision | Date | What changed |
|---|---|---|
| 1.27 | 2026-07-16 | Author's pass over the 1.26 audit material, plus the resolution of the one thing 1.26 left contradictory. The regime gate is no longer dead config: it is armed on purpose, with a passive feed calling update_vix() each bar, and it fails open (a missing or stale volatility series leaves the scalar at 1.0 rather than de-grossing on bad data), so the rule sharpens from "delete it or mark it dead" to "resolve it explicitly, delete it or arm it deliberately and price what you armed". The drawdown throttle now carries the band arithmetic in full: the corrected ramp flattens at a 13.75% drawdown, where (|dd| − heat)/band reaches 0.75, and a scaled-ramp alternative that lands the floor exactly on the 15% kill line is given, because what is indefensible is calling the first one a cliff-free ramp to 15% when it flattens 1.25 points earlier. Deeper passes on the metric suite (CVaR/CDaR sign discipline: gate on the magnitude with the sign kept, never abs() in alert logic), the correlation dial (a worked scenario table), tail risk and ruin (synthetic paths must carry the backtest's own cost and financing model; the log-vs-simple return-convention seam between _rebuild_path and assess_strategy_ruin; the compute cost of re-running a real strategy_fn over 1,000 paths), observability (the five-verb framing and the monitoring gap between liveness and forensics) and incident & postmortem (the book as a postmortem ledger, the engine behind every rule in it made explicit). House style: the em dash is gone from the book entirely, and is now a build guard. |
| 1.26 | 2026-07-16 | The audit revision: what a live risk audit found, and the verifier bugs behind it. A proactive audit of the running system found four safety controls silently inert while every board stayed green, and a parallel audit found four conclusion-flipping bugs in the verification code itself. Both are now war-stories. In Part II (free): a new Verify your verifier section (independently reimplement the load-bearing cell; audit assuming a bug) plus the window that deleted the crash; the deflated-Sharpe gate that rubber-stamped every winner (an annualised Sharpe fed into a daily variance term inflated z roughly tenfold and pinned dsr_prob near 1.000), with the frequency walkthrough corrected end to end; a vol-matched comparison caveat in the metric suite; and a public-index margin-call worked example plus a "length is not coverage" bootstrap caveat in tail risk and ruin. In Parts V to VI: the correlation dial's freshness guard firing perfectly for 46 days while the book ran ungoverned (fail-safe as fail-open); regime_scale named as dead config; the drawdown throttle's band-normalisation cliff and the persisted halt that forgot its own high-water mark (also in state durability); the borrow cost that makes levering a low-vol sleeve the dominated route; a fourth runtime attestation rung and a worked audit-triggered postmortem in incident & postmortem; the dead sleeve that read healthy on every gauge; frozen-paper-feed flatten and bar-flow assertions; and retiring a live sleeve manufacturing the orphan that halts the whole book. |
| 1.25 | 2026-06-30 | Second-pass review of the items the 1.24 remediation had deliberately deferred: applied the ~10 that were genuinely additive (the rest stay skipped as duplicative, owned by another chapter, or thesis-preserving). Adds the alpha-side-killers scope note + a four-gate "spine" box to Ch. 1; a "three things a single-snapshot parity test still misses" note (transient, stateful, multi-feed) to live == research; partial-fill protective-leg and terminal-vs-transient retry guidance to broker realities; a per-leg currency-conversion note to per-strategy equity & FX; self-consistent gate snippets in the data-quality gate; and a "how a bug becomes a catalogue entry" intake note in the failure-mode catalogue. |
| 1.24 | 2026-06-30 | Audit-driven remediation of the whole improvement backlog (a multi-agent re-read of every chapter against every backlog item). Fixed the 8 remaining high-severity gaps (the capstone as a signposted "second read", a complete A-code/V-era register + a scannable war-story index, the data-gate's operator-facing Regression artefact (with the ch.13 overlap compressed), the correlation dial's 1.0-ceiling-vs-1.5-default honesty note, a bar-by-bar de-risk-ladder trace, and a standalone verdict-mapping on the pre-flight checklist), plus ~130 medium/low improvements folded surgically across 28 chapters (worked Kelly and ruin examples, a closed-form first-passage cross-check, a drawdown-gate summary table, config-validation and units-contract notes, new glossary terms, and many cross-references). No new chapters; existing-chapter depth only. |
| 1.23 | 2026-06-29 | Completed the Part B existing-chapter pass: surgical worked-number and operational additions across Parts I–VII closing the high-severity gaps from the improvement backlog, without new chapters. Highlights: a fully-numeric de-risk ladder and a flatten-selection criterion in layered safety; a build-time import-check Dockerfile, concrete heartbeat constants + atomic writer, and an fx_market_likely_open() sketch in containerizing; a post-redeploy health gate, an escalation/paging table, and the exact reset_halt invocation in the live runbook; an operational "clean soak" definition, a pre-live slippage-budget technique, and a data-parity check in paper to live; explicit exit criteria and a severity ranking in caveats; Sortino, Almgren-Chriss, and survivorship citations in the reading list; and operationalised appendices: an A–Z index + ops-vocabulary in the glossary, halt-persistence + the five-term scale_factor on the integration card, and a copy-pasteable checkbox version of the pre-flight checklist. |
| 1.16–1.22 | 2026-06-29 | Seven Tier-3 additions: new chapters Time, sessions & calendars, Order lifecycle & idempotency, When the strategy is a model (the ML lifecycle), Live TCA & best-execution evidence, Running an incident & the postmortem, and The operator under fire; plus a covariance-estimation/shrinkage deepening and a realised-vs-assumed correlation-drift band folded into the allocator and layered-safety chapters. |
| 1.5–1.15 | 2026-06-29 | Eight new chapters + a runnable appendix completing Tiers 1–2 of the improvement backlog: Factor & beta exposure, The execution layer, The trade record vs the log, Alerting & the dead-man's switch, Solo operator or team, Capacity & crowding, Combining forecasts, Observability, and State durability & disaster recovery; a Legal & regulatory pre-live bucket; Appendix D: Run it yourself; and end-of-chapter Exercises (with collapsible answers) throughout. |
| 1.4 | 2026-06-26 | New Part VI chapter Reconciliation: making the broker the book of record. Generalises the boot-time restart-adoption story into a continuous discipline: the broker is the book of record and your in-memory state is a cache that drifts. Covers the five break classes (missed fill, out-of-band manual close, corporate-action split, cash/NLV/FX drift, stuck order), the three-way reconciliation (book vs broker vs trade log), the alert→confirm→halt action ladder (and why auto-adopt is forbidden), and reconciliation as a retained evidentiary artifact. Honest about what Titan reconciles today (an internal-book drift watchdog with one auto-halt path) vs what's still unmodelled (the cross-currency NLV invariant). Closes the dangling "reconciliation orphan trip" the runbook operates but never defined. |
| 1.3 | 2026-06-24 | Two new chapters in Part VI. One strategy, end to end: a capstone walks the running bond→gold example through all 20 pipeline stages in order, as a build log, surfacing the cross-stage seam bugs (the bracket reject, the silent fx=1.0, the leg sized by the signal price instead of the traded price) that survive every individual chapter. The Learn loop builds the Operate → Learn → retire arrow the lifecycle diagram has always promised: detecting a decayed edge (re-running the verdict function on live evidence; the drift-band throttle vs the structural-break detector) and a pre-committed retirement rule, honest about which rungs are armed, inert, or still wiring. |
| 1.2 | 2026-06-22 | Added a war-story about a safety counter that silently disarmed itself on every restart. In the failure-mode catalogue: the guard that reset on every restart: a minimum-hold counter and a drawdown circuit-breaker that lived only in memory, so a frequently-restarting system silently disarmed both (a position exited a bar early; a breaker cleared mid-drawdown and re-levered). Plus, in layered safety, the closing-the-loop sequel to the fresh-but-wrong drift band: rebuilding the band for the bundle you switched to, with a parameter-parity lock and a plausibility gate on the output. |
| 1.1 | 2026-06-11 | Added war-stories about safeguards that agreed with each other while both were wrong, code that had never run until it crashed live, and a "close" that closed nothing. From a full adversarial re-audit: mutually-reinforcing-wrong safeguards (two checks validating each other against a phantom roster), dormant code is unvalidated code (a strategy whose first live act was a latent crash), and the close that closed nothing (strategy-scoped flatten no-oping on framework-reconciled positions) in the failure-mode catalogue; plus, in layered safety, a fresh-but-wrong drift band (provenance + fail-safe), an out-of-process backstop whose halt never reached the node, and the kill switch that didn't announce itself. |
| 1.0 | 2026-06 | Initial edition: Parts I–VII. |