Trade Markout na Wetin? Execution Quality Explain
Trade markout na change for mid price after fill. See the sign convention, adverse selection, and markout curve from one second reach five minutes.
Trade markout na the change wey happen for mid price over fixed time after fill, measured from the exact moment wey that fill print. Positive mean say market move for your side after you trade. Negative mean say e move against you, and na this one desks dey call adverse selection. The horizon wey you choose, whether one second or five minutes, dey determine the question wey the number dey answer.
Trade markout na wetin?
Start with mid price: na the halfway point between best bid and best offer, the midpoint of NBBO. Markout takes that mid for chosen horizon after your fill, subtracts reference price, then e apply sign based on the side wey you trade.
**markout at horizon h = side * (mid at t+h - reference price)**, where side na plus one if you buy and minus one if you sell.
Na the sign convention dey cause confusion most times. If you buy and mid later fall, markout go negative: you buy, price go down, and the person wey sell to you get better result for that trade. Na adverse selection written as number. If you sell and mid later fall, markout go positive because the sign change with the side. Every fill get two sides, and one side markout na the other side own with the sign reversed.
The three reference prices
The reference price wey you subtract dey decide wetin the markout dey measure.
- The fill price. Markout become money: wetin the position worth at t+h compared with wetin you pay. The spread wey you pay or earn dey inside am.
- The mid at the moment of the fill. This one remove the spread and isolate how market move after you trade. Na the cleanest way to read adverse selection.
- The quote on the side you traded. If you measure against the touch wey you take, or the touch wey you post, e show how the fill compare with the price wey actually dey available.
Execution quality work dey use the second one for adverse selection and the first one for profit and loss. Both dey show for the first panel below, using one set of fills.
The markout curve and wetin the shape mean
Run the same statistic across many horizons and you go get curve. The shape fit tell you more than any single number.
- Curve wey drop sharply inside the first second and remain down dey describe flow wey market don pick off: price move against the fill almost immediately.
- Curve wey continue to fall for minutes dey show flow wey carry real information about where price dey go.
- Flat curve near zero dey describe benign flow. After five minutes, mid still look like how e look when the fill happen.
- Curve wey start negative and climb back toward zero na the shape passive maker wey dey collect rebates dey look for. The early dip na the spread plus immediate impact, while the recovery na market coming back.
Choosing horizon na itself decision about wetin you dey measure. Below one second, markout mostly dey read latency and queue position. If you stretch am to one minute, e dey read the short-term information inside the flow. Past five minutes, normal market drift fit start to overwhelm the fill itself.
Real markout curve, fill by fill
The panel below takes every INTC print from the June 10, 2026 regular session, classify each one as buy initiated or sell initiated against the last quote of the second before e print, then average the signed markout at 5 horizons. Two series dey use the same fills: one measured from the mid at fill, and one from the fill price.
The exact SQL behind every number
WITH
mid_by_second AS
(
SELECT
dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
argMax((toFloat64(bid_price) + toFloat64(ask_price)) / 2, sip_timestamp) AS mid
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'INTC'
AND sip_timestamp >= toDateTime('2026-06-10 13:30:00', 'UTC')
AND sip_timestamp < toDateTime('2026-06-10 20:00:00', 'UTC')
AND bid_price > 0
AND ask_price > bid_price
GROUP BY sec
),
signed_fills AS
(
SELECT
t.sec AS sec,
t.fill_price AS fill_price,
q.mid AS ref_mid,
if(t.fill_price > q.mid, 1, -1) AS side
FROM
(
SELECT
dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
sec - 1 AS ref_sec,
toFloat64(price) AS fill_price
FROM global_markets.stocks_trades
WHERE ticker = 'INTC'
AND sip_timestamp >= toDateTime('2026-06-10 13:30:01', 'UTC')
AND sip_timestamp < toDateTime('2026-06-10 19:55:00', 'UTC')
AND price > 0
AND size > 0
) AS t
INNER JOIN mid_by_second AS q ON q.sec = t.ref_sec
WHERE t.fill_price != q.mid
)
SELECT
multiIf(f.horizon_s < 60,
concat(toString(f.horizon_s), ' sec'),
concat(toString(intDiv(f.horizon_s, 60)), ' min')) AS horizon,
round(avg(f.side * (fut.mid - f.ref_mid) / f.ref_mid) * 10000, 3) AS mid_basis_bps,
round(avg(f.side * (fut.mid - f.fill_price) / f.fill_price) * 10000, 3) AS fill_basis_bps,
count() AS fill_count
FROM
(
SELECT
sec,
fill_price,
ref_mid,
side,
horizon_s,
sec + horizon_s AS future_sec
FROM signed_fills
ARRAY JOIN [1, 5, 15, 60, 300] AS horizon_s
) AS f
INNER JOIN mid_by_second AS fut ON fut.sec = f.future_sec
GROUP BY f.horizon_s
ORDER BY f.horizon_sAcross 900593 classified fills, the mid basis series read 3.068 basis points at 1 sec and 2.977 basis points at 5 min. Basis point na one hundredth of one percent of the price, so one fill fit move by rounding error, but a million shares fit mean real money.
The fill basis series open at -0.488 basis points. The gap between the two series at the shortest horizon na effective half spread: how far the print land from the mid. Taker pay that one on entry, while maker earn am. Everything after the first horizon na market movement.
Fill size and the shape of the curve
Adverse selection no dey affect all fills the same way. If you split the same session by print size, small fills and blocks of one thousand shares or more go dey for the same axes.
The exact SQL behind every number
WITH
mid_by_second AS
(
SELECT
dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
argMax((toFloat64(bid_price) + toFloat64(ask_price)) / 2, sip_timestamp) AS mid
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'INTC'
AND sip_timestamp >= toDateTime('2026-06-10 13:30:00', 'UTC')
AND sip_timestamp < toDateTime('2026-06-10 20:00:00', 'UTC')
AND bid_price > 0
AND ask_price > bid_price
GROUP BY sec
),
signed_fills AS
(
SELECT
t.sec AS sec,
t.fill_size AS fill_size,
q.mid AS ref_mid,
if(t.fill_price > q.mid, 1, -1) AS side
FROM
(
SELECT
dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
sec - 1 AS ref_sec,
toFloat64(price) AS fill_price,
size AS fill_size
FROM global_markets.stocks_trades
WHERE ticker = 'INTC'
AND sip_timestamp >= toDateTime('2026-06-10 13:30:01', 'UTC')
AND sip_timestamp < toDateTime('2026-06-10 19:55:00', 'UTC')
AND price > 0
AND size > 0
) AS t
INNER JOIN mid_by_second AS q ON q.sec = t.ref_sec
WHERE t.fill_price != q.mid
)
SELECT
multiIf(f.horizon_s < 60,
concat(toString(f.horizon_s), ' sec'),
concat(toString(intDiv(f.horizon_s, 60)), ' min')) AS horizon,
round(avgIf(f.side * (fut.mid - f.ref_mid) / f.ref_mid, f.fill_size < 1000) * 10000, 3) AS small_fill_bps,
round(avgIf(f.side * (fut.mid - f.ref_mid) / f.ref_mid, f.fill_size >= 1000) * 10000, 3) AS block_fill_bps,
countIf(f.fill_size >= 1000) AS block_fill_count
FROM
(
SELECT
sec,
fill_size,
ref_mid,
side,
horizon_s,
sec + horizon_s AS future_sec
FROM signed_fills
ARRAY JOIN [1, 5, 15, 60, 300] AS horizon_s
) AS f
INNER JOIN mid_by_second AS fut ON fut.sec = f.future_sec
GROUP BY f.horizon_s
HAVING countIf(f.fill_size < 1000) > 0
AND countIf(f.fill_size >= 1000) > 0
ORDER BY f.horizon_sAt 5 min horizon, prints below one thousand shares average 2.983 basis points, while 11588 prints of one thousand shares or more average 2.495. Two quotes wey fill the same total volume against those two groups no go finish the day for the same place.
How markouts become the spread numbers for execution reports
Markout na the missing term inside standard spread decomposition. Effective spread na wetin taker actually pay: twice the signed distance from mid to print. Split am into two. One part na realized spread, wetin maker keep after market don move. The other part na adverse selection, wey be mid basis markout multiplied by two. The identity exact: effective spread = realized spread + adverse selection.
The exact SQL behind every number
WITH
mid_by_second AS
(
SELECT
dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
argMax((toFloat64(bid_price) + toFloat64(ask_price)) / 2, sip_timestamp) AS mid
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'INTC'
AND sip_timestamp >= toDateTime('2026-06-10 13:30:00', 'UTC')
AND sip_timestamp < toDateTime('2026-06-10 20:00:00', 'UTC')
AND bid_price > 0
AND ask_price > bid_price
GROUP BY sec
),
signed_fills AS
(
SELECT
t.sec + 60 AS future_sec,
t.et_time AS et_time,
t.fill_price AS fill_price,
q.mid AS ref_mid,
if(t.fill_price > q.mid, 1, -1) AS side
FROM
(
SELECT
dateDiff('second', toDateTime('2026-06-10 13:30:00', 'UTC'), sip_timestamp) AS sec,
sec - 1 AS ref_sec,
toFloat64(price) AS fill_price,
formatDateTime(toStartOfInterval(toTimeZone(sip_timestamp, 'America/New_York'), toIntervalMinute(30)), '%H:%i') AS et_time
FROM global_markets.stocks_trades
WHERE ticker = 'INTC'
AND sip_timestamp >= toDateTime('2026-06-10 13:30:01', 'UTC')
AND sip_timestamp < toDateTime('2026-06-10 19:55:00', 'UTC')
AND price > 0
AND size > 0
) AS t
INNER JOIN mid_by_second AS q ON q.sec = t.ref_sec
WHERE t.fill_price != q.mid
)
SELECT
f.et_time AS et_time,
round(avg(2 * f.side * (f.fill_price - f.ref_mid) / f.ref_mid) * 10000, 3) AS effective_spread_bps,
round(avg(2 * f.side * (f.fill_price - fut.mid) / f.ref_mid) * 10000, 3) AS realized_spread_bps,
round(avg(2 * f.side * (fut.mid - f.ref_mid) / f.ref_mid) * 10000, 3) AS adverse_selection_bps,
count() AS fill_count
FROM signed_fills AS f
INNER JOIN mid_by_second AS fut ON fut.sec = f.future_sec
GROUP BY f.et_time
ORDER BY f.et_timeFor the half hour wey start at 09:30 Eastern, effective spread average 10.651 basis points. Out of this, 8.313 na adverse selection term at a sixty-second horizon, while 2.338 na wetin maker retain. The panel cover 13 half-hour buckets.
Na these components dem dey summarize venue by venue for Rule 605 and 606 execution reports, and na the arithmetic behind price improvement claims wey dey rely on the sub-penny rule and price improvement. Rebate na fixed credit per share. Adverse selection na variable cost per share on fills wey quote actually receive. To weigh one against the other over measured curve, instead of headline rate card, na the check behind maker-taker fees and rebates, and e dey alongside the mechanics for why market makers lose money.
How dem compute these numbers
Every panel dey use INTC quotes and prints from the June 10, 2026 regular session, 09:30 to 16:00 Eastern. Quotes collapse to one mid per second, using the last one printed inside that second. Print classify as buy initiated when e land above the mid of the previous second, and sell initiated when e land below am. Na the standard quote rule. Prints wey sit exactly on that mid dem drop instead of guessing, so midpoint executions no enter the sample. Using the previous second mid as reference stop the reference from peeking forward. Horizons na whole seconds counted from the second of the print, and fill enter a horizon only when quote dey for the target second.
FAQ
Wetin be markout for trading?
Markout na the signed change for mid price over fixed horizon after fill. Positive mean say market move for the direction of your trade after you get filled. Negative mean say e move the other way, and na the definition of adverse selection.
Negative markout always mean say fill bad?
No. Negative markout at one second on a marketable order mostly na the spread wey the order pay, which na the price of getting execution immediately. The more important thing na whether the curve continue to fall at longer horizons or flatten out.
Wetin be the difference between markout and slippage?
Slippage compare fill with decision price or arrival price, so e grade the whole path of an order. Markout compare fill with mid at a horizon after fill, so e grade wetin happen next. One score the parent order; the other score the individual fill.
Which horizon markout suppose use?
E depend on wetin the fill dey for. Sub-second horizons grade latency-sensitive execution, while one minute na common default for adverse selection on liquid names. Publishing the horizon beside the number na wetin make two markouts comparable at all.
How markout relate to effective spread?
Effective spread split into realized spread plus adverse selection component, and that component na mid basis markout multiplied by two. If horizon change, the split between the two go change too. Na why published spread statistic no complete unless e show the horizon.
Every panel here come with the SQL wey produce am. Open one, change the ticker or date, and the same markout curve go rebuild from scratch on the Strasmore terminal.