为什么做市商会亏损:逆向选择
了解逆向选择如何侵蚀做市商利润,掌握 markout 曲线的衡量方法,并分析库存风险与排队位置成本,判断报价是否真正有利可图。
做市商会因逆向选择而亏损:主动买入卖价的交易者往往已经知道该报价过时。每笔成交开始时通常带来一笔小额收益,约为买卖价差的一半;随后几秒钟的价格变化,决定这笔收益能保留多少。
衡量工具是成交后价格偏离(markout)。它表示成交后固定时间窗口内、带方向的价格变动。下方图表根据成交和报价记录,绘制实际的成交后价格偏离曲线。我们的配套文章 做市商如何获利介绍了同一账本中的收入端。
交易中的逆向选择是什么?
做市商同时报出两个价格:一个是买入价,另一个是卖出价。每个价格都对应明确的报价数量。两者之间的差额称为买卖价差,这项业务的计算逻辑很简单。以买入价买入,再以卖出价卖出,每天重复数万次,平均每次往返交易获得的收益大致接近价差。
这种计算建立在买卖两方平衡的假设上。但实际并不平衡。挂出的报价相当于一项随时可被行使的选择权,任何人都可以在自己选择的时点成交,而最密切关注市场的交易者往往会挑选最有利的时机。一只基金执行大额母单时,如果卖出价仍然偏低,就会持续买入。某个相关工具已经出现价格变动后,交易系统会买入尚未重新定价的一方。
逆向选择就是对这种交易结构偏移的称呼:做市商获得的成交,更多来自最迫切希望成交的交易者。其表现是,做市商报出的价差与最终留存的价差之间存在差距。
做市中的 markout 是什么?
markout 回答的是一个问题,而且是在每次成交后提出的:从做市商所处的交易方向看,固定若干秒后,价格到了哪里?假设做市商以每股 50.02 美元卖出 100 股,当时中间价为 50.00 美元。这笔成交一开始带来每股 2 美分的价差收益,按交易台的单位计算为 20 mil;1 mil 是十分之一美分。如果 60 秒后中间价升至 50.04 美元,那么 60 秒 markout 就是负 20 mil。最初的价差收益消失了,而且又损失了同样的金额。
将某一时间窗口内的每笔成交取平均,并按观察期限绘制出来,得到的就是 markout 曲线。下方面板展示了 AAPL 在 2026 年 5 月 14 日星期四午间三个小时窗口内的曲线。每笔成交都根据其成交所在那一秒的中间价确定方向:高于中间价的成交计为主动买入,意味着做市商处于卖方。
每个数字背后的完整 SQL
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.secs第一条序列表示成交瞬间获得的价差收益,即成交价与中间价之间的距离,平均为每股 19.66 mil。第二条序列表示中间价移动一段时间后,这些成交的价值:成交后 1 秒为 20.5 mil,5 分钟后为 9.81 mil。在任何观察期限上,两条序列之间的距离就是 markout,它来自做市商报出的 spread。
曲线快速下行后趋于平缓,说明做市商为即时重新定价付出了代价,但保留了剩余价差。曲线在所有观察期限上都以相近斜率持续下行,说明这些成交始终处在持续变动价格的不利一侧。前一种形态是正常经营成本。后一种形态说明报价需要调整。
哪些成交属于有毒流量?
这里的“有毒”是一个技术术语。若做市商成交后,在大样本下的各个观察期限内,成交标的的markout曲线都朝不利于该做市商的方向倾斜,那么这类流量就是有毒流量。交易台会根据所有可见标签对成交进行分类,包括成交笔数、交易场所、订单类型和交易对手方标识。成交规模是公开行情记录中带有的标签。
每个数字背后的完整 SQL
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)成交量低于100股的成交,开盘时每股获得19.47毫的价差收益;一分钟后,每股价值为15.22毫。成交量达到1,000股及以上的成交,开盘时每股获得36.26毫;在相同观察期限内,每股价值为21.34毫。同一工具、同样的三个小时,每股经济结果却不同。最大额订单往往完全避开公开队列,这正是大宗交易安排实现的目的。
库存风险:无法及时对冲的头寸
Markout期限也是一只时钟。做市商以买价买入5,000股后,就持有5,000股。在对冲或卖出头寸前,该头寸都会暴露于价格接下来的变动。对冲很少能即时完成:单只股票头寸可以用相关ETF或期权头寸进行抵消,而这些工具各自都存在需要支付的spread。库存风险,是在这段时间窗口内可能发生的价格变动幅度;对任何股票而言,其衡量方式都相同。价格在接下来一分钟内通常会移动多远?在接下来一小时内又会移动多远?
每个数字背后的完整 SQL
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.mins在2026年5月,SPY一分钟内的平均绝对变动为1.9个基点;一个基点是百分之一的百分之一。同期,NVDA一分钟内的平均绝对变动为5.5个基点。将时间窗口延长至一小时后,这两个数值分别变为14.1和40.4。能够在一分钟内将头寸压平的做市商,面对的是第一组数值。持仓一小时的做市商,面对的是第二组数值;但无论哪种情况,成交时收取的价差收益都相同。
为什么做市商排在队尾时会亏钱
交易所会按照挂单到达的先后顺序撮合同一价格的剩余订单:先看价格,再看时间。买价一侧有40,000股排队时,排在队尾的订单要等前面的40,000股全部成交。估算排队位置本身也是一门专业。
关键在于,队列清空究竟意味着什么。队列有两种清空方式。卖方持续击穿买价,直到该价位的订单全部成交;或者价格向下穿过该价位,将该价位留在后方。排在队首附近的订单,两种情况下都可能成交。排在队尾的订单,大多在第二种情况下成交,也就是该价位即将变成旧价格的时刻。两家做市商可以在同一价格交易同一工具,但最终持有的数量不同。排队位置不会出现在报价价差中,因为两家做市商报出的价格完全相同。它会体现在成交后价格走势曲线中。
为什么扩大报价并非免费修复方案
面对糟糕的成交后价格曲线,最直接的做法是扩大报价价差。报价越宽,每笔成交带来的收益越高,但成交笔数越少。这两个结果都会体现在当天的成交记录中。成交记录按成交价距离中间价的幅度排序。
每个数字背后的完整 SQL
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)成交价距离中间价不超过半美分的成交,占窗口期成交股数的 27.58%,一分钟后每股价值 0.95 mils。成交价偏离中间价超过两美分的成交,占成交股数的 33.19%,每股为 46.86 mils。距离中间价更远的报价,只能获得当天成交量中较小的一部分。
撤回报价的第一项成本是成交率下降。第二项成本是交易所返佣。许多交易场所会按每股成交量向做市方支付返佣,而返佣收入取决于成交股数,不取决于报价宽度。决定返佣率的成交量档位按月统计,因此一个清淡月份会重新确定下个月每笔成交的返佣。放弃队列位置是最后一项成本。撤单时要付出这一成本,重新挂回队尾时还要再付一次。每个做市方都处在这条曲线的某个位置。能够最精确衡量自身成交后价格表现的做市方,可以更靠近最优报价,同时保留这项收益。这种衡量能力,正是最大型做市商所守住的优势。
常见问题
做市商会在单笔交易中亏损吗?
会,而且经常发生。做市账簿由大量小额盈利和小额亏损组成。亏损成交往往集中在价格即将变动之前。做市业务依靠数百万笔成交的平均结果获利。
交易中的markout是什么?
markout是成交后固定时间窗口内市场价格的变化。计算时从某一方的视角确定方向,正数表示该方获利。股票交易台通常以每股千分之一报价markout,期权交易台则以每张合约的tick计价。
什么是有毒订单流?
它指的是一类订单流:做市商完成成交后,markout曲线持续朝不利于做市商的方向移动,也就是价格在每次成交后继续远离成交方向。这个标签描述的是一组订单流的统计特征,并不针对任何单个交易者作出评价。
做市商为什么扩大spread,而不是撤掉报价?
扩大报价可以让做市商继续留在市场中,并通过更高的价格补偿较差的markout曲线。撤掉报价不会带来收益,还会放弃排队位置。交易台会根据情况采取这两种做法,关键取决于报价预计会过时多久。
如何衡量逆向选择?
使用markout衡量。首先根据做市商所处的买卖方向,为每笔成交确定符号;然后计算成交后各个固定时间窗口内的中间价变化平均值。成交时获得的价差收入与各时间窗口对应价值之间的差额,就是逆向选择成本,单位与spread相同。
这些数据如何构建
每个AAPL面板读取两份公开记录:成交记录和报价记录。将2026年5月14日14:00至17:00 UTC之间的每笔成交,与该成交所在秒的全国最佳买卖报价中间价均值进行匹配,然后确定方向。高于该中间价的成交计为主动买入,此时做市商处于卖方。恰好等于中间价的成交不带有买卖方向,因此予以剔除;距中间价超过2%的成交也一并剔除。买价等于或高于卖价的报价记录会被排除,因为锁定或交叉市场没有可用的中间价。
按秒进行的第二层匹配,可以近似还原成交发生时的报价,并平滑最快速的报价更新。各时间窗口的价格也来自同一组按秒计算的中间价。库存面板使用一分钟K线,并只保留至少包含50笔成交的K线,因此样本主要集中在当天交易最活跃的时段。
这里的每个面板都附有生成它的SQL,因此markout计算过程可以逐行检查。若要在其他股票或其他日期重建这条曲线,请在Strasmore终端中用自然语言提出请求。