Microstructure and Execution · Execution
9Dark Pools and Blocks
A pension fund wants to buy two million shares of a stock that trades five million a day. Shown on a lit book, the order would move the price before a tenth of it traded; sent to a dark pool, it waits for a seller, and every venue it touches learns a little of what it wants. Dark venues exist to let large orders meet without announcing themselves, and they work only as well as they keep the secret. This chapter builds a dark pool and a block venue beside a lit book in the exchange simulator, measures who fills in the dark, and works one large order four ways to price what leaks.
9.1 Midpoint crossing and minimum quantities
A dark pool (One Quant Book 1, chapter 9) displays nothing and usually crosses at the midpoint of the lit market’s best bid and offer, so both sides save half the spread against trading on the lit book: between 20.00 and 20.02, a cent a share each, USD 100 on 10 000 shares. The price is borrowed: the pool needs the lit quotes, and its crosses are only as current as its copy of them. firm.exchsim now gives a dark venue that copy: a reference quote control message (N) carries the lit venue’s best bid and offer to the dark engine after each change, and midpoint pegs price off it (midpoint_dark_pool(reference=…)).
Definition 9.1 (Minimum execution quantity)
A minimum execution quantity on a resting dark order is the smallest fill it accepts: an incoming order that cannot trade at least that much with it passes it by. On an incoming immediate-or-cancel order it is the smallest total fill worth taking.
A resting midpoint buy of 5 000 shares with a minimum of 1 000 ignores a 300-share sell and trades with a 1 500-share one. The minimum is a filter on counterparties: small orders that probe the pool, and the small orders of fast traders generally, cannot reach it. It is also a filter on fills: the large order trades less.
Definition 9.2 (Crossing network)
A crossing network matches buy and sell orders at a price taken from elsewhere (the lit midpoint, a closing price, a benchmark), without price discovery of its own, either continuously or at scheduled times.
9.2 Conditional orders and block venues
Definition 9.3 (Indication of interest)
An indication of interest (IOI) is a non-binding message that a trader may want to trade a security, with a side and sometimes a size or a price, sent to a counterparty or a venue to find the other side of a large trade.
Definition 9.4 (Conditional order)
A conditional order is an indication of interest resting on a block venue: when it meets a contra conditional of at least both sides’ minimum sizes, the venue invites both traders to firm up, to send a binding order, within a short timer. If both do, the block crosses; if either does not, nothing trades.
Definition 9.5 (Firm-up rate)
A participant’s firm-up rate is the share of the invitations it receives to which it responds with a firm order. Block venues track it and restrict participants whose rate is low, because a conditional that does not firm up has learnt that the other side exists at no cost.
Conditionals let one order rest on several block venues and algorithms at once without risking a double fill, since only a firm-up commits it. Their weakness is in the definition: an invitation tells both sides that a large contra exists. A counterparty that never meant to trade gets the information for free, which is why the firm-up rate is policed (Figure 9.1). firm.darkpool.ConditionalBook implements the matching, invitations, firm-up timers and rates.
def invitations(self, t_ns: int) -> list[tuple[int, int, int, int]]:
"""Match free conditionals in time priority: (invitation id, buy id, sell id, qty)."""
out = []
free = sorted((o for o in self.orders.values() if not o.busy), key=lambda o: o.t_ns)
buys, sells = [o for o in free if o.side > 0], [o for o in free if o.side < 0]
for b in buys:
for s in sells:
if s.busy or b.busy:
continue
q = min(b.qty, s.qty)
if q >= b.min_qty and q >= s.min_qty:
b.busy = s.busy = True
iid = self._next_inv
self._next_inv += 1
self.open[iid] = _Inv(b, s, q, t_ns)
for o in (b, s):
self.stats.setdefault(o.owner, [0, 0])[0] += 1
out.append((iid, b.id, s.id, q))
break
return out
9.3 Who trades in the dark, and the evidence
Zhu (2014) explained who goes dark. Informed traders trade in the same direction as one another, crowd on the heavy side of the market and so face a higher risk of not being filled in the dark, where the other side must come to them; the exchange suits them better, the dark pool suits uninformed traders, and a dark pool can concentrate information on the exchange. Comerton-Forde and Putnins (2015) found in Australian data that dark trades are less informed than lit trades, that low levels of non-block dark trading are benign or even beneficial for informational efficiency and high levels harmful, and no evidence that block trades in the dark impede price discovery.
The chapter’s market reproduces the selection. Its efficient price moves by exogenous jumps and by the permanent impact of uninformed lit market orders, ticks a share (informed orders reveal , they do not move it). Liquidity providers quote on LIT; noise and informed takers try the dark pool first half the time and send what is left to LIT; patient uninformed traders rest midpoint pegs in the dark. Over four seeds of 45 minutes, informed takers who tried the dark were filled for 6.3% of their shares, uninformed ones for 17.5%: the informed buy when everyone informed buys, and the dark sellers run out. Resting in the dark gives up the spread, but its fills were followed by a move of cents in the resting trader’s favour over 30 seconds, against cents for lit providers, who capture 0.51 cents of spread and pay adverse selection on it.
9.4 Information leakage
Definition 9.6 (Information leakage)
Information leakage is the part of a large order’s cost that comes from other traders learning of it before it is complete, from its fills, its quotes, its conditionals or its routing, and trading ahead of it.
Definition 9.7 (Pinging order)
A pinging order is a small immediate-or-cancel order sent to a dark venue to detect hidden liquidity: a fill reveals a resting contra order at that price, and repeated fills reveal a large one.
A fund buys 20 000 shares from ten minutes into the session over 30 minutes, four ways: lit, a market order of 200 every 18 seconds; dark, one resting midpoint peg for the whole order; dark with a minimum, the same peg with a minimum of 1 000; block, conditionals in a block venue where natural sellers post conditionals of 5 000 to 15 000 shares every five minutes on average, 30% of whom never firm up and buy 2 000 shares on LIT instead. Whatever is left after 30 minutes is bought on LIT at once. A pinger probes the dark pool every two seconds with 100 shares, alternating sides; when two probes in a row on one side fill within five seconds, it buys (or sells) 500 shares on LIT ahead of the order it has found.
if s == PINGER and venue == "DARK":
self.pings += 1
fund = self.dark.trades[-1][4] == FUND # whose order the probe hit
self.fund_pings += fund
last = self._last_ping.get(side, (-1e9, False))
if last[0] > self.t - 5.0: # two fills in a row: a large order
self._market(PINGER, -side, 500, False) # trade ahead of it on LIT
self.front_runs.append((self.t, 500, fund or last[1]))
self._last_ping[side] = (self.t, fund)
The shortfalls are noisy, so the simulation also accounts for the two costs it knows. Each lit buy of moves by and raises the price of every share the fund buys afterwards: summed over the fund’s own lit children this is its own-impact cost, basis points for 100 children; summed over the pinger’s and the leaky sellers’ trades ahead of it, when they were triggered by the fund, it is the leakage cost. Over sixteen seeds with the same exogenous events for every strategy (Figure 9.2):
- Lit: shortfall 3.8 basis points (standard error 1.4), drift of the mid over the window 7.3 (2.3), own impact 4.95, no leakage.
- Dark: the peg completes in about 360 seconds, but the pinger finds it: 88 of its probes fill against the fund, it buys 44 000 shares ahead, and the leakage costs 10.9 basis points (0.3). Shortfall 12.5 (0.5), drift 26.1 (2.2).
- Dark with a minimum of 1 000: no probe can fill it and there is no leakage, but only 46% of the order fills in the dark; the rest is bought at the end, at 1.4 basis points of own impact. Shortfall 9.5 (1.6), drift 11.9 (1.6).
- Block: 79% crosses in blocks, 0.75 leaky invitations per run cost 0.6 basis points. Shortfall (1.9), drift (2.2).
mx_dark.compare.The lessons hold beyond the model’s numbers. A resting dark order is visible to whoever probes for it, and the probe costs the prober 100 shares at the midpoint; the leak can cost more than the impact the dark venue was chosen to avoid. A minimum quantity above the probe size stops the leak and costs completion. And a midpoint fill saves the spread but not the impact when the counterparty is flow that would otherwise have sold on the lit book: taking it out of the lit market moves the price the same way. Blocks are cheap in the simulation because their sellers bring size that would not otherwise have traded: the cost of a trade is the imbalance it creates, wherever it is printed.
9.5 Dark pools in enforcement records
The secret is the product, and enforcement records show what happens when operators do not keep it. On August 12, 2015 ITG and its affiliate AlterNet Securities agreed to pay USD 20.3 million, admitting that an undisclosed proprietary desk, Project Omega, had accessed live feeds of its dark pool subscribers’ orders and executions and traded against them in POSIT. On January 31, 2016 Barclays agreed to pay USD 70 million, half to the SEC and half to the New York Attorney General, for misrepresenting how its Liquidity Profiling policed its LX pool, and Credit Suisse USD 84.3 million over its Crossfinder pool, where it misrepresented its Alpha Scoring of subscribers’ flow, accepted over 117 million sub-penny orders and alerted two high-frequency firms to customer orders through its Crosslink service. Each is a case of information leakage by the venue itself.
As of September 2026 — Dark trading caps in the European Union
The MiFIR review entered into force on 28 March 2024. It replaces the double volume cap on dark trading with a single volume cap that applies only to the reference price waiver, from 18 months after entry into force; ESMA planned its first suspension file under the new cap for 9 October 2025.
9.6 Tutorial: the block that leaked
Goal. Build a lit and a dark venue with a block layer, measure who fills in the dark, and price the leakage of a large order. End state: Figure 9.2 and the numbers of sections 3 and 4.
- Venues.
mx_dark.Market(seed, strategy): two engines driven directly, the dark one priced by control N after each change of the lit top. - Selection.
zhu(): dark fill rates of informed and uninformed takers, capture and 30-second move of resting fills in the dark and on the lit book. - Leakage.
run(seed, strategy)forlit,dark,dark_min,block;compare()over sixteen seeds; draw withfig_dark.py. - Block layer.
firm_darkpool.ConditionalBook: add conditionals, collect invitations, firm up, expire, and read the firm-up rates.
What to change next. Give the pinger 50-share probes and the fund a minimum of 200; let the block venue exclude participants whose firm-up rate falls below one half, and watch the leakage.
9.7 Build: the dark venue
Purpose. Dark and block liquidity for the execution algorithms of chapters 16 to 18 and 28, and the leakage measures the transaction-cost analysis of chapter 19 reports.
Interface. ConditionalBook(firm_up_ns): add, cancel, invitations, firm_up, expire, firm_up_rate; shortfall_bps, pre_completion_drift_bps, counterparty_markout. In firm.exchsim: control N in the Python, C++20 and Rust engines, ExchangeConfig(reference, reference_ns), midpoint_dark_pool(reference=…).
Rules. A conditional matches only when the smaller size meets both minimums; an order is in one invitation at a time; the block crosses only when both firm up within the timer; a lapsed invitation counts against whoever did not respond.
Acceptance tests. code/firm/darkpool/tests/: an invitation, a two-sided firm-up, a lapse and the resulting rates; shortfall, drift and counterparty mark-out by hand. code/firm/exchsim/tests/: a midpoint peg with a minimum ignores a small order and crosses a large one at the lit mid; the fixtures with three N messages stay byte-identical in C++20 and Rust.
Stretch. Periodic dark auctions; venue-level participant scoring that blocks low firm-up rates; the counterparty mark-out curve of chapter 19.
Sources and further reading
- H. Zhu, “Do dark pools harm price discovery?”, Review of Financial Studies 27(3), 2014.
- C. Comerton-Forde and T. Putniņš, “Dark trading and price discovery”, Journal of Financial Economics 118(1), 2015.
- U.S. Securities and Exchange Commission, press release 2015-164 (ITG, AlterNet Securities), 2015; press release 2016-16 (Barclays, Credit Suisse), 2016.
- European Securities and Markets Authority, Double Volume Cap Mechanism, web page, 2025.
9.8 Exercises
Exercise 9.1 ★
The lit market is 20.00 bid, 20.02 offered. What does each side of a 10 000-share midpoint cross save against crossing the spread on the lit book?
Solution
Solution of Exercise 9.1.
The midpoint is 20.01: the buyer saves and the seller , a cent a share each, USD 100 on 10 000 shares.
Exercise 9.2 ★
A resting midpoint buy of 5 000 with a minimum of 1 000 meets a 300-share sell, then a 1 500-share sell. What trades?
Solution
Solution of Exercise 9.2.
Nothing with the 300-share sell (below the minimum); 1 500 shares with the second. 3 500 remain resting.
Exercise 9.3 ★
A participant received 40 invitations and firmed up 28. What is its firm-up rate, and why does the venue care?
Solution
Solution of Exercise 9.3.
. Each lapsed invitation told the participant that a large contra existed without it trading: a low rate marks a participant who uses conditionals to fish for information, and the venue restricts it to protect the others.
Exercise 9.4 ★★
With ticks a share on a 100.00 stock, a pinger buys 500 shares ahead when the fund has bought 5 000 of 20 000. How much does that one trade cost the fund, in basis points of the whole order?
Solution
Solution of Exercise 9.4.
The trade raises by ticks, 0.25 basis points at 100.00, on the 15 000 shares still to buy: basis points of the order.
Exercise 9.5 ★★
In the simulation informed takers fill 6.3% of what they try in the dark and uninformed ones 17.5%. Explain the gap with Zhu’s argument.
Solution
Solution of Exercise 9.5.
Informed traders trade when is away from the mid and all on the same side; the dark liquidity they need, on the other side, was posted by patient uninformed traders at random, and the informed exhaust it. Uninformed takers arrive on both sides and find it more often.
Exercise 9.6 ★★
Show that 100 equal lit children of a 20 000-share order cost in own impact, and compute it.
Solution
Solution of Exercise 9.6.
Child of is followed by shares that pay its impact : . With , , : 4.95 ticks, 4.95 basis points at 100.00.
Exercise 9.7 ★★★
Coding. Rerun dark_min with a minimum of 200 instead of 1 000 on the sixteen seeds. Compare the leakage, the share filled in the dark, the completion time and the shortfall with both dark strategies.
Solution
Solution of Exercise 9.7.
A minimum of 200 still blocks the pinger’s 100-share probes: no leakage, the whole order fills in the dark, in about 1 020 seconds on average, at a shortfall of 7.0 basis points (standard error 0.9) against 12.5 for the unprotected peg and 9.5 for a minimum of 1 000; the drift is 13.6. A minimum just above the probe size keeps the protection and loses much less of the natural flow.
Exercise 9.8 ★★★
Find the flaw. “All our dark fills were at the midpoint, so our large order cost us nothing.”
Solution
Solution of Exercise 9.8.
Midpoint fills save the spread, not the rest: the price moved while the order was worked, because the order’s fills took flow out of the lit market and because others learnt of it. Measure the shortfall against the arrival price, the drift before completion and the counterparties’ mark-outs; in the simulation the unprotected dark order cost 12.5 basis points, all at the midpoint.
9.9 Problem: The Block That Leaked
Problem 9.1
Weekend problem — the block that leaked
A fund must buy 20 000 shares within 30 minutes and asks where to send the order. Answer with the simulated market.
Part I — The venues.
- What does a midpoint cross save, and where does its price come from?
- What does the dark engine need from the lit venue, and how does the simulator give it?
- Define a minimum execution quantity and give its two effects.
- Define a conditional order and a firm-up rate.
- Why does a lapsed invitation leak information?
Part II — Selection.
- State Zhu’s argument.
- Give the dark fill rates of informed and uninformed takers in the simulation.
- Compare the capture and 30-second move of resting fills in the dark and on the lit book.
- What did Comerton-Forde and Putnins find about block trades?
Part III — Four ways to buy.
- Describe the pinger and the leaky sellers.
- Derive the own-impact cost of the lit strategy.
- How is the leakage cost accounted?
- Give the shortfall, drift and accounted costs of the four strategies.
- Why does the unprotected dark order cost more than the lit one?
- What does the minimum quantity of 1 000 fix, and what does it cost?
Part IV — Venues and the verdict.
- Why are blocks cheap in the simulation, and when would they not be?
- Summarise the ITG, Barclays and Credit Suisse cases in one sentence each.
- What changed in the EU’s cap on dark trading?
- State the named result: the price drift before completion of a parent order worked in the dark against in the lit market, and the leakage cost in basis points.
- In one sentence: where should the fund send its order?
Solution
Solution of Problem 9.1.
1. Half the spread for each side; the lit market’s best bid and offer. 2. A current copy of the lit quotes: control N, sent after each change of the lit top. 3. The smallest fill a dark order accepts; it keeps small probing orders away and it reduces the fills. 4. A non-binding resting indication that must be firmed up when invited; the share of invitations a participant firms up. 5. Both sides learn that the contra exists, and one of them paid nothing to learn it. 6. Informed traders crowd on one side and face higher execution risk in the dark, so they prefer the exchange; uninformed ones prefer the dark. 7. 6.3% and 17.5%. 8. Dark: no capture, cents of move; lit providers: 0.51 cents of capture, of move. 9. No evidence that block trades in the dark impede price discovery. 10. The pinger probes every two seconds with 100 shares and trades 500 ahead after two fills in a row; 30% of block sellers never firm up and buy 2 000 ahead. 11. See exercise 6: 4.95 basis points. 12. each triggered trade ahead the fund’s shares still to fill, over the order’s size. 13. Lit 3.8, 7.3, 4.95 own impact; dark 12.5, 26.1, 10.9 leakage; dark with a minimum 9.5, 11.9, 1.4 own impact; block , , 0.6 leakage (standard errors 0.5 to 2.3). 14. The pinger found it 88 times and bought 44 000 shares ahead: the leak (10.9 basis points) is larger than the lit order’s own impact (4.95). 15. It stops the leak; only 46% fills in the dark and the rest is bought at the end. 16. Their sellers bring size that would not otherwise have traded; with leaky or informed counterparties, or when the block’s sellers would otherwise have sold on the lit book, they would not be. 17. ITG: an undisclosed desk traded against its dark pool’s subscribers using their live orders (USD 20.3 million). Barclays: misrepresented how it policed its pool (USD 70 million). Credit Suisse: misrepresented its scoring, took sub-penny orders and alerted high-frequency firms to customer orders (USD 84.3 million). 18. The double volume cap was replaced by a single volume cap on the reference price waiver, from 18 months after the MiFIR review’s entry into force. 19. Named result: over the 30-minute window the mid drifted 26.1 basis points against the unprotected dark order and 7.3 against the lit one, and the dark order’s accounted leakage cost 10.9 basis points; a minimum quantity above the probe size removed it. 20. To block venues with natural sellers first, and to the dark pool only behind a minimum quantity larger than any probe.
9.10 Interview questions
Interview question 9.1 ★ trader
What is a dark pool, and why would an institution use one?
Solution
Solution of Interview question 9.1.
A venue that displays no orders and usually crosses at the lit midpoint: an institution uses it to trade size without showing it, saving the spread and hoping to avoid impact.
What the interviewer is looking for: Midpoint; no display; size and leakage.
Interview question 9.2 ★★ trader
How would you protect a large resting dark order from being detected?
Solution
Solution of Interview question 9.2.
A minimum execution quantity above typical probe sizes, randomised and partial exposure across venues, avoiding venues with poor participant controls, conditionals only on venues that police firm-up rates, and monitoring fills for signs of probing.
What the interviewer is looking for: Minimum quantity; venue selection; monitoring.
Interview question 9.3 ★★ researcher
Do dark pools harm price discovery? Give the theory and the evidence.
Solution
Solution of Interview question 9.3.
Theory (Zhu): dark pools attract uninformed flow and can concentrate information on the exchange. Evidence (Comerton-Forde and Putnins): low levels of non-block dark trading are benign, high levels harmful, blocks not harmful.
What the interviewer is looking for: Selection argument; nonlinearity in the evidence.
Interview question 9.4 ★★ trader, researcher
How would you measure information leakage in your firm’s executions?
Solution
Solution of Interview question 9.4.
Compare the price drift while orders are worked with a benchmark of similar orders, the mark-outs of counterparties by venue, and the price moves after IOIs and invitations; randomise routing where possible to separate leakage from selection.
What the interviewer is looking for: Drift; counterparty mark-outs; a comparison group.
Interview question 9.5 ★★ developer
Design the matching logic of a conditional block venue. What state does it keep per order and per participant?
Solution
Solution of Interview question 9.5.
Per order: owner, side, size, minimum, time, whether it is in an open invitation. Per invitation: both orders, size, start time, who has firmed up. Per participant: invitations and firm-ups (the rate), and any restriction. Matching in time priority among free orders whose sizes meet both minimums.
What the interviewer is looking for: Invitation state; timer; participant scoring.
Interview question 9.6 ★★★ trader
Your midpoint fills look free, yet your shortfall on dark-heavy orders is higher than on lit ones. What is going on?
Solution
Solution of Interview question 9.6.
The midpoint saves the spread but the order leaked or took flow out of the lit market, and the price drifted while it was worked; measure the drift and the counterparties’ mark-outs, add a minimum quantity, and compare with lit and block executions of similar orders.
What the interviewer is looking for: Leakage and impact beyond the spread; how to measure them.