Smart Order Routing: Where Your Order Actually Goes
You don't choose where your fills come from — the router does, and the router has incentives of its own: fee schedules, rebates, internalization, toxicity. Understand those incentives and you'll know whose side it's on.
You press “buy.” Your order vanishes into the broker’s router. A few hundred milliseconds later, you get filled. You assume the fill came from the venue showing the best price on your screen.
It didn’t.
US equities trade simultaneously across more than a dozen lit exchanges, 30-plus alternative trading systems (ATS, mostly dark pools), and countless internalizing broker-dealers. The NBBO on your terminal — the National Best Bid and Offer — is a synthesized number that may not exist on any single venue at the moment you look at it. The order you sent got sliced, routed, filled in pieces, and possibly re-routed mid-flight by a smart order router (SOR) making decisions in microseconds.
If you don’t understand how your SOR works, you’re trading blind. The router determines what spreads you cross, what fees you pay, what fills you get, and — critically — what information you leak. And a router is not a neutral pipe: behind every decision sits an incentive — fee schedules, rebates, internalization economics, toxicity data. This article walks those incentives end to end, and ends on the question that has to be asked: is this thing working for you, or for someone else?
Harris (2003, Ch. 25) frames all of it as market fragmentation: the same security trading in many places at once creates arbitrage opportunities, but also execution complexity. The SOR exists to navigate that complexity. The only question is on whose behalf.
The Landscape
The lit venues for US equities are the registered exchanges: NYSE, Nasdaq, CBOE — and IEX, which started life as an ATS and has been a registered exchange since 2016. Each has its own book, fee schedule, and latency profile.
Dark pools are ATS that don’t display quotes. They match internally, then report the trades to the consolidated tape via FINRA’s Trade Reporting Facility (TRF). Examples: Goldman’s Sigma X, Morgan Stanley’s MS Pool, Citadel Connect, Credit Suisse’s Crossfinder, Virtu MatchIt, and dozens more.
Internalizers are broker-dealers that fill orders against their own inventory and never route to a venue at all. Retail flow is heavily internalized: payment for order flow (PFOF) means retail market orders get filled by wholesalers like Citadel Securities and Virtu, who keep the spread.
For a single stock, your SOR might simultaneously see displayed size on 5 lit exchanges, indications of hidden size in 8 dark pools, and internalization offers from 2 wholesalers. Deciding where each child order goes — that is the entire content of SOR logic.
The Basic Decision Tree
When you send a market order to buy 1,000 shares, the SOR runs roughly this sequence:
- Check the NBBO. What’s the best displayed offer across all lit venues?
- Check dark pools. Any indications of hidden size at or better than the NBBO?
- Check internalizers. Will a wholesaler fill sub-penny better than the NBBO?
- Route accordingly. Send to the venues with the best combination of price, size, and fees.
- Re-route as needed. If the first venue doesn’t fill, move to the next.
For a small order in a liquid stock, this is mostly mechanical. For a large order in a less liquid name, it’s a multi-stage optimization — and the objective function contains things besides your fill quality. Start with the most openly priced of them: fees.
Lit Exchange Routing: The Fee Game
When the SOR routes to a lit exchange, the order either rests on the book (maker) or takes immediately (taker). Four variables drive the choice: whether the venue pays a rebate for adding liquidity or charges for taking it; the actual rates — maker-taker fees run 0.0030 per share, which on a 100,000-share order is 300 in either direction; matching-engine speed, which matters for latency-sensitive strategies; and fill probability, since some exchanges simply fill marketable orders at higher rates than others.
The classic maker-taker model: post a limit order and collect a rebate when someone hits it; send a marketable order and pay a fee. But some exchanges run it backwards — taker-maker, where the taker gets paid. These inverted venues are particularly interesting for liquidity takers: configure your SOR to favor them for aggressive orders and you collect a small per-share rebate instead of paying a fee. Tiny per share; not tiny multiplied by your volume.
def route_marketable_order(side, qty, venues):
"""Pick the best venue for a marketable order."""
best_venue = None
best_effective_cost = float('inf')
for venue in venues:
quote = venue.nbbo(side)
fee = venue.taker_fee(side)
cost = quote + fee # effective cost to fill
if cost < best_effective_cost:
best_effective_cost = cost
best_venue = venue
return best_venue
That’s a toy. Real SORs weigh fill probability, queue position, latency, and anti-gaming protection — and “lowest effective cost” doesn’t always win. If the venue is “toxic,” full of informed traders who take your liquidity and run the price, the fee you saved on paper comes back doubled in price. How toxicity gets quantified is a section of its own, below.
Dark Pool Routing: The Price of Saving the Spread
Dark pools don’t display quotes. Your SOR sends an order (or an indication of interest), and the pool’s matching engine tries to cross it against a resting order. No match, and the order waits in the dark or cancels at its time-in-force.
The attractions are real: no displayed spread, so crossing against a dark order inside the spread is price improvement; nothing resting visibly on any book, so nobody sees you waiting; and mid-point matching at many pools, where a buy filled at mid saves half the spread outright.
But each attraction carries its bill. Adverse selection: dark liquidity is not random — informed traders prefer dark pools precisely to avoid being front-run, so your average dark fill is more likely to be “toxic,” a counterparty who knew something. Information leakage: your order isn’t displayed, but the ping your SOR sends is observable, and a sophisticated market maker who sees it knows someone is hunting for size. Fees: some pools charge takers more than lit exchanges do; others pay rebates but deliver worse fills.
Harris (2003, Ch. 25) covers dark pools at length. His point: they emerged as a reaction to displayed execution — institutions didn’t want their orders visible, so venues appeared that hid them. The trade-off between hidden liquidity and information leakage is the central design problem of the dark pool, and it’s the reason the next section exists.
Anti-Gaming: Don’t Let Your Routing Pattern Testify Against You
A naive SOR that pings every pool for every order gets recognized, then harvested. The pattern is unmistakable: touch 8 dark pools in 10 milliseconds for a 100-share order and sophisticated counterparties know it’s a retail internalizer or a small algo, and trade ahead of it.
Anti-gaming logic aims to make the SOR unpredictable. The modern toolkit: minimum size thresholds, so pools don’t get pinged for orders too small to matter; randomized timing, never all pools at once; varied sequencing, changed by day and by symbol; conditional routing that skips pools showing recent signs of informed flow; and IEX-style speed bumps — IEX introduced a 350-microsecond delay to neutralize the fastest traders, and other venues have followed with their own anti-latency-arbitrage measures.
The cost is inconsistency. If the SOR skips today a pool it pinged yesterday, your TCA acquires unexplained variation. A few TCA systems account for this by comparing SOR behavior across orders; most don’t.
Internalization: The Most Opaque Layer
When a retail broker receives a retail market order, the order is often filled by the broker’s own desk or a wholesaler (Citadel Securities, Virtu) at a price inside the NBBO. The wholesaler pays the broker for the flow (PFOF) and keeps the spread.
Institutional internalization is less common but real. If your broker is also a market maker, they may offer to fill you internally at the midpoint. The arithmetic sounds like a wash — they earn the spread, you save the spread — but in practice internalized fills sometimes come in worse than the displayed price. Most institutional SORs carry a built-in internalization preference when the broker makes markets, and this is a regulatory question as much as an execution one: the SEC has been scrutinizing PFOF and internalization since 2020. Your broker’s SOR probably internalizes more than you’d choose — and how much more is something you can actually check, as the disclosure section below shows.
Four Scenarios, Four Routings
What these decisions look like in the field, in four examples.
Small market order, liquid stock: the SOR routes to 2-3 lit exchanges at once, captures liquidity at the NBBO, maybe collects improvement from an inverted venue on the way. Cost: 0-1 cent per share; you barely notice. Large limit order that gets hit: the SOR posts on the exchange with the highest maker rebate and deepest queue, and deliberately avoids internalization — you want the displayed fill, not the wholesale one. Cost: negative; you earn the spread plus the rebate. Large market order, less liquid stock: the SOR pings dark pools first for mid-point fills, takes what it can, then sweeps the lit exchanges. Cost: 3-10 cents per share depending on size and volatility. Order during a news event: the SOR freezes routing, waits for the book to settle, then resumes — without that, you’re charging into a chaotic book full of stale quotes and paying through the nose.
The cost differences across these scenarios are not subtle. A well-configured SOR reliably saves 5-10 bps per trade. A badly configured one reliably loses the same.
What the Buy Side Can and Can’t Control
If you’re on the buy side, you have some leverage over your SOR — less than you’d think.
You can specify venue preferences (“keep my orders out of dark pool X, their fills are toxic”), anti-gaming parameters (“randomize my routing”), dark-pool participation caps (“no more than 20% of my order fills dark”), and lit-exchange priority (“favor inverted venues for aggressive orders”). What you typically can’t control: the internalization logic, which is built into the broker’s SOR — you can disable it wholesale but not direct it; latency optimization, because the low-latency infrastructure is the broker’s asset, not yours; and the anti-gaming IP, which is the broker’s crown jewels.
Which is why broker selection matters enormously: the SOR is the broker’s intellectual property, and the spread between good and bad is wide. Broker selection gets its own article.
One more structural point that’s easy to miss: the algo and the router are a stack. A VWAP algo doesn’t care which venue its child orders hit — it cares that fills are clean and the venue mix doesn’t overpay. But a liquidity-seeking algo that pings dark pools and waits on hidden orders is half an SOR itself, and so is a POV algo aggregating lit liquidity across venues. The boundary between “algo” and “router” has blurred: the algo makes the high-level decisions (when, how aggressively), the SOR handles the low-level routing (where) — but the algo’s decisions constrain the SOR and the SOR’s capabilities constrain the algo. Evaluating a broker’s execution therefore means evaluating the whole stack. A broker with a great algo and a bad SOR underperforms one with a mediocre algo and a better SOR. Experienced buy-side traders know this; the inexperienced don’t.
Toxicity Detection: The Router’s Immune System
“Toxic” has come up repeatedly; here’s the operational definition: a venue is toxic when its fills are systematically followed by adverse price moves. Dark pool X’s fills consistently run 2-3 bps worse than other pools within 30 seconds of filling? Deprioritize it.
There are three ways to quantify it. Markouts: after a fill at time , measure the price change at , , ; if the price moves against you, the fill was toxic. Fill-rate analysis: a pool that fills 30% of your orders at the NBBO but 50% at inferior prices is choosing when to fill you — in its own favor. Comparison to expectation: if the model predicts a fill at X and you consistently fill at X − 2 bps, the venue is delivering worse than the model expects.
def markout_score(fills, lookhead_ms=5000):
"""Compute average markout for a set of fills."""
total = 0
for fill in fills:
future_price = get_mid(fill.symbol, fill.time + lookhead_ms)
if fill.side == 'BUY':
total += future_price - fill.price
else:
total += fill.price - future_price
return total / len(fills)
Negative markout means the venue’s fills are toxic (price moved against you afterward); positive means the fills ran in your favor. Modern SORs use markout data to re-rank venues dynamically: a pool that’s been toxic for the past hour gets demoted on the spot. Which also explains why your broker’s routing looks inconsistent intraday — it’s adapting.
Auditing With Regulatory Data
So how do you verify any of this beyond the broker’s word? Since 2020 the SEC has pushed routing transparency, and it has handed you three concrete instruments.
Rule 606 requires brokers to disclose their routing practices quarterly: where your orders went, what fees were paid or received. Rule 605 requires execution venues to publish monthly execution-quality statistics: the fills actually delivered versus what was available. And the ATS reporting rules force dark pools to disclose more about their operations.
For the buy side this is leverage. The 606 report shows your broker internalizing 40% of your flow at inferior prices? You have data to push back with. The 605 statistics show price improvement consistently below the industry median? You have grounds to renegotiate. An honest broker welcomes the disclosure; a dishonest broker’s 606 report is all asterisks and footnotes — which is itself information.
The audit checklist is short. Pull your 606 report and see where the orders went and what you paid. Compare markouts by venue — which pools feed you clean fills, which feed you toxic ones. Check whether your internalization rate exceeds what you’d choose. Test any new broker with a small order and trace the routing before committing size. Then talk to the broker’s SOR team about their routing logic — every large broker has one, and a team that can’t explain its own router is a red flag. If you’re on the broker side of the table, run the same logic in reverse: measure toxicity continuously and drop toxic venues from default routing; randomize within bounds, because excessive anti-gaming costs execution quality; write 606 reports a human can read; and accept that an SOR is not set-and-forget — it needs continuous calibration.
Finally, the field guide. SORs come in roughly four profiles: retail-focused (heavy internalization, PFOF, NBBO or sub-penny fills — fine for small orders, bad for institutional flow); institutional default (mixed lit and dark, heavy mid-point pool usage, selective internalization — a reasonable balance for most institutional flow); aggressive liquidity-seeking (many pool pings, rebate-earning lit posts, aggressive internalization — built for large orders in liquid names); and patient (mostly passive posts, waits for fills — built for non-urgent orders in stable names). Which you want depends on your strategy; most institutional traders run the second or third. Knowing which one you’ve actually been handed is the first line of the audit.
References
- Harris, L. (2003). Trading and Exchanges: Market Microstructure for Practitioners. Oxford University Press. Ch. 25. ISBN: 978-0-19-514470-3.
- Perold, A. F. (1988). “The Implementation Shortfall: Paper Versus Reality.” Journal of Portfolio Management, 14(3), 4-9.
- Almgren, R., & Chriss, N. (2000). “Optimal Execution of Portfolio Transactions.” Journal of Risk, 3(2), 5-39.