周二上午 11:14,某沪上 私募 量化 团队的研究员刚跑完 沪深300 ETF(510300)上 5 秒级订单流信号的回测:样本内 Sharpe 5.2,样本外 Sharpe 4.8。基金经理盯着权益曲线只问一句:「上规模交易会发生什么?」研究员不知道——回测假设每一笔成交都按中价(mid)拿到、零市场冲击。在 200,000 份的元订单(metaorder)量级下,平方根法则预测约 6bp 的永久性冲击,而信号每个周期产生的优势只有 8bp。这套策略在纸面上是真的、在生产中不赚钱。所有的厘从微观结构里来,也从微观结构里走。本课要教的,是 4.2-4.5 每一个 alpha 与执行决策的基础——五个锚点:价差、最小变动单位、订单流不平衡、市场冲击、队列位置。
买卖价差:三种可量度变体
价差不是一个数字,是三个。每个度量的对象不同:
1. quoted spread s_q(t) = best_ask(t) - best_bid(t)
2. effective spread s_e(t) = 2 * |trade_price(t) - mid(t^-)| # mid just before the trade
3. realised spread s_r(t) = 2 * D(t) * (trade_price(t) - mid(t + Δ)) # D=+1 buy-agg, -1 sell-agg; Δ = 5 minutes
报价价差(quoted spread) 是屏幕上的头条数字。常用基点表达:s_q_bp = 10000 * s_q / mid_price。510300 在 0.001 元 tick、约 4 元价位 ≈ 2.4bp;600519 在 0.01 元 tick、约 1500 元价位 ≈ 0.07bp。中小盘股在涨跌停近端可见 10-30bp BBO 价差。
有效价差(effective spread) 是激进方在往返等价基础上实际支付的成本:进场过半价差,离场再过半价差。参考的 mid(t^-) 是成交 前 那一瞬间的中价。通常 s_e ≤ s_q,因为激进委托有时与隐藏价格改进(hidden-pricing improvement,如内化经纪商提供)成交。对 510300 的中位数成交,s_e / s_q 约 0.7-0.9。
实现价差(realised spread) 度量做市商扣除逆向选择后的利润。D(t) = +1 对应主买、 D(t) = -1 对应主卖,Δ = 5 分钟 是行业标准前视期。s_r 度量从成交时到 Δ 之后中价之间价格反对做市商方向走了多少;剩下的有效价差归了知情交易者。对流动性高的 A 股,实现价差大约是有效价差的一半——这意味着 做市商 报出的价差里约一半作为逆向选择成本付给了知情流量。
三个组分在经济意义上做加法分解:
s_q = adverse-selection cost + inventory cost + order-processing cost
- 逆向选择成本(adverse-selection cost) 是做市商承担被知情流量挑选风险所要的补偿;扩大报价部分抵消被挑走(pick off)的损失。引文:Glosten-Milgrom。
- 库存成本(inventory cost) 是 做市商 在两次对冲成交之间临时持有风险所要的补偿;引文:Stoll / Huang-Stoll。
- 报单处理成本(order-processing cost) 是交易所手续费加报价系统的技术成本;结构性固定。
只引文不推导的对应:Glosten-Milgrom 1985 处理逆向选择层;Stoll 1989 / Huang-Stoll 1997 处理库存层。每个微观结构书架上都坐着它们。形式化推导属于 4.2 / 4.5 选修课题。
Roll 的估计量作为 sanity check
你只有逐笔成交价、没有报价。还能估出价差吗?能:
spread_estimate = 2 * sqrt(-cov(Δp_t, Δp_{t-1}))
在「buy-at-ask / sell-at-bid 弹跳」模型下,相邻成交价变化具有负的序列协方差——卖一价上的一笔买入更可能跟着 买一价上的一笔卖出,而不是另一笔卖一价上的买入。该负协方差的深度就是价差。成交价变化的负序列协方差在 buy-at-ask / sell-at-bid 弹跳模型下意味着非零价差;把这个估计量作为对重建 L1 feed 的 sanity check——如果重建的报价价差与 Roll 估计量在同一数据上差异超过约 30%,二者中必有一个是错的(通常是委托簿重建错了)。
最小变动单位(tick size)与队列形态
最小变动单位(tick size)是交易所规定的最小价格变动。A 股规则:绝大多数股票(包括贵州茅台 600519 这种价位千元以上的)固定 0.01 元;A 股 ETF 通常 0.001 元(比股票细一个数量级——这是监管为 ETF 套利提供的让步);CN 没有美式 sub-penny 规则。引上交所 / 深交所 业务规则文件作为 tick size 的权威出处。
tick size 对委托簿有三类结构性效应:
- 盘口队列深 当 tick 相对波动率大。510300 在 0.001 元 tick、约 4 元价位上对应 ~2.4bp 的 tick,BBO 可能停留同一价位多秒、订单积累——单侧 10 万份级深度常见。
- 价格聚集 因为 tick 让价格离散化。同样波动率下、更细 tick 会让成交价更均匀分布。
- 流量在涨跌停附近变薄 A 股的涨跌停 ±10%(主板)/ ±20%(科创板 / 创业板)/ ±5%(ST)一旦触及,对应侧锁定、激进单只能排队不能成交,队列结构断裂。
资深同事第一天就强制的规则:每一种 tick 选择都是交易所的政策杠杆,策略的损益模型必须包含 tick——因为 (a) 价差下限就是 tick;(b) tick-bound 的队列又深又慢,你被动成交的概率在排队过深时崩塌。
订单流不平衡(OFI):经典的短期信号
每一笔成交带方向。D_i = +1 如果买侧主动(marketable 单向上越价差);D_i = -1 如果卖侧主动。上交所 / 深交所 逐笔成交 数据 直接发布 主买 / 主卖 / 中性 字段——CN 的权威主动方标记。对于缺失该字段的旧数据集或聚合 feed,Lee-Ready tick rule 重建:成交价高于中价标主买、低于中价标主卖;中价上的成交退回到 prior-trade direction。
定义有符号成交量与归一化订单流不平衡:
def compute_ofi(trades, window_seconds=1):
"""对固定宽度桶计算归一化订单流不平衡。
OFI ∈ [-1, +1]; +1 = 全部主动买单;-1 = 全部主动卖单。
"""
# 用主动方对每笔成交标号
trades["D_i"] = trades["aggressor_side"].map({"buy": +1, "sell": -1}).fillna(0)
# 按固定宽度桶
buckets = trades.set_index("ts").groupby(pd.Grouper(freq=f"{window_seconds}s"))
signed_volume = (buckets["D_i"] * buckets["size"]).sum()
total_volume = buckets["size"].sum()
OFI = signed_volume / total_volume # lives in [-1, +1]
forward_return_5s = buckets["mid"].last().pct_change().shift(-5)
return OFI, forward_return_5s
经验签名,用 510300 一日的 1 秒级 L1 数据走一遍:把 forward_return(t, t+5s) ~ OFI(t) 跑回归,常规会期内,期待 t 统计量 10-30 之间、单回归元 R² 0.5-2% 之间。单条 OFI 观测只解释一小片,多条观测复合成可交易的信号。信号在 60-300 秒内衰减,半衰期与个股相关。
OFI 是 流(flow)——窗口内速率信号。它的兄弟 queue imbalance(委托簿不平衡) 是同时刻的 状态(state),用 L2 深度定义 QI = (top_bid_depth − top_ask_depth) / (top_bid_depth + top_ask_depth),落在 [-1, +1]。QI 也正向预测中价短期走势,时间尺度更短(亚秒到几秒)、R² 更小。多数 做市商 与短期统计套利团队把 OFI 与 QI 融合成单一短期信号。引文:Cont, Kukanov & Stoikov 2014 (《The price impact of order book events》, Journal of Financial Econometrics 12(1)) 是行业标准引用;4.2.2 信号构建 课会讲围绕这类信号的 IC / IR 与衰减分析纪律。
市场冲击(market impact):价格因为你交易而动
一句话讲完经验规律:跨资产类、跨数十年,元订单(metaorder——以单一 meta 单分阶段成交的大单)的永久价格冲击呈如下标度:
permanent_impact ≈ Y * σ * sqrt(Q / V)
其中 Q 是元订单大小,V 是日成交量,σ 是日波动率,Y ≈ 0.5-1.0 是横截面常数。这就是 市场冲击的平方根法则(square-root law of impact),也叫 Almgren-Thum-Hauptmann 法则。元订单的永久价格冲击与参与率(participation rate)的平方根成正比。
冲击分解为两部分:
1. permanent impact — 永远不反转的那部分价格变化;
反映你的交易传递给市场的信息;
Kyle 1985 模型中由 Kyle 的 lambda 形式化
2. temporary impact — 在你停止交易后会反转的那部分价格变化;
反映你交易期间消耗掉的流动性;
按 t^(-β) 幂律衰减,β ≈ 0.5-0.8
永久性冲击(permanent impact)。 一部分价格变化永远不反转——它反映了市场从你的交易中推断出的信息;Kyle 1985 连续拍卖模型用 Kyle 的 lambda(Δp = λ * SV 与有符号成交量 SV 线性)形式化——这里只引文、不推导。
暂时性冲击(temporary impact)。 一部分价格变化在你停止交易后反转——它反映你交易期间消耗的流动性(你挤走的 做市商 在略差的价格补回来要几分钟);按幂律 f(t) ≈ t^(-β) 衰减,β ≈ 0.5-0.8。
Almgren-Chriss 2000 (《Optimal execution of portfolio transactions》, Journal of Risk 3(2)) 把执行计划下的冲击成本 / 方差权衡形式化:要在时间 T 内成交 Q 的交易员可以快速成交(高冲击、低交易期内方差)或慢速成交(低冲击、高交易期内价格漂移方差),最优排程通过风险厌恶参数在两者之间平衡。前向指针:4.5.2(交易成本与市场冲击)讲生产回测里用的完整冲击成本模型;4.5.3(执行算法)讲算法动物园(POV / VWAP / IS / 自适应)。
实务规则:每个达到容量相关规模的回测必须把冲击成本一行加上去;忽略冲击在典型规模下系统性地把容量相关 pnl 高估 50-200%;这是除前视偏差和幸存者偏差之后最常见的回测错误。
队列位置:被动成交概率的主导因素
当你以 BBO 价位提交一条被动限价委托,它加入该价位的队列。设你前面已有挂单量 X、对手侧在该价位的成交速率 T 每秒,则近似:
fill probability per second ≈ T / (X + your_size)
expected_time_to_fill ≈ (X + your_size) / T
队列位置与预期成交时间是线性的。 在 A 股流动性最好的 ETF 上,BBO 队列常达 10 万份级,成交速率几千份 / 秒——队尾的 100 份要等 30+ 秒,常常等不到——队列可能撤单而非成交。
经典规律:BBO 上大多数驻留挂单是撤单而非成交。BBO 上的撤单成交比(cancel-to-trade ratio)5-30 是地板不是 bug。为什么?激进方看到簿的变化就重新报价;不重新报价的被动挂单被逆向选择掉。这里有一个 逆向选择陷阱(adverse selection trap):成交快的被动挂单往往因为价格马上要逆你而动——快成交是坏成交。
每个被动成交策略都需要一个条件于队列位置的成交率模型。L1 与 L2 feed 无法 告诉你你的队列位置(L1 不暴露挂单;L2 显示聚合深度但无个体身份),所以队列位置感知的策略要求 L3——CN 的 上交所 / 深交所 逐笔委托。前向指针:4.5.3 讲队列位置感知的撤改单(cancel + replace)策略。
五个锚点与收尾规则
本课的五个微观结构锚点,加上每个的前向指针——讲它对应纪律的课在哪里:
1. bid-ask spread (→ 4.5.2 for transaction-cost decomposition)
2. tick size (→ 4.5.3 for execution-algorithm tick-aware placement)
3. order-flow imbalance (→ 4.2.2 for signal-construction discipline)
4. market impact (→ 4.5.2 for impact-cost model + 4.5.3 for execution algorithms)
5. queue position (→ 4.5.3 for queue-aware execution; requires L3 feed)
微观结构是厘的去处和来处;每个量化策略都分解为信号加成本,而成本几乎全是微观结构;永远不要在没有同时计算交易成本的情况下计算收益信号;干净的数据救不了你的冲击成本——冲击是在活市场对真实规模交易付的。
本课触碰术语—— 订单簿、限价订单簿、买卖价差、做市商、最小变动单位、订单流、队列位置、延迟、成交量加权平均价(VWAP)、时间加权平均价(TWAP)、实施差额、滑点、交易成本——是 4.2-4.5 alpha 研究、因子构造、执行课程依赖的成本侧底座。
练习
Exercise
给你 510300 的一日 bars_1s(symbol, ts, mid, best_bid, best_bid_size, best_ask, best_ask_size, last_trade_price, last_trade_size, aggressor_side)。做四个计算并汇报:
(i) 计算常规会期内时间加权平均的 quoted spread,相对中价、单位 bp;汇报一个数。
(ii) 对每一个 1 秒桶,算 OFI = signed_volume / total_volume,其中 signed_volume = sum(D_i * size_i)、 D_i = +1 表主买、D_i = -1 表主卖;从 mid 算 forward_return_5s;跑 OLS 回归 forward_return_5s ~ OFI;汇报斜率系数、t 统计量和 R²。
(iii) 对成交价序列应用 Roll 估计量 spread_estimate = 2 * sqrt(-cov(Δp_t, Δp_{t-1}));计算比值 roll_estimate / time_weighted_quoted_spread;预期落在 [0.5, 1.0];用一句话说明若比值 >1.5 或 <0.3 各意味着什么。
(iv) 用平方根法则 permanent_impact ≈ 0.6 * σ_daily * sqrt(Q / V_daily),取 σ_daily = 1%、510300 取 V_daily = 50M份,估计元订单 Q = 200,000份 的永久价格冲击(bp)。
四个答案合成一个表格汇报。
提示
Σ (s_q * dt) / Σ dt;转 bp 用 10000 * s_q / mid。对 (iii),Roll 估计量在流动性好的标的上应接近报价价差——比值落在 [0.5, 1.5] 之外说明二者必有一个被错算。提示
0.6 × 0.01 × sqrt(200_000 / 50_000_000) ≈ 0.6 × 0.01 × 0.0632 ≈ 3.8 bp。20 万份元订单光是永久冲击就要约 3.8bp;信号必须越过它加上价差才能见 pnl。Formula Explorer
OFI(t) = (\sum_i D_i * size_i) / (\sum_i size_i)KaTeX 公式
四个核心公式的 KaTeX 形式参考:
参考卡
本课装配的组件,按次序:
- Inline-code listing — 三种可量度价差变体(
quoted spread、effective spread、realised spread)及其公式。 - Inline-code listing — 经济意义的三向分解(逆向选择 / 库存 / 报单处理)及引文。
- Fenced ```text 块 — Roll 估计量
spread_estimate = 2 sqrt(−cov(Δp_t, Δp_{t-1}))与 30% sanity 规则。 - Fenced ```python 代码块 —
compute_ofi(trades, window_seconds=1)函数与D_i主动方标号。 - Fenced ```text 块 — 平方根法则
permanent_impact ≈ Y σ sqrt(Q / V)、Y ≈ 0.5-1.0。 - Inline-code listing — 两类冲击分量(永久 / 暂时)及 Kyle、Almgren-Chriss 引文。
- Fenced ```text 块 — 队列位置成交公式
expected_time_to_fill ≈ (X + your_size) / T。 - Inline-code listing — 五个微观结构锚点与前向指针 4.2.2 / 4.5.2 / 4.5.3。
- Exercise — 510300 上四问回归练习,含 Two progressive Hints 各保持简短。
- FormulaExplorer — OFI 公式
OFI = Σ D_i size_i / Σ size_i。
纪律收尾:信号与成本同时算;干净数据救不了你的冲击成本;撤单成交比 5-30 是地板不是 bug。
下一课
把现象抓在手里之后,下一课组装把原始 tick 转成研究就绪数据集的清洗管线——所谓「数据工程」,每个初级量化的头六个月都在做这件事。L4 产出的 bars_1m 与 bars_daily 是 4.2 / 4.5 每一个回归与回测的输入。带着本课纪律走:信号与成本同时算;干净数据救不了冲击;撤单成交比 5-30 是地板。