Lee-Ready 成交方向分类:只用价与报价推断每笔是买还是卖
微观结构里几乎所有模型——从 Roll、Glosten-Harris 到 Huang-Stoll 价差分解、订单流失衡、VPIN——都要先回答一个原始问题:这笔成交是买方主动还是卖方主动?可交易所的 tick 数据往往不标方向。Lee-Ready (1991) 给出了一套两步规则:报价规则(成交价高于中间价判为买、低于判为卖)先处理绝大多数价内成交,Tick 规则再救那些恰好打在中间价上的疑难成交。本文用 5 万笔模拟成交跑通完整算法,实测整体准确率 89.8%(价内成交 100%、价差内成交 80%),拆解误差全部来自中点成交与价格改善;再演示分类误差如何传导到下游订单流失衡信号(相关系数掉到 0.76),以及报价陈旧化如何快速侵蚀准确率——这正是 Lee-Ready 建议报价前移 5 秒的原因。诚实边界:错标率 10-15% 会污染所有下游模型、算法在不同市场结构下需重标定、高频碎片化市场中点滞后(中阶)。
一个所有微观结构模型都绕不开的前置问题#
你想估价差里的信息成分(Huang-Stoll)、想算订单流失衡、想跑 VPIN 度量订单流毒性、想复现 Kyle 的价格冲击——所有这些的第一步,都要求你知道每一笔成交到底是买方主动打上去的,还是卖方主动砸下来的。
问题是:交易所推送的逐笔成交(tick data)通常只有价格和数量,没有方向标签。撮合系统里买卖双方都存在,谁是”主动方”(liquidity taker)需要你自己推断。
Lee 和 Ready (1991) 给出的算法,是过去三十年被引用最多、实盘用得最广的方向分类方法。它只用成交价和当时的买卖报价,逻辑简单到可以写在一张便签上,准确率却能到 85-90%。
两步规则:报价规则打主力,Tick 规则补漏#
Lee-Ready 的核心是两条规则的级联:
第一步——报价规则(quote rule):
- 成交价 高于 买卖中间价 → 判为买方主动(buyer-initiated,主动吃卖单)
- 成交价 低于 中间价 → 判为卖方主动(seller-initiated,主动砸买单)
直觉很硬:主动买入者愿意付更高的价(往卖价靠),成交价自然落在中点上方;主动卖出者愿意接受更低的价(往买价靠),成交价落在中点下方。绝大多数打在报价上的成交,报价规则一步搞定。
第二步——Tick 规则(tick rule): 处理报价规则失效的情况——成交价恰好等于中间价。这时上下都不靠,报价规则弃权,改用价格自身的变化方向:
- 成交价 高于 上一笔不同的成交价(uptick)→ 判为买
- 成交价 低于 上一笔不同的成交价(downtick)→ 判为卖
- 相等(zero tick)→ 沿用上一笔的方向
Tick 规则的逻辑:价格在往上走,说明近期有买压主导;往下走则卖压主导。它是报价规则的兜底。

上图是 400 笔抽样成交按”相对中点位置”画出来的:红点(判为买)集中在中点上方、蓝点(判为卖)集中在下方——报价规则在价内成交上几乎不出错。黑叉是分类错误,全部聚集在中点附近的橙色带里,也就是 Tick 规则不得不上场的地方。
Python 实现:完整两步算法#
import numpy as np
rng = np.random.default_rng(11)
N = 50_000
half = 0.05
mids = 100.0 + np.cumsum(rng.normal(0, 0.01, N)) # 中间价随机游走
bid, ask = mids - half, mids + half
Q_true = np.where(rng.random(N) < 0.5, 1, -1) # 真实方向 +1买 / -1卖
# 生成成交价:多数打在报价上,部分中点成交,部分价格改善(可能越过中点)
price = np.empty(N)
for i in range(N):
u = rng.random()
if u < 0.12: # 中点成交:报价规则失效
price[i] = mids[i]
elif u < 0.30: # 价格改善:可能落到中点错误一侧
base = ask[i] if Q_true[i] == 1 else bid[i]
price[i] = base - Q_true[i] * rng.uniform(0, half * 1.3)
else: # 打在报价上
base = ask[i] if Q_true[i] == 1 else bid[i]
price[i] = base
# --- Lee-Ready 两步分类 ---
Q_est = np.zeros(N)
last_diff = price[0]
for i in range(N):
m = mids[i]
if price[i] > m + 1e-9: # 报价规则
Q_est[i] = 1
elif price[i] < m - 1e-9:
Q_est[i] = -1
else: # Tick 规则兜底
if price[i] > last_diff: Q_est[i] = 1
elif price[i] < last_diff: Q_est[i] = -1
else: Q_est[i] = Q_est[i-1] if i else 1
if i and price[i] != price[i-1]:
last_diff = price[i-1]
print(f"整体准确率: {np.mean(Q_est == Q_true)*100:.1f}%")python跑出来整体准确率 89.8%,跟 Lee-Ready 原文及后续大量实证(85-92%)一致。
准确率从哪来,误差往哪去#
把准确率按成交位置拆开看,故事就清楚了:

