Waarom market makers geld verliezen door adverse selection
Ontdek waarom adverse selection de voornaamste oorzaak is van verliezen bij market makers. Leer hoe markout curves, inventory risk en queue position kosten de winstgevendheid bepalen.
Market makers verliezen geld door adverse selection: de handelaar die een offer wegneemt, is vaak degene die al weet dat dat offer verouderd is. Elke fill opent met een klein krediet, ongeveer de helft van de spread, en de seconden die volgen bepalen hoeveel van dat krediet overblijft. Het meetinstrument hiervoor is de markout, een gesigneerde prijsverandering op een vaste horizon na een fill. De onderstaande panelen bouwen echte markout-curves op basis van trade- en quote-prints. Ons bijbehorende artikel over hoe market makers geld verdienen behandelt de inkomstenzijde van hetzelfde grootboek.
Wat is adverse selection in de handel?
Een market maker plaatst twee prijzen tegelijk: een bid om te kopen en een offer om te verkopen, elk voor een opgegeven omvang. Het gat daartussen is de bid ask spread, en het vak is rekenwerk. Kopen op de bid, verkopen op de offer, tienduizenden keren per dag herhalen; de gemiddelde round trip levert iets op dat dicht bij de spread ligt.
Dat rekenwerk gaat ervan uit dat beide zijden in balans aankomen. Dat is niet zo. Een resting quote is een openstaande optie die iedereen op elk gewenst moment kan uitoefenen, en de handelaren die het meest opletten, kiezen de beste momenten. Een fonds dat een grote parent order uitvoert, blijft kopen terwijl de offer goedkoop blijft. Een systeem dat al heeft gezien dat een gecorreleerd instrument is bewogen, neemt de zijde die nog niet is herprijsd.
Adverse selection is de naam voor de scheefgroei in die mix: de fills die een maker ontvangt, zijn gewogen naar de handelaren die ze het hardst nodig hadden. Het symptoom is een gat tussen de spread die een maker quote en de spread die een maker overhoudt.
Wat is een markout in market making?
Een markout beantwoordt één vraag, gesteld na elke fill: waar stond de prijs een vast aantal seconden later, gemeten vanaf de zijde waar ik op zat? Stel dat een maker 100 aandelen verkoopt op $50,02 terwijl de midpoint op $50,00 staat. Die fill opent met twee cent per aandeel aan krediet, 20 mils in desk-eenheden, waarbij een mil een tiende van een cent is. Als de midpoint zestig seconden later is bewogen naar $50,04, dan is de 60-seconden markout min 20 mils. Het initiële krediet is verdwenen, en nog eens hetzelfde bedrag erbij.
Bereken het gemiddelde over elke fill in een venster en zet dit uit tegen de horizon, en het resultaat is een markout-curve. Het onderstaande paneel bouwt er een voor AAPL over een venster van drie uur rond het middaguur op donderdag 14 mei 2026. Elke print is gesigneerd ten opzichte van de midpoint van de seconde waarin deze werd geprint: een print boven de midpoint telt als een taker die koopt, wat de maker aan de verkoopzijde plaatst.
De exacte SQL achter elk getal
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.secsDe eerste reeks is het krediet op het moment van de fill, de afstand tussen de print en de midpoint, gemiddeld 19.66 mils per aandeel. De tweede reeks is wat diezelfde fills waard zijn zodra de midpoint tijd heeft gehad om te bewegen: 20.5 mils na één seconde, en 9.81 mils na vijf minuten. De afstand tussen de twee reeksen op elke horizon is de markout, en die komt uit de spread die de maker heeft gequote.
Een curve die snel daalt en daarna afvlakt, beschrijft een maker die betaalt voor de onmiddellijke herprijsing en de rest behoudt. Een curve die op elke horizon dezelfde helling blijft vertonen, beschrijft fills die aan de verkeerde kant landen van een prijs die blijft bewegen. De eerste vorm is een kostenpost van de bedrijfsvoering. De tweede is een quote die moet veranderen.
Welke fills zijn toxic flow?
Het woord toxic heeft hier een technische betekenis. Flow is toxic wanneer de markout-curve ervan tegen de maker in loopt die de fill heeft uitgevoerd, op elke horizon, over een grote steekproef. Desks sorteren fills op elk label dat ze kunnen zien: printomvang, venue, ordertype, tegenpartij-identificatie. Omvang is het label dat op de openbare tape staat.
De exacte SQL achter elk getal
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 onder de 100 aandelen openen met 19.47 mils per aandeel aan krediet en zijn een minuut later 15.22 mils waard. Prints van 1.000 aandelen en meer openen met 36.26 mils en zijn over dezelfde horizon 21.34 mils waard. Zelfde instrument, dezelfde drie uur, andere economie per aandeel. De grootste orders vermijden de openbare wachtrij vaak volledig, wat het doel is van een block trade.
Inventory risk, de positie die niet tijdig kan worden gehedged
Een markout-horizon is ook een klok. Een maker die 5.000 aandelen koopt op de bid, houdt 5.000 aandelen aan, en totdat de positie is gehedged of verkocht, is deze blootgesteld aan wat de prijs daarna ook doet. Hedging is zelden onmiddellijk: een positie in één aandeel kan worden gecompenseerd met een gecorreleerd ETF of een optiepositie, en elk daarvan brengt zijn eigen spread met zich mee om te overbruggen. Inventory risk is de omvang van de beweging die binnen dat venster past, en het wordt voor elk instrument op dezelfde manier gemeten. Hoe ver beweegt de prijs doorgaans over de volgende minuut, en over het volgende uur?
De exacte SQL achter elk getal
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.minsOver mei 2026 gemeten, bedroeg de gemiddelde absolute beweging in SPY over één minuut 1.9 basis points, waarbij een basis point een honderdste van een procent is. NVDA mat 5.5 over dezelfde minuut. Rek de klok op naar een uur en de twee cijfers worden 14.1 en 40.4. Een maker die binnen een minuut kan flattenen, leeft met het eerste paar. Een maker die een uur aanhoudt, leeft met het tweede paar, en het krediet dat bij de fill wordt geïnd is in beide gevallen identiek.
Waarom market makers geld verliezen achteraan in de wachtrij
Beurzen matchen resting orders tegen één prijs in de volgorde van aankomst: prijs eerst, dan tijd. Een order achteraan in een wachtrij van 40.000 aandelen op de bid wacht tot de 40.000 aandelen vóór de order zijn verwerkt, en het inschatten van de wachtrijpositie is een discipline op zich.
Het lastige is wat verwerken betekent. Een wachtrij raakt op twee manieren leeg. Verkopers blijven de bid raken totdat het niveau is uitgeput, of de prijs beweegt omlaag door het niveau heen en laat het achter zich. Een order vooraan in de rij neemt deel aan beide. Een order achteraan wordt grotendeels gevuld op de tweede manier, op het moment dat het niveau op het punt staat de oude prijs te worden. Twee makers kunnen hetzelfde instrument tegen dezelfde prijs verhandelen en er verschillende bedragen aan overhouden. De wachtrijpositie verschijnt nooit in de quoted spread, aangezien beide makers exact dezelfde prijs hebben gequote. Het verschijnt in de markout-curve.
Waarom het verbreden van de quote geen gratis oplossing is
Het voor de hand liggende antwoord op een slechte markout-curve is breder quoten. Een bredere quote levert meer op per fill en bereikt minder fills. Beide helften van die handel staan in de prints van dezelfde dag, gesorteerd op hoe ver elke print van de midpoint landde.
De exacte SQL achter elk getal
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 binnen een halve cent van de midpoint waren goed voor 27.58 procent van de aandelen in het venster, en waren een minuut later 0.95 mils per aandeel waard. Prints die meer dan twee cent erbuiten landden, waren goed voor 33.19 procent van de aandelen, tegen 46.86 mils. Een quote die verder van de midpoint wordt geplaatst, wordt bereikt door een kleiner deel van het dagvolume.
De fill rate is de eerste kostenpost van het terugstappen. Exchange rebates zijn de tweede, aangezien veel venues een maker per gevuld aandeel betalen en die inkomsten schalen met het aantal aandelen in plaats van met de breedte van de quote. De volumetiers die het rebate-tarief bepalen, worden maandelijks geteld, dus een rustige maand herprijst elke fill in de volgende maand. Het opgeven van de wachtrijpositie is de laatste kostenpost, betaald bij het verlaten en opnieuw betaald achteraan de rij bij het terugkeren. Elke maker bevindt zich ergens op deze curve, en degenen die hun eigen markouts het meest nauwkeurig meten, kunnen het dichtst bij de touch zitten en toch het krediet behouden. Die meting is de voorsprong die de grootste market makers verdedigen.
Veelgestelde vragen
Verliezen market makers geld op individuele transacties?
Regelmatig. Een making book is een verdeling van kleine winsten en kleine verliezen, en de verliezende fills clusteren op de momenten vlak voordat een prijs beweegt. De business rust op het gemiddelde over miljoenen fills.
Wat is een markout in de handel?
Een markout is de verandering in de marktprijs op een vaste horizon na een fill, gesigneerd vanuit het perspectief van één zijde, waarbij een positief getal betekent dat die zijde heeft gewonnen. Aandelendesks noteren markouts in mils per aandeel, en optiedesks in ticks per contract.
Wat betekent toxic order flow?
Het beschrijft order flow waarvan de markout-curve hardnekkig tegen de market maker in loopt die de fill uitvoert, wat betekent dat de prijs na elke fill verder weg blijft bewegen. Het label is een statistische eigenschap van een stroom orders en bevat geen oordeel over een individuele handelaar.
Waarom verbreden market makers spreads in plaats van hun quotes in te trekken?
Een bredere quote houdt een maker in de markt tegen een prijs die compenseert voor een slechtere markout-curve. Het intrekken van de quote levert niets op en geeft de wachtrijpositie prijs. Desks doen beide, en de keuze hangt af van hoe lang de quote naar verwachting verouderd zal blijven.
Hoe wordt adverse selection gemeten?
Met markouts. Signeer elke fill op basis van de zijde waar de maker op zat, en bereken daarna het gemiddelde van de midpoint-verandering op vaste horizons. Het gat tussen het krediet bij de fill en de waarde op elke horizon is de adverse selection-kostenpost, in dezelfde eenheden als de spread.
Hoe deze cijfers zijn opgebouwd
Elk AAPL-paneel leest twee openbare registers: de trade tape en de quote tape. Elke print tussen 14:00 en 17:00 UTC op 14 mei 2026 wordt gematcht met de gemiddelde national best bid and offer midpoint van de seconde waarin deze werd geprint, en vervolgens gesigneerd. Een print boven die midpoint telt als een taker buy, wat de maker aan de verkoopzijde plaatst. Prints precies op de midpoint hebben geen zijde en worden verwijderd, evenals elke print die meer dan 2 procent van de midpoint afwijkt. Quote-records waarbij de bid de offer ontmoet of kruist, worden uitgesloten, aangezien een locked of crossed market geen bruikbare midpoint heeft.
Matching op seconden-niveau benadert de quote die heerste op de microseconde van de fill, en het vlakt de snelste updates af. Horizon-prijzen komen van dezelfde midpoints op seconden-niveau. Het inventory-paneel gebruikt bars van één minuut en behoudt alleen bars met ten minste 50 prints, wat de steekproef concentreert in de drukste uren van de dag.
Elk paneel hier bevat de SQL die het heeft geproduceerd, dus de markout-wiskunde is regel voor regel inzichtelijk. Om de curve voor een andere naam of een andere dag opnieuw op te bouwen, kunt u er in gewoon Nederlands om vragen op de Strasmore-terminal.