Winnow

Pre-trade risk & low-latency trading

On this page

Electronic trading is the most latency-sensitive rule problem there is. Every order that leaves a trading system is supposed to pass a book of checks first — limits, collars, restricted instruments, per-desk exposure — and the check has to finish before the order goes out. Not in a monitoring dashboard a second later. Before.

⚡ Where speed pays for itself

Here the deadline is not a customer's patience, it is the market itself: a queue position measured in nanoseconds and a regulator that requires the check to happen pre-trade. A gate that is too slow gets removed, weakened, or moved off the order path — which is exactly how firms end up with a monitor instead of a control. Winnow decides in tens of nanoseconds against a book of thousands of rules, allocating no memory, inside your own trading process, so the gate can stay on the hot path and still be a real gate.

The stakes🔗

The rule is not optional. In the US, SEC Rule 15c3-5 — the Market Access Rule — requires broker-dealers to have automated controls that prevent the entry of erroneous orders and of orders exceeding pre-set credit and capital thresholds (17 CFR 240.15c3-5, adopting release). In the EU, RTS 6 Article 15 requires pre-trade controls on order entry, including price collars that "automatically block or cancel orders," and Article 12 requires a kill functionality that can cancel any or all unexecuted orders immediately (Delegated Regulation 2017/589).

What it costs to have the monitor instead of the gate is a matter of public record. On 1 August 2012, a Knight Capital order router replayed dormant code and, for 212 incoming orders, sent millions of child orders to market: 4 million executions in 154 stocks, more than 397 million shares, in about 45 minutes, leaving a $3.5 billion long and $3.15 billion short position and a loss of over $460 million. The SEC's order is precise about what was missing. Knight had no control "to prevent the entry of erroneous orders at a point immediately prior to the submission of orders to the market"; it had no firm-wide capital threshold "linked to automated controls that would prevent the entry of orders"; and its primary risk tool, PMON, was post-execution, relied "entirely on human monitoring," did not display the limits it was meant to enforce, and "experienced delays during high volume events" — such as the one it was needed for (SEC order 34-70694).

And the timescale is regulated too: for high-frequency algorithmic trading, EU RTS 25 sets timestamp granularity at 1 microsecond or better with maximum divergence from UTC of 100 microseconds (Delegated Regulation 2017/574). When the regulator's own unit of account is the microsecond, a risk check measured in milliseconds is not on the order path in any meaningful sense.

How it works🔗

Every limit is a rule, and every outbound order is one event tested against the whole book at once. "Block a sell order in this instrument over 50,000 shares from desk 4 priced more than 5% through the far touch." "Halt this strategy when its open exposure passes the pre-set threshold." "Reject anything in a restricted symbol." This is the reverse query — one event, many standing rules — and the answer is the list of rules that fired. If it is empty, the order goes out.

The point of doing it in nanoseconds is not the nanoseconds. It is that a gate this cheap has no excuse to be moved off the hot path.

Two places to put the rule book — only one of them is a control

INLINE GATE — the order cannot get out unchecked Market data tick arrives Strategy decides to send Risk book · Winnow 10,000 rules, one event p99 113 ns · 0 allocations Exchange order accepted Blocked rule fired POST-TRADE MONITOR — what Knight had on 1 August 2012 Market data tick arrives Router dormant code wakes no gate here orders leave unchecked Exchange 4M executions Monitor post-execution, human-paced 45 minutes · $460M

The difference is one hop, not one product. A gate is only a control if it sits between the decision and the wire, which means it must fit in the time budget of that hop. At ~113 ns for the ninety-ninth order out of a hundred, against a book of 10,000 rules, there is no latency argument for moving it off the path.

The latency budget🔗

Trading systems come in three tiers, and it is worth being blunt about which one this page is about. Hardware paths — logic in FPGA silicon — run wire-to-wire in the low hundreds of nanoseconds; that is not a software problem and Winnow is not competing for it. Tuned software paths, with kernel bypass and pinned cores, run single-digit microseconds. Ordinary software runs tens of microseconds.

