4. 逐笔委托数据字段详解

逐笔委托是交易所行情中最“原始”的一类数据:它记录的是每一笔新进入撮合队列的委托,而不是撮合完成后的结果。做逐笔回放时,委托数据决定了“盘口是怎么被摆出来的”,成交数据决定了“盘口是怎么被吃掉的”,两者必须通过字段映射对齐到同一条时间轴上,回放才有意义。本节把逐笔委托的核心字段逐一拆开,并给出它与逐笔成交之间的关联方式。

一、逐笔委托的核心字段

以沪深交易所常见的逐笔委托数据结构为例,一条委托记录通常包含以下字段(不同交易所、不同行情版本字段名略有差异,但语义基本一致):

字段典型类型含义与使用要点
委托编号(OrderNo / ApplSeqNum)整数交易所内唯一递增序号,是委托与成交关联的主键,回放排序的第一依据
证券代码(SecurityID)字符串标的标识,回放时用于过滤单只股票
委托价格(Price)定点数限价委托的申报价;市价委托通常填 0 或特定标记值,需结合委托类型解释
委托数量(OrderQty / Balance)整数申报数量;部分行情同时给出“剩余数量”,两者含义不同,不能混用
买卖方向(Side)枚举通常 1=买、2=卖(或 B/S),是判断主动方与盘口变化方向的关键
委托类型(OrdType)枚举限价、市价、本方最优、对手方最优等,决定价格字段如何解读
时间戳(TransactTime / TickTime)时间精确到毫秒甚至微秒,回放时与成交时间戳共同决定事件先后

这里最容易踩坑的是委托数量与剩余数量。申报数量是委托进入时的原始量,剩余数量是经过部分成交后队列中还没被消耗的量。回放重建盘口时,应当用“申报量减去已成交量”来维护队列,而不是直接拿剩余数量覆盖,否则在部分成交场景下会出现队列量跳变。

二、委托类型决定价格字段的解读方式

限价委托的 Price 就是真实申报价,可以直接插入对应价位的队列。市价委托的 Price 往往为 0,此时不能把它当成“价格为 0 的限价单”插入盘口,而应理解为“以对手方最优价立即成交”的指令。本方最优、对手方最优等类型同理,价格字段只是参考值,真正的成交价要看成交记录。回放逻辑中应先按 OrdType 分支处理,再决定是否把该委托挂入队列。

判断依据:若 OrdType 为限价且 Price 大于 0,则该委托进入对应价位队列等待撮合;若为市价类,则该委托不进入队列,直接与对手方队列撮合,其成交结果体现在逐笔成交数据中。

三、委托与成交的关联字段映射

逐笔成交记录中通常包含买方委托编号与卖方委托编号两个字段(如 BidApplSeqNum、OfferApplSeqNum),它们分别指向成交双方对应的委托记录。这就是委托与成交之间最直接的关联桥梁:一笔成交必然对应一个买方委托编号和一个卖方委托编号,通过这两个编号可以反查委托的价格、方向、类型与时间。

除编号外,还有几组需要对齐的字段:

  • 证券代码:委托与成交必须同代码,跨代码关联一定是数据错位。
  • 时间戳:成交时间应不早于对应委托时间,若出现倒挂,说明时间字段口径不一致(如一个是交易所时间、一个是本地接收时间)。
  • 方向:成交记录中的主动方方向,应与“后进入队列的一方”方向一致,可用于校验关联是否正确。
  • 数量:同一委托编号下的多笔成交数量之和,不应超过该委托的申报数量。
逐笔委托 ⇄ 逐笔成交 字段关联映射 逐笔委托(Order) 委托编号 OrderNo 主键 证券代码 SecurityID 价格 Price 数量 OrderQty 方向 Side 类型 OrdType / 时间戳 逐笔成交(Trade) 买方委托编号 BidSeq 卖方委托编号 OfferSeq 成交价格 TradePrice 成交数量 TradeQty 成交时间 TradeTime 主动方方向 Side 编号映射 编号映射 价格校验 数量校验 方向校验 时间先后 实线:主键关联 虚线:一致性校验

四、回放中的实际处理方式

假设我们回放某只股票的一段行情,收到如下两条记录(示例数据,用于说明处理逻辑):

委托: OrderNo=10023, SecurityID=600000, Price=10.50, OrderQty=800, Side=买, OrdType=限价, Time=09:31:02.150
成交: BidSeq=10023, OfferSeq=10008, TradePrice=10.50, TradeQty=300, Time=09:31:02.180

处理顺序应当是:先按时间戳把委托与成交合并成一条事件流,09:31:02.150 先处理委托——在买盘 10.50 价位插入 800 股;09:31:02.180 再处理成交——通过 BidSeq=10023 找到买方委托,通过 OfferSeq=10008 找到卖方委托,从买方队列扣减 300 股,剩余 500 股仍挂在 10.50。若后续再来一笔针对 10023 的成交 500 股,则该委托被完全消耗,从队列移除。

这里有一个必须明确的约定:成交数量扣减的是委托的剩余量,而不是重新插入一条新委托。很多回放实现出错,就是因为把每笔成交当成独立事件去改盘口,却没有回写到原委托对象上,导致同一委托被重复计算。正确做法是维护一个以 OrderNo 为键的委托字典,成交到达时按编号查字典、扣减剩余量、更新队列总量。

校验建议:对每个 OrderNo 累计其所有成交的 TradeQty,若累计值大于 OrderQty,说明关联字段错位或数据重复;若某委托在收盘时累计成交远小于申报量且未撤单,需检查是否漏收了撤单记录。撤单在逐笔委托中通常以独立记录或特定 OrdType 出现,回放时同样要按 OrderNo 定位并移除队列。

五、字段口径统一是回放正确的前提

不同数据源的字段命名和取值约定并不一致:有的用 1/2 表示买卖,有的用 B/S;有的价格是整数放大 10000 倍,有的已是浮点;有的时间戳是交易所撮合时间,有的是行情落地时间。开始回放前,应先建立一张字段映射表,把外部字段统一到内部模型:OrderNo 统一为 64 位整数,Price 统一为定点整数(避免浮点误差),Side 统一为枚举,Time 统一为同一时区的毫秒时间戳。只有口径统一,委托编号才能稳定地关联到成交,时间戳才能正确地排出事件先后,回放出的盘口才与真实撮合过程一致。