3. 上交所逐笔委托核心字段解析
上交所逐笔委托消息(Binary 协议中的 Order 消息,消息类型 'A')是重建订单簿最基础的原料。一条消息看似只有十几个字段,但每个字段的编码方式、单位、取值范围都直接决定后续映射是否正确。本节以一条真实的委托消息为对象,逐字段拆解其编码规则,并完成一次完整的字段提取。
消息整体结构与字段清单
上交所逐笔委托采用定长二进制格式,单条消息共 44 字节(不含消息头)。核心字段包括:委托序号(OrderNo)、买卖方向(Side)、订单类型(OrdType)、委托价格(Price)、委托数量(Volume)、委托时间(TransactTime)以及证券代码(SecurityID)。其中价格与数量均为整数编码,需要按固定精度还原为实际值,这是映射中最容易出错的地方。
委托序号:订单簿重建的主键
委托序号(OrderNo)是 8 字节无符号整数,由交易所按当日委托到达顺序单调递增分配。它有两个用途:一是作为订单的唯一标识,二是作为判断订单先后顺序的依据。在逐笔合并(逐笔委托 + 逐笔成交)时,成交消息中的买方委托序号和卖方委托序号都指向这个值,因此映射时必须原样保留为 64 位整数,不能截断为 32 位,也不能转成浮点数——浮点数在超过 2^53 后会丢失精度,而当日委托序号完全可能突破这个量级。
实际处理中,建议在内存中用 uint64 或 Python 的 int 存储,落库时使用 BIGINT UNSIGNED。若用 pandas 读取,需显式指定 dtype={'order_no': 'uint64'},否则默认的 int64 虽能容纳,但一旦与其他表 join 时被推断为 float 就会出问题。
买卖方向与订单类型:字符枚举的映射
买卖方向(Side)占 1 字节,取值为字符 'B'(买)或 'S'(卖)。订单类型(OrdType)同样占 1 字节,上交所逐笔委托中常见取值为 'A'(增加,即新订单)和 'D'(删除,即撤单)。这两个字段都是 ASCII 字符而非数字,解析时直接按字节读取即可,但映射到内部模型时建议统一转为小写字符串或枚举,避免大小写混用导致过滤条件失效。
需要特别注意的是,撤单消息(OrdType='D')同样携带价格和数量字段,但语义是"撤销原委托",其数量通常为原委托的剩余量。若在订单簿重建时把 'D' 消息当作新订单插入,会造成订单簿虚增。正确做法是:遇到 'D' 时,用 OrderNo 定位已有订单并将其移除,价格与数量字段仅作校验参考。
委托价格与数量:整数编码的精度还原
这是映射环节最核心的两个字段。上交所逐笔委托中,价格(Price)为 8 字节有符号整数,单位为 0.0001 元,即实际价格 = 整数值 ÷ 10000;数量(Volume)为 8 字节有符号整数,单位为 100 股(1 手),即实际股数 = 整数值 × 100。以示例消息为例,若 Price 字段原始值为 105000,则实际价格为 105000 ÷ 10000 = 10.50 元;若 Volume 原始值为 5,则实际数量为 5 × 100 = 500 股。
这里有两个易错点。第一,价格精度是 0.0001 元而非 0.01 元,虽然 A 股报价最小变动单位通常是 0.01 元,但字段本身保留了四位小数,映射时若提前按两位小数取整,会在后续与成交价比对时产生偏差。第二,数量单位是"手"而非"股",若直接拿原始值当股数使用,订单簿深度会缩小 100 倍。建议在映射层统一转换为"元"和"股"两个标准单位,并在字段命名上体现单位,例如 price_yuan、volume_shares,从命名上杜绝单位混淆。
委托时间:紧凑时间戳的解析
委托时间(TransactTime)为 8 字节无符号整数,编码格式为 HHMMSSmmm,即时分秒各两位、毫秒三位,共 9 位数字。例如 93000500 表示 09:30:00.500。解析时按位截取:前两位为小时,第 3-4 位为分钟,第 5-6 位为秒,后三位为毫秒。由于该字段不含日期,映射时需结合交易日期字段拼接为完整时间戳。若直接用整数除法取模,务必注意毫秒部分不足三位时的高位补零问题——交易所输出通常已补齐,但做健壮性校验时仍应检查位数。
单条消息的完整提取示例
假设收到一条原始字节序列,按上述规则解析后得到如下中间结果(示例数据,用于说明提取过程):
OrderNo = 1000001
SecurityID = "600000 "
Side = 'B'
OrdType = 'A'
Price = 105000
Volume = 5
TransactTime = 93000500
# 还原为标准单位
price_yuan = 105000 / 10000 = 10.50
volume_shares = 5 * 100 = 500
time_str = "09:30:00.500"
提取完成后应做三项校验:其一,SecurityID 去除尾部空格后应为 6 位数字;其二,Side 与 OrdType 必须落在已知枚举集合内,否则标记为异常消息;其三,价格与数量还原后应为正数(撤单消息除外,其数量可能为 0)。通过校验的字段再写入标准化结构,进入后续的订单簿重建流程。
把上述字段逐一拆解后可以看到,上交所逐笔委托的映射难点不在字段数量,而在单位与精度的还原,以及字符枚举的语义区分。掌握这几点,单条消息的字段提取就能稳定复现,为后续逐笔合并与订单簿重建打下可靠基础。