Winnow is one step inside a software path: the risk decision, not the decode, not the network. The question is what fraction of the budget that step consumes.

A 5-microsecond software tick-to-trade budget, and the slice a 10,000-rule gate takes

budget 0 1 µs 2 µs 3 µs 4 µs 5 µs risk gate: 181 ns end-to-end (p99) — 3.6% of the budget FOR SCALE Hardware path, wire to wire 100–500 ns not a software tier — Winnow does not compete here Tuned software, wire to wire 1–10 µs the tier this page is about Ordinary software, wire to wire 10–50 µs gate cost is a rounding error

The green sliver is the whole rule decision: assembling the event and testing it against 10,000 standing rules, at the ninety-ninth percentile. The tiers are the industry's own bands, not our measurements; the sliver is ours, measured, and it is the only number on this chart we are claiming.

Why the size of the book stops mattering🔗

A risk book is not small. Per-instrument limits, per-desk limits, per-strategy limits, restricted lists, and self-match constraints multiply out to thousands or hundreds of thousands of rules. The naive approach — test the order against each rule in turn — costs time proportional to the book, which is why slow gates get thinned out.

Winnow files each rule under its most distinctive condition. An order in one instrument, from one desk, can only match the handful of rules filed under those values; the rest are never examined. The cost tracks the candidates, not the book.

200,000 standing rules, one order: what actually gets examined

THE BOOK 200,000 rules never read on the hot path index CANDIDATES ~20 rules filed under this instrument and this desk verify DECISION rules that fired empty ⇒ order goes out 144 ns measured, one core, compound rules same cost at 50,000 rules

Quadrupling the book from 50,000 to 200,000 rules changed the measured cost by under 1% (145.2 ns → 144.4 ns per order). Work tracks candidates, not rules, so the gate does not get slower as the risk policy grows — which removes the usual reason for pruning it.

One order against the whole book: time per decision← shorter is faster · log scale

Winnow1,000 rules 18.9 nsfastest
Winnow10,000 rules 57.3 ns
Winnow200,000 compound rules 144 ns20× rules, 2.5× time
Hand-written scan10,000 rules, one core 2.34 µs≈41× slower
Every rule, fully evaluated10,000 rules 112 µs≈1,960× slower
10ns100ns1µs10µs100µs1ms

Each gridline is 10× slower than the one before. The bottom bar is the same engine with the index switched off — every rule examined for every order — and it is the honest baseline for "just loop over the limits." The gap is what buys the gate its place on the order path.

What we measured🔗

Where the nanoseconds go · 10,000 standing rules, one core

250 ns 500 ns 750 ns 1 µs 1.25 µs ~2 rules share the key match only 69 ns · p50 113 ns · p99 300 ns · p99.9 ~2 rules share the key event assembly + match 119 ns · p50 181 ns · p99 384 ns · p99.9 ~20 rules share the key match only 209 ns · p50 366 ns · p99 1,100 ns · p99.9 ~20 rules share the key event assembly + match 256 ns · p50 388 ns · p99 1,203 ns · p99.9 Matching itself allocates no memory at all; the assembly step is the only part that touches the heap today.

Two shapes of book, because it is the only thing that moves the number. When ~20 limits share an order's key, all 20 are verified and the decision costs ~209 ns; when ~2 do, ~69 ns. The one order in a thousand is the one to plan for: 384 ns and 1.2 µs at p99.9 respectively, still inside a single-digit-microsecond budget.

🧪 In simulation — 10,000 standing rules, 3.2 million orders checked

We built a rule book of 10,000 compound standing rules — each pivoting on an identifier, with a numeric threshold and a set-membership condition, the shape a per-instrument limit book takes — and pushed 3.2 million events through the gate on one core, recording the distribution rather than an average.

