1. 逐笔数据解析与订单流基础
订单流特征工程的第一步,不是写因子,而是把交易所推送的逐笔数据还原成一张可计算的“市场微观结构快照”。逐笔成交(Trade)与逐笔委托(Order)是两类性质完全不同的记录:成交记录描述“已经发生的撮合”,委托记录描述“意图进入或退出订单簿的挂单”。只有把两者按时间轴对齐,才能得到买一卖一、价差、深度等订单流核心量。
一、逐笔成交与逐笔委托的数据结构
以常见的A股Level-2逐笔数据为例,逐笔成交通常包含:成交时间(精确到毫秒或十毫秒)、证券代码、成交编号、成交价格、成交数量、买卖方向标识(主动买/主动卖/未知)、买方委托序号、卖方委托序号。逐笔委托则包含:委托时间、委托编号、价格、数量、买卖方向、委托类型(限价/市价/本方最优等)。关键点在于:成交记录中的买方委托序号与卖方委托序号,是连接成交与委托的桥梁,通过它可以追溯一笔成交是由哪两笔挂单撮合而成,进而判断是主动买还是主动卖。
需要特别说明方向约定:本课程统一采用“主动方视角”——成交方向记为主动买(外盘)表示买方吃掉卖方挂单,主动卖(内盘)表示卖方砸向买方挂单。所有后续因子计算均以此为准,切换视角时必须显式声明。
二、订单流核心概念:买一卖一、价差与深度
买一(Bid1)是当前订单簿中最高买价,卖一(Ask1)是最低卖价。价差 = Ask1 − Bid1,是流动性的直接价格度量;价差越小,交易成本越低。深度则描述某一价位或价格区间内的挂单总量,常见形式有:买一量、卖一量、前五档累计量、以及按价格加权的深度。深度不是静态数字,它随逐笔委托的插入、撤单、成交而实时变化,因此必须用事件流的方式重建订单簿,而不是简单对快照做差分。
三、数据清洗与对齐方法
原始逐笔数据常见问题包括:时间戳乱序、重复推送、成交编号缺失、委托序号无法匹配、集合竞价与连续竞价混排、以及跨市场(如沪深)时间基准不一致。清洗的核心原则是先排序、再去重、后匹配:按交易所时间戳稳定排序,以成交编号或(时间+序号)去重,再用委托序号做成交—委托关联,无法匹配的记录标记为“方向未知”而非直接丢弃,避免样本选择偏差。
对齐方面,逐笔成交与逐笔委托的时间粒度可能不同(如成交十毫秒、委托毫秒),需要统一到同一时间栅格。常用做法是:以较细粒度时间为基准,将较粗粒度记录归入其所属时间桶,并在桶内按序号排序。重建订单簿时,按“委托到达→插入订单簿→成交扣减→撤单移除”的事件顺序逐条处理,任何一步顺序错误都会导致买一卖一错位。
# 伪代码:逐笔事件重建订单簿(示例逻辑)
events = sort_by_time(trades + orders) # 统一时间轴
book = OrderBook()
for e in events:
if e.type == "order" and e.side == "buy":
book.add_bid(e.price, e.qty, e.order_id)
elif e.type == "order" and e.side == "sell":
book.add_ask(e.price, e.qty, e.order_id)
elif e.type == "trade":
book.reduce(e.buy_order_id, e.qty)
book.reduce(e.sell_order_id, e.qty)
elif e.type == "cancel":
book.remove(e.order_id)
snapshot = book.top5() # 输出买一卖一与五档深度
完成上述步骤后,每条时间桶都能得到一组结构化字段:买一价、卖一价、价差、买一量、卖一量、五档累计深度、主动买成交量、主动卖成交量。这些字段就是后续订单流因子的原料。判断清洗是否成功的实用标准是:重建后的买一价始终不高于卖一价(无交叉),且主动买量与主动卖量之和应等于该时段总成交量(允许极小的未知方向残差)。若出现持续交叉或量能不守恒,应回查事件排序与委托序号匹配环节。
把上述链路跑通后,读者应能对任意一个交易日的逐笔文件产出一张按时间排列的订单流快照表。这张表既是数据清洗的验收物,也是后续价差因子、深度因子、主动买卖不平衡因子的统一输入。下一阶段的所有特征,都建立在这张表“买一不高于卖一、量能守恒”的基础之上。