Why Market Makers Lose Money: Adverse Selection
Why do market makers lose money? Adverse selection is the main channel. See how markout curves measure it, plus inventory risk and queue position costs.
Market makers lose money on adverse selection: the trader who lifts an offer is often the one who already knows that offer is stale. Every fill opens with a small credit, roughly half the spread, and the seconds that follow decide how much of that credit survives. The measurement tool is the markout, a signed price change at a fixed horizon after a fill, and the panels below build real markout curves out of trade and quote prints. Our companion piece on how market makers make money covers the revenue side of the same ledger.
What is adverse selection in trading?
A market maker posts two prices at once: a bid to buy and an offer to sell, each good for a stated size. The gap between them is the bid ask spread, and the business is arithmetic. Buy at the bid, sell at the offer, repeat tens of thousands of times a day, and the average round trip collects something close to the spread.
That arithmetic assumes the two sides arrive in balance. They do not. A resting quote is a standing option that anyone may exercise at a moment of their own choosing, and the traders paying closest attention pick the best moments. A fund working a large parent order keeps buying while the offer sits cheap. A system that has already seen a correlated instrument move takes the side that has not repriced yet.
Adverse selection is the name for the tilt in that mix: the fills a maker receives are weighted toward the traders who wanted them most. The symptom is a gap between the spread a maker quotes and the spread a maker keeps.
What is a markout in market making?
A markout answers one question, asked after every fill: where was the price a fixed number of seconds later, measured from the side I was on? Suppose a maker sells 100 shares at $50.02 while the midpoint sits at $50.00. That fill opens with two cents per share of credit, 20 mils in desk units, where a mil is one tenth of a cent. If the midpoint has moved to $50.04 sixty seconds later, the 60 second markout is minus 20 mils. The opening credit is gone, and the same amount again with it.
Average that across every fill in a window and plot it against the horizon, and the result is a markout curve. The panel below builds one for AAPL over a three hour midday window on Thursday, May 14, 2026. Each print is signed against the midpoint of the second it printed in: a print above the midpoint counts as a taker buying, which puts the maker on the sell side.
The exact SQL behind every number
WITH
qs AS (
SELECT toUnixTimestamp(toDateTime(sip_timestamp)) AS ts,
avg((toFloat64(bid_price) + toFloat64(ask_price)) / 2) AS mid
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-05-14 14:00:00'
AND sip_timestamp < '2026-05-14 17:06:00'
AND bid_price > 0 AND ask_price > bid_price
GROUP BY ts
),
fills AS (
SELECT t.ts AS ts, t.px AS px, t.shares AS shares, q.mid AS mid_at_fill,
if(t.px > q.mid, 1, -1) AS taker_side
FROM (
SELECT toUnixTimestamp(toDateTime(sip_timestamp)) AS ts,
toFloat64(price) AS px, toUInt64(size) AS shares
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-05-14 14:00:00'
AND sip_timestamp < '2026-05-14 17:00:00'
AND size > 0
) AS t
INNER JOIN qs AS q ON q.ts = t.ts
WHERE t.px != q.mid AND abs(t.px / q.mid - 1) < 0.02
)
SELECT
concat('+', toString(e.secs), 's') AS horizon,
round(1000 * avg(e.taker_side * (e.px - e.mid_at_fill)), 2) AS edge_at_fill_mils,
round(1000 * avg(e.taker_side * (e.px - f.mid)), 2) AS edge_after_mils
FROM (
SELECT toUInt32(ts + secs) AS future_ts, secs, px, mid_at_fill, taker_side
FROM (SELECT *, arrayJoin([1, 5, 15, 30, 60, 300]) AS secs FROM fills)
) AS e
INNER JOIN qs AS f ON f.ts = e.future_ts
GROUP BY e.secs
ORDER BY e.secsThe first series is the credit at the instant of the fill, the distance between the print and the midpoint, averaging 19.66 mils per share. The second series is what those same fills are worth once the midpoint has had time to move: 20.5 mils one second out, and 9.81 mils five minutes out. The distance between the two series at any horizon is the markout, and it comes out of the spread the maker quoted.
A curve that drops quickly and then flattens describes a maker paying for the immediate repricing and keeping the remainder. A curve that keeps sloping the same way at every horizon describes fills that land on the wrong side of a price that keeps going. The first shape is a cost of doing business. The second is a quote that needs to change.
Which fills are toxic flow?
The word toxic is doing a technical job here. Flow is toxic when its markout curve slopes against the maker who filled it, at every horizon, over a large sample. Desks sort fills by every label they can see: print size, venue, order type, counterparty identifier. Size is the label carried in the public tape.
The exact SQL behind every number
WITH
qs AS (
SELECT toUnixTimestamp(toDateTime(sip_timestamp)) AS ts,
avg((toFloat64(bid_price) + toFloat64(ask_price)) / 2) AS mid
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-05-14 14:00:00'
AND sip_timestamp < '2026-05-14 17:06:00'
AND bid_price > 0 AND ask_price > bid_price
GROUP BY ts
),
fills AS (
SELECT t.ts AS ts, t.px AS px, t.shares AS shares, q.mid AS mid_at_fill,
if(t.px > q.mid, 1, -1) AS taker_side
FROM (
SELECT toUnixTimestamp(toDateTime(sip_timestamp)) AS ts,
toFloat64(price) AS px, toUInt64(size) AS shares
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-05-14 14:00:00'
AND sip_timestamp < '2026-05-14 17:00:00'
AND size > 0
) AS t
INNER JOIN qs AS q ON q.ts = t.ts
WHERE t.px != q.mid AND abs(t.px / q.mid - 1) < 0.02
)
SELECT
multiIf(s.shares < 100, 'under 100 shares',
s.shares < 500, '100 to 499',
s.shares < 1000, '500 to 999',
'1,000 or more') AS size_bucket,
count() AS fills_count,
round(1000 * avg(s.taker_side * (s.px - s.mid_at_fill)), 2) AS edge_at_fill_mils,
round(1000 * avg(s.taker_side * (s.px - f.mid)), 2) AS edge_after_60s_mils
FROM (SELECT *, toUInt32(ts + 60) AS future_ts FROM fills) AS s
INNER JOIN qs AS f ON f.ts = s.future_ts
GROUP BY size_bucket
ORDER BY min(s.shares)Fills under 100 shares open with 19.47 mils per share of credit and are worth 15.22 mils a minute later. Prints of 1,000 shares and up open with 36.26 mils and are worth 21.34 mils over the same horizon. Same instrument, same three hours, different economics per share. The largest orders often avoid the public queue altogether, which is what a block trade is arranged to do.
Inventory risk, the position that cannot be hedged in time
A markout horizon is also a clock. A maker who buys 5,000 shares at the bid holds 5,000 shares, and until the position is hedged or sold it is exposed to whatever the price does next. Hedging is rarely instant: a single stock position can be offset with a correlated ETF or an options position, and each of those carries its own spread to cross. Inventory risk is the size of the move that fits inside that window, and it is measured the same way for any name. How far does the price typically travel over the next minute, and over the next hour?
The exact SQL behind every number
WITH
bars AS (
SELECT ticker, window_start,
toDate(toTimeZone(window_start, 'America/New_York')) AS et_date,
toFloat64(close) AS px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'NVDA')
AND window_start >= '2026-05-01 00:00:00'
AND window_start < '2026-06-01 00:00:00'
AND transactions >= 50
AND close > 0
),
starts AS (
SELECT ticker, et_date, px, mins,
window_start + toIntervalMinute(mins) AS future_start
FROM (SELECT *, arrayJoin([1, 2, 5, 15, 30, 60]) AS mins FROM bars)
)
SELECT
concat(toString(s.mins), ' min') AS hold_horizon,
round(avgIf(abs(f.px / s.px - 1) * 10000, s.ticker = 'SPY'), 1) AS spy_drift_bps,
round(avgIf(abs(f.px / s.px - 1) * 10000, s.ticker = 'NVDA'), 1) AS nvda_drift_bps
FROM starts AS s
INNER JOIN bars AS f
ON f.ticker = s.ticker AND f.et_date = s.et_date AND f.window_start = s.future_start
GROUP BY s.mins
HAVING countIf(s.ticker = 'SPY') > 0 AND countIf(s.ticker = 'NVDA') > 0
ORDER BY s.minsAcross May 2026, the average absolute move in SPY over one minute measured 1.9 basis points, where a basis point is one hundredth of one percent. NVDA measured 5.5 over the same minute. Stretch the clock to an hour and the two figures become 14.1 and 40.4. A maker who can flatten inside a minute lives with the first pair. A maker holding an hour lives with the second pair, and the credit collected at the fill is identical either way.
Why market makers lose money at the back of the queue
Exchanges match resting orders at one price in the order they arrived: price first, then time. An order at the back of a 40,000 share queue at the bid waits for the 40,000 shares ahead of it to clear, and estimating queue position is a discipline of its own.
The awkward part is what clearing means. A queue empties in two ways. Sellers keep hitting the bid until the level is exhausted, or the price moves down through the level and leaves it behind. An order near the front takes part in both. An order at the back fills mostly on the second path, at the moment the level is about to become the old price. Two makers can trade the same instrument at the same price and keep different amounts of it. Queue slot never appears in the quoted spread, since both makers quoted the identical price. It appears in the markout curve.
Why widening the quote is not a free fix
The obvious answer to a bad markout curve is to quote wider. A wider quote earns more per fill and reaches fewer fills. Both halves of that trade sit in the same day's prints, sorted by how far each print landed from the midpoint.
The exact SQL behind every number
WITH
qs AS (
SELECT toUnixTimestamp(toDateTime(sip_timestamp)) AS ts,
avg((toFloat64(bid_price) + toFloat64(ask_price)) / 2) AS mid
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-05-14 14:00:00'
AND sip_timestamp < '2026-05-14 17:06:00'
AND bid_price > 0 AND ask_price > bid_price
GROUP BY ts
),
fills AS (
SELECT t.ts AS ts, t.px AS px, t.shares AS shares, q.mid AS mid_at_fill,
if(t.px > q.mid, 1, -1) AS taker_side
FROM (
SELECT toUnixTimestamp(toDateTime(sip_timestamp)) AS ts,
toFloat64(price) AS px, toUInt64(size) AS shares
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-05-14 14:00:00'
AND sip_timestamp < '2026-05-14 17:00:00'
AND size > 0
) AS t
INNER JOIN qs AS q ON q.ts = t.ts
WHERE t.px != q.mid AND abs(t.px / q.mid - 1) < 0.02
)
SELECT
multiIf(s.cents <= 0.5, '0.5 cents or less',
s.cents <= 1.0, '0.5 to 1 cent',
s.cents <= 2.0, '1 to 2 cents',
'over 2 cents') AS distance_from_mid,
round(100 * sum(s.shares) / sum(sum(s.shares)) OVER (), 2) AS share_of_volume_pct,
round(1000 * avg(s.taker_side * (s.px - f.mid)), 2) AS edge_after_60s_mils
FROM (
SELECT *, toUInt32(ts + 60) AS future_ts, abs(px - mid_at_fill) * 100 AS cents
FROM fills
) AS s
INNER JOIN qs AS f ON f.ts = s.future_ts
GROUP BY distance_from_mid
ORDER BY min(s.cents)Prints within half a cent of the midpoint accounted for 27.58 percent of the shares in the window, worth 0.95 mils per share a minute later. Prints landing more than two cents out accounted for 33.19 percent of the shares, at 46.86 mils. A quote posted farther from the midpoint is reached by a smaller share of the day's volume.
Fill rate is the first cost of stepping back. Exchange rebates are the second, since many venues pay a maker per share filled and that income scales with shares rather than with the width of the quote. The volume tiers that set the rebate rate are counted monthly, so a quiet month reprices every fill in the next one. Giving up the queue slot is the last cost, paid on the way out and paid again at the back of the line on the way in. Every maker sits somewhere on this curve, and the ones measuring their own markouts most precisely can sit closest to the touch and still keep the credit. That measurement is the edge the largest market makers defend.
FAQ
Do market makers lose money on individual trades?
Routinely. A making book is a distribution of small gains and small losses, and the losing fills cluster in the moments just before a price moves. The business rests on the average across millions of fills.
What is a markout in trading?
A markout is the change in the market price at a fixed horizon after a fill, signed from the point of view of one side, where a positive number means that side gained. Equities desks quote markouts in mils per share, and options desks in ticks per contract.
What does toxic order flow mean?
It describes order flow whose markout curve slopes persistently against the market maker filling it, meaning the price keeps moving away after each fill. The label is a statistical property of a stream of orders, and it carries no judgment about any single trader.
Why do market makers widen spreads instead of pulling their quotes?
A wider quote keeps a maker in the market at a price that pays for a worse markout curve. Pulling the quote earns nothing and surrenders the queue position along with it. Desks do both, and the choice turns on how long the quote is expected to stay stale.
How is adverse selection measured?
With markouts. Sign each fill by the side the maker was on, then average the midpoint change at fixed horizons afterwards. The gap between the credit at the fill and the value at each horizon is the adverse selection cost, in the same units as the spread.
How these numbers were built
Every AAPL panel reads two public records: the trade tape and the quote tape. Each print between 14:00 and 17:00 UTC on May 14, 2026 is matched to the average national best bid and offer midpoint of the second it printed in, then signed. A print above that midpoint counts as a taker buy, which places the maker on the sell side. Prints exactly at the midpoint carry no side and are dropped, along with any print more than 2 percent away from the midpoint. Quote records where the bid meets or crosses the offer are excluded, since a locked or crossed market has no usable midpoint.
Second level matching approximates the quote prevailing at the microsecond of the fill, and it smooths the fastest updates. Horizon prices come from the same second level midpoints. The inventory panel uses one minute bars and keeps only bars carrying at least 50 prints, which concentrates the sample in the busiest hours of the day.
Every panel here carries the SQL that produced it, so the markout math is open to inspection line by line. To rebuild the curve on a different name or a different day, ask for it in plain English on the Strasmore terminal.