69 nsmedian decision against all 10,000 rules — 113 ns at the 99th percentile
0memory allocations per decision, measured, not estimated
144 nsper order when the book grows to 200,000 compound rules
1,960×faster than fully evaluating every rule in the book

What this is: a test run on a generated rule book and a generated order stream, not a customer deployment — the rules and traffic are invented, the speeds and the allocation counts are measured. It ran on one core of an ordinary 16-core desktop, on Windows, with no core pinning, no core isolation, and normal background load: the tail figures here are therefore pessimistic for a tuned colocated host, and the worst individual spikes we saw (hundreds of microseconds, rarer than one in ten thousand) are operating-system scheduling, not rule evaluation. We have not yet measured this on an isolated core under a real-time kernel, so do not take a p99.99 from this page. Percentiles are measured over blocks of 32 orders, because the system clock's own resolution is coarser than a single decision. Every indexed decision was cross-checked against an exhaustive pass over all 10,000 rules, so a gate that quietly matched nothing could not pass itself off as a fast one; the probes ship with Winnow for your team to re-run.

🤖 With AI in the loop

Trading is the clearest case of the division this whole site argues for: models estimate, rules decide. A signal model can predict short-horizon price movement, and an anomaly model can score an order flow as unusual, but neither can be the thing that enforces a capital threshold — regulators require controls that prevent entry on an automated, pre-set basis, and a probability is not a limit. In Winnow, a model's score is one more column: "block when the anomaly score is above 80 and open exposure is over the desk's threshold" is a rule, checked in nanoseconds, and adjustable by a risk officer in minutes rather than a retraining cycle. More patterns: Deep Dive: AI + Rules Engines.

Why Winnow fits🔗

  • It is a library, not a service. The gate runs inside the trading process. There is no network hop, no serialization, and no separate risk server to be unavailable at the wrong moment — which is also what "direct and exclusive control" wants.
  • No allocation on the decision path. Matching an order against the whole book performs zero heap allocations once warm, measured with a counting allocator. Nothing to garbage-collect, no allocator lock, no surprise page fault mid-decision.
  • Single-threaded and deterministic. The decision path uses no thread pool and no work-stealing, so there is no scheduler hand-off inside a decision and no jitter from other cores' queues.
  • Exact money and exact time. Prices and notional limits are held as exact decimals, not floating-point, so no rounding drift reaches a limit check; epoch-nanosecond timestamps are a native numeric column.
  • The book can change while the market is open. Rules are plain text, applied live; a decision already in flight reads a complete, frozen snapshot of the previous book. Widening a collar or adding a restricted symbol needs no restart — and no code release.
  • The same book serves surveillance. The rules that gate an order also match a fill stream for post-trade monitoring, so the pre-trade limit and the surveillance alert cannot drift apart into two different definitions.

Where Winnow does not belong🔗

An honest boundary is worth more than a broad claim, so:

  • It is not a hardware path. Wire-to-wire in the low hundreds of nanoseconds is FPGA territory. Winnow is the decision step inside a software path; if your whole budget is 200 ns from photon to order, this is the wrong tool.
  • It does not decode market data. ITCH, OUCH, FIX, SBE parsing and order-book maintenance are somebody else's job. Winnow starts once you have field values.
  • Event assembly is the remaining cost. Handing the engine an event currently builds a small keyed structure — about 72 ns and four small allocations for a three-field order, roughly as much as the match itself. It is the one part of this page that allocates, it is measured above rather than hidden in an average, and a flat schema-indexed event view would remove it.
  • Per-tick writes into the store are a different pattern. The gate reads; the rule book is registered ahead of time. Streaming every tick into the columnar store as rows is a batch-ingest pattern, not a hot-path one.
  • The extreme tail is unproven here. See the disclosure above: our tail numbers come from an untuned desktop, and the honest last trustworthy column is p99.9.

For the measurement methodology behind the comparisons, and the cost arithmetic on a larger book, see Deep Dive: Cost Savings. For the adjacent case where the same book runs over a fill stream rather than an order path, see Real-time alerting & monitoring.