arrow_backBACK TO LOW-LATENCY TRADING SYSTEMS & ALGO TRADING — FROM THE ORDER BOOK TO A LIVE RETAIL ALGO
Lesson 08Low-Latency Trading Systems & Algo Trading — From the Order Book to a Live Retail Algo6 min read

Architecture & Order Management

October 28, 2026

TL;DR

A real retail algo is several processes, each doing what it's best at. A React UI gives you a dashboard, controls and live P&L. A Python web service handles auth, config, orchestration and the REST/WebSocket API. A C++ strategy engine owns the hot path — order book, signals, pre-trade risk, with ring buffers and no GC — because that's where predictable low latency matters (Lesson 5). Redis is the fast nervous system: pub/sub to pass events between processes and hot shared state. PostgreSQL is the durable source of truth: orders, fills, P&L, configs, audit — things you must never lose and will query later. Between every signal and the exchange sits the OMS and, crucially, pre-trade RISK CHECKS that ALL must pass: max order size and price sanity (fat-finger), position and daily-loss limits, margin, duplicate/idempotency, kill-switch state, and rate limits. And a kill switch — one action that halts strategies, cancels orders, blocks new ones and flattens positions — that you test regularly. Risk checks are mandatory AND fast; never skip them. Educational, not financial advice.

Now we assemble the whole thing. A serious retail algo isn’t one script — it’s a small system of cooperating processes, each chosen for what it does best, with a hard safety layer between your strategy and real money. This lesson lays out a realistic architecture (the one you described: React, Python, C++, Redis, PostgreSQL), explains why it’s split the way it is, and then covers the part that matters more than any strategy: the order-management system and pre-trade risk checks that stop a bug or a bad signal from becoming a blown account.

A Real Retail Algo Architecture

Here’s a production-shaped layout. The key idea is separation of concerns: the latency-critical work, the orchestration, the fast shared state, the durable record, and the human interface are different jobs with different tools.

A real retail algo architecture: React UI, Python web service, C++ engine, Redis, PostgreSQL. React UI (dashboard, controls, P&L) connects down to the Python web service / API (auth, config, orchestration, REST/WS), which connects down to the C++ strategy engine (hot path): order book, signals, pre-trade risk, ring buffers, no GC, microsecond loop. Redis on the left (hot shared state, pub/sub between processes, caching) and PostgreSQL on the right (durable store: orders, fills, P&L, configs, audit) both connect to the engine. The engine connects down to the Broker API to Exchange (WebSocket data in, orders out). Why split it this way: C++ owns the latency-critical loop (tick to signal to risk to order), predictable, no GC pauses. Python owns everything where developer speed beats microseconds: the web/API tier, config, research and backtests, and the React dashboard's backend. Redis is the fast nervous system, pub/sub to pass events between processes and hot shared state; PostgreSQL is the source of truth you can query later and never lose

The pieces and why each is what it is:

  • React UI. Your dashboard: live P&L, positions, strategy status, and controls (start/stop a strategy, hit the kill switch). A trading system needs a human in the loop who can see what’s happening and intervene fast; a good UI is a safety feature, not a luxury.
  • Python web service (the API tier). Handles authentication, configuration, orchestration (start/stop strategies, push config), and serves the REST/WebSocket API the UI talks to. Python is perfect here: developer speed and a rich ecosystem matter far more than microseconds for the control plane.
  • C++ strategy engine (the hot path). This owns the latency-critical loop — maintaining the order book, computing signals, running pre-trade risk, and emitting orders — with ring buffers and no garbage collection (Lesson 5), for predictable low latency. For a slow-horizon retail strategy this could even be Python, but the principle is that the hot path is isolated and optimised, whatever language it’s in.
  • Redis — the fast nervous system. An in-memory store used two ways: pub/sub to pass events between processes (the engine publishes fills and P&L updates; the web service and UI subscribe), and hot shared state (current positions, latest prices) that multiple processes read quickly. It’s the low-latency glue between components.
  • PostgreSQL — the source of truth. The durable, queryable record of everything that must survive a crash and be audited later: every order, every fill, P&L history, strategy configs, and an audit trail. If Redis is working memory, Postgres is long-term memory. You never lose an order record, and you’ll query this constantly for post-trade analysis (Lesson 13).
  • Broker API → Exchange. The engine connects out to your broker (WebSocket for data in, REST/WebSocket for orders out) — through the clean adapter layer of Lesson 9.

The reason to split it this way is the thread running through Lesson 5: put the latency-critical 5% where latency is handled carefully (C++, no GC, ring buffers), and everything else where developer productivity wins (Python, React). Redis and Postgres give you the two kinds of memory you need — fast-and-shared, and durable-and-true. This is a clean, honest, buildable architecture, not an over-engineered fantasy; it scales down to a single strategy (the Lesson 13 capstone) and up to many.

A few cross-cutting notes:

  • Separate processes, clear interfaces. The engine, web service and UI are separate processes communicating over Redis and APIs, so one can crash or restart without taking the others down, and you can deploy them independently.
  • Redis is working memory, Postgres is truth. Don’t rely on Redis for anything you can’t afford to lose (it’s in-memory); write the durable record to Postgres. Reconcile the two.
  • The UI is a control surface. Make the kill switch (below) prominent and instant from the UI. In a bad moment you want one obvious button.