- 报价上成交:100% 准确——只要成交价明确落在中点一侧,报价规则不会错;
- 价差内成交:只有 80%——中点成交(Tick 规则只能靠历史价格猜)和价格改善成交(打过了头,落到中点错误一侧,报价规则被误导)是全部误差的来源;
- 整体 89.8%——由两类成交的占比加权而成。
这个拆解给了一个重要的实操启示:你的数据里价内成交占比越高,Lee-Ready 越可靠。流动性好、价差窄、成交密集在报价上的大盘股,分类近乎完美;而暗池、中点撮合、频繁价格改善的品种,Lee-Ready 的软肋暴露无遗。
分类误差会传导到下游信号#
方向分类几乎从不是终点,而是订单流失衡、VPIN、价差分解的输入。10% 的错标不会原地消失,它会顺着计算链传导、放大或抵消。

上图用 200 笔滚动窗口计算订单流失衡(OFI = 买占比 − 卖占比):灰线是用真实方向算的、红线是用 Lee-Ready 估计方向算的。两条线大方向一致,但估计 OFI 与真实 OFI 的相关系数只有 0.76——10% 的方向错标,让下游信号丢掉了约四分之一的解释力。如果你的策略靠 OFI 择时,这部分噪声直接吃你的信噪比。
结论很朴素:分类误差不是”洗掉”就没事,它是所有下游微观结构信号的噪声地板。任何声称”用订单流失衡预测短期价格”的策略,其准确率上限先被 Lee-Ready 的方向精度卡住一道。
报价陈旧化:一个隐蔽但致命的坑#
Lee-Ready 有个常被忽略的技术细节:成交和报价的时间戳对齐。在纸带时代,成交上报比报价更新慢,Lee 和 Ready 建议把报价前移 5 秒再和成交匹配,避免用”过时的报价”判”新成交”。

上图模拟了报价滞后对准确率的侵蚀:报价越陈旧(横轴 bar 数越大),准确率下降得越快——从对齐时的 89.8% 一路掉下去。原因是错配的中间价让报价规则频繁误判:你拿着 5 秒前的中间价去比对现在的成交价,中间价早就漂走了。
这在今天的高频、碎片化市场里更麻烦:多个交易所各有报价、时钟不完全同步、NBBO(全国最优买卖价)的构造本身有微秒级延迟。对齐没做好,准确率的账先亏一半。
三个实操要点#
一、先看你的数据长什么样。 价内成交占比、中点成交比例、价格改善频率,决定了 Lee-Ready 在你的标的上是 95% 还是 80%。别套用文献里的”88%“当作自己数据的准确率——先在有真实方向标签的子样本上标定一次。
二、时间戳对齐是第一优先级。 在做任何精细化之前,先确保成交和报价的时钟对齐、必要时前移报价。这一步的收益通常比换更花哨的分类算法(BVC、深度学习分类器)还大。
三、把方向精度当成下游模型的误差预算。 你的价差分解、OFI 择时、VPIN 毒性度量,精度上限都被这 10% 卡着。汇报下游结果时,要么在方向标签质量高的子样本上验证,要么明确把分类误差写进不确定性区间——否则你会把”分类噪声”当成”策略 alpha”。
诚实的边界#
- 10-15% 的错标是硬地板。 即便完美对齐、数据干净,中点成交和价格改善成交也无法靠价与报价可靠区分。要更高精度,得上更丰富的数据(订单簿事件、成交-挂单撮合日志),那已经不是 Lee-Ready 的适用范围。
- 不同市场结构需要重标定。 报价规则和 Tick 规则的相对贡献,在连续竞价、做市商市场、暗池里差异巨大。A 股连续竞价、无正式做市商,中点成交比例和美股不同,直接套 Lee-Ready 参数会偏。
- BVC 等替代方法在高频下可能更好。 Easley 等提出的 Bulk Volume Classification 用价格变化的正态 CDF 给出”买占比”的连续估计,在超高频、逐笔难以对齐报价的场景下有时优于 Lee-Ready,但它给的是概率不是硬标签,两者适用场景不同。
- 它只是预处理,不是策略。 Lee-Ready 本身不产生任何 alpha,它是让下游微观结构分析能跑起来的”数据清洗”层。把它当策略核心是搞错了定位。
Lee-Ready 的地位,来自它在”简单”和”够用”之间找到的那个甜点:只用最容易拿到的价与报价,就能给 85-90% 的成交贴上方向标签,让整座微观结构分析大厦有地基可站。你每次算订单流、每次拆价差,脚下踩的都是这套三十年前的两步规则。
参考文献#
- Lee, C. M. C., & Ready, M. J. (1991). Inferring Trade Direction from Intraday Data. Journal of Finance, 46(2), 733-746.
- Ellis, K., Michaely, R., & O’Hara, M. (2000). The Accuracy of Trade Classification Rules: Evidence from Nasdaq. Journal of Financial and Quantitative Analysis, 35(4), 529-551.
- Easley, D., López de Prado, M. M., & O’Hara, M. (2012). Flow Toxicity and Liquidity in a High-Frequency World. Review of Financial Studies, 25(5), 1457-1493.
- Chakrabarty, B., Li, B., Nguyen, V., & Van Ness, R. A. (2007). Trade Classification Algorithms for Electronic Communications Network Trades. Journal of Banking & Finance, 31(12), 3806-3821.