Order Management & the Pre-Trade Risk Gauntlet

Between a strategy deciding “buy 50” and that order reaching the exchange sits the most important code in your whole system — far more important than the strategy itself. A clever strategy with weak risk controls blows up; a mediocre strategy with strong ones survives to improve.

Order lifecycle and pre-trade risk: every order passes the gauntlet BEFORE it reaches the exchange. Flow: Strategy (signal fires, 'buy 50') to Pre-trade risk (checks, ALL must pass) to OMS (assign id, track state) to Broker/Exchange (order placed, fills return). Pre-trade risk checks: max order size and price sanity (fat-finger); position limit per instrument; max daily loss not breached; exposure / margin available; duplicate / idempotency check; kill-switch not engaged; rate limit within broker caps. The kill switch: one command (or an automatic trigger) that stops all strategies, cancels open orders, blocks new ones, and flattens or hedges positions; trigger on daily-loss breach, data gaps, disconnection, or a human panic button; test it regularly, you'll want it one day. Risk checks are mandatory AND fast, they sit on the hot path, so keep them tight but never skip them

The order lifecycle: a strategy fires a signal → it passes pre-trade risk checks → the OMS assigns an id and tracks the order’s state → the order goes to the broker/exchange and fills return. The OMS (order-management system) is the bookkeeper: it gives every order a unique id, tracks its state (pending → acknowledged → partially filled → filled / cancelled / rejected), reconciles fills against the durable record (Postgres), and knows your true current position at all times. Getting this right is unglamorous and essential — if you don’t know exactly what orders are live and what you hold, you can’t manage risk.

The pre-trade risk checks are the gauntlet every order must clear, and all must pass:

  • Max order size & price sanity — catch the “fat-finger” bug: a mistyped quantity or a price far from the market. The classic account-ender is a loop that accidentally sends 10,000 orders; a size check stops it.
  • Position limit per instrument — never hold more than you’ve decided is safe in any one thing.
  • Max daily loss not breached — if today’s loss hits your limit, stop trading. This single check saves accounts.
  • Exposure / margin available — don’t send an order you can’t cover.
  • Duplicate / idempotency check — don’t send the same order twice because of a retry or a bug (idempotency: a retried request has no extra effect).
  • Kill-switch not engaged — if the kill switch is on, nothing goes out.
  • Rate limit within broker caps — stay under the broker’s order-rate limits (Lesson 9), both to comply and to avoid runaway sends.

These checks sit on the hot path, so they must be fast — but they are mandatory, never skipped for speed. “Fast and always” is the rule; a risk check you bypass under load is the one that was about to save you.

The Kill Switch

Every trading system needs one thing it can always do: stop everything, now. The kill switch is a single action (a UI button, a command, and automatic triggers) that: halts all strategies, cancels all open orders, blocks any new orders, and flattens or hedges open positions. Wire it to fire automatically on danger signals — the daily-loss limit breached, a market-data gap or feed death (Lesson 3), a broker disconnection, or a human hitting the panic button — and make it instant and obvious from the UI.

The discipline that separates people who keep their money: test your kill switch regularly. A kill switch you’ve never exercised is a kill switch you don’t know works, and you’ll discover its bug at the worst possible moment. Treat it like a fire drill. One day a strategy will misbehave, a feed will die mid-position, or the market will do something violent — and the kill switch is the difference between a bad day and a catastrophe.

Pitfalls to Avoid

  1. One monolithic script. Separate the hot path, the control plane, the fast state and the durable record. One crash shouldn’t take everything down.
  2. Relying on Redis for durable data. It’s in-memory and can be lost. Write orders, fills and P&L to Postgres — your source of truth — and reconcile.
  3. Weak or skipped pre-trade risk checks. They matter more than the strategy. Make them mandatory, comprehensive, and fast; never bypass under load.
  4. No position/daily-loss limits. The two checks that most often save accounts. Enforce them on every order.
  5. No idempotency. Retries and bugs resend orders; a duplicate check prevents accidental double-trading.
  6. No kill switch, or an untested one. You will need it. Build it, wire automatic triggers, and test it regularly like a fire drill.
  7. No human visibility. If you can’t see live state and intervene, you can’t manage a bad moment. The UI is a safety feature.

Quick Recap

  • A real architecture separates concerns: React UI (visibility + control), Python web service (orchestration/API), C++ engine (hot path, Lesson 5), Redis (fast pub/sub + shared state), PostgreSQL (durable source of truth).
  • The OMS tracks every order’s id and state and your true position; between signal and exchange sits the pre-trade risk gauntlet.
  • Risk checks — size/price sanity, position & daily-loss limits, margin, idempotency, kill-switch, rate limit — are mandatory AND fast, never skipped.
  • The kill switch halts strategies, cancels orders, blocks new ones and flattens positions; wire automatic triggers and test it regularly.
  • Risk management matters more than the strategy. Educational, not financial advice.

Next lesson: making your system broker-agnostic — a clean multi-broker framework so one interface drives many brokers (and later, crypto exchanges).