2. 沪深逐笔数据文件结构解析

逐笔委托与逐笔成交是构建订单簿重建、微观结构分析和交易行为研究的基础数据。上交所与深交所在字段定义、编码方式和文件分发机制上存在明显差异,若在读取阶段不做区分,后续关联键匹配会出现大量错配。本节围绕两所逐笔文件的字段结构、命名规则与读取要点展开,为后续关联键对照打下数据层基础。

一、上交所逐笔委托与成交字段

上交所逐笔数据通常以 CSV 形式按日分发,委托表与成交表分开存放。委托表核心字段包括:SecurityID(证券代码)、TradeDate、OrderTime(精确到毫秒或微秒的时间戳)、OrderNo(当日委托序号)、OrderType(委托类型,如 A 表示新增委托、D 表示删除)、OrderPrice、OrderQty、Side(B/S 买卖方向)。成交表核心字段包括:TradeTime、TradeID(成交编号)、BuyOrderNo、SellOrderNo、TradePrice、TradeQty。

需要特别注意的是,上交所成交表中的 BuyOrderNo 与 SellOrderNo 直接指向委托表中的 OrderNo,这是上交所关联键最直接、最可靠的一环。但委托表中的 OrderNo 是当日连续编号,跨日后会重置,因此关联时必须同时限定 TradeDate 与 SecurityID,不能仅凭序号跨日匹配。

二、深交所逐笔委托与成交字段

深交所逐笔数据同样分为委托与成交两类,但字段命名与语义有差异。委托表常见字段为:证券代码、委托时间、委托序号、委托类型、委托价格、委托数量、买卖方向。成交表常见字段为:成交时间、成交序号、买方委托序号、卖方委托序号、成交价格、成交数量。

深交所的关键差异在于:其委托序号与成交序号在部分数据版本中并非全局唯一,而是按频道或按证券分段编号;同时深交所逐笔委托中还存在“撤单”类记录,撤单记录会携带原委托序号,读取时需将撤单与新增委托区分处理,否则会把撤单误当作有效委托参与订单簿重建。此外,深交所部分文件采用二进制格式分发,字段为定长结构,需按字节偏移解析,不能直接按逗号分隔读取。

三、文件命名与分发机制

两所逐笔文件普遍采用“市场标识 + 数据类型 + 交易日期 + 序号”的命名结构。例如上交所常见形如 order_20240102.csv、trade_20240102.csv 的命名,深交所则常见带证券代码或频道号的分片文件。分发上,上交所多按日打包为压缩包,深交所则可能按证券或按频道切分为多个文件,单日数据量可达数十 GB。读取前应先建立“日期—文件—证券”的索引,避免逐文件全量扫描。

沪深逐笔文件结构与关联键对照 上交所(CSV 按日分发) 逐笔委托表 OrderNo OrderTime OrderType OrderPrice/Qty Side 逐笔成交表 TradeID BuyOrderNo SellOrderNo TradePrice/Qty TradeTime OrderNo 直连 深交所(CSV/二进制,按频道分片) 逐笔委托表 委托序号 委托时间 委托类型(含撤单) 委托价格/数量 买卖方向 逐笔成交表 成交序号 买方委托序号 卖方委托序号 成交价格/数量 成交时间 委托序号关联 关联键匹配的三重约束(两所通用) ① 同一 TradeDate ② 同一 SecurityID ③ 序号当日唯一性校验 读取要点 CSV:显式指定编码与列类型,时间戳按毫秒/微秒解析,避免科学计数法丢失序号精度 二进制:按定长结构体偏移解析,先读文件头确认字段版本,再逐条解码,禁止按分隔符切分

四、CSV 与二进制读取要点

CSV 读取看似简单,但逐笔数据有两个高频陷阱。第一是序号精度:委托序号、成交序号可能达到 10 位以上,若用默认浮点类型读入,会被转成科学计数法并丢失末位,导致关联键匹配失败。正确做法是在读取时显式指定为字符串或 64 位整型。第二是时间戳解析:上交所时间戳可能精确到微秒,深交所部分文件精确到毫秒,解析时应先确认时间单位,再统一转换为同一精度的时间对象,否则同一笔成交与委托的时间先后判断会出错。

二进制读取则必须依赖字段结构定义。以深交所定长结构为例,假设单条委托记录为 32 字节,前 8 字节为委托序号、接下来 8 字节为时间戳、再 4 字节为价格(按最小价格单位整数存储)、4 字节为数量、剩余为类型与方向标志。读取时应先读文件头确认版本与记录长度,再按偏移逐字段解码。价格字段若以整数存储,需除以最小价格单位(如 0.01 元)还原为真实价格,这一步在 CSV 中通常已由分发方完成,二进制中则必须自行处理。

# 示例:按定长结构读取深交所二进制逐笔委托(参数为教学假设)
import struct

RECORD = struct.Struct("<QqIIBB")  # 序号, 时间戳, 价格, 数量, 类型, 方向
with open("order_20240102.bin", "rb") as f:
    header = f.read(16)          # 文件头:版本 + 记录长度
    while True:
        buf = f.read(RECORD.size)
        if len(buf) < RECORD.size:
            break
        order_no, ts, price_raw, qty, otype, side = RECORD.unpack(buf)
        price = price_raw / 100.0   # 假设最小价格单位为 0.01 元

五、读取后的结构校验

完成读取后,建议先做三项校验再进入关联环节:其一,检查委托表中 OrderNo(或委托序号)在当日、单证券范围内是否唯一,若存在重复,说明文件分片未合并或序号分段未处理;其二,检查成交表中买方、卖方委托序号是否都能在委托表中找到对应记录,缺失比例异常通常意味着撤单记录被过滤或分片文件缺失;其三,检查时间戳单调性,逐笔数据按时间递增排列,若出现明显回退,可能是多频道文件合并顺序有误。这三项校验能提前暴露大部分结构性问题,避免把数据层错误带入关联键分析。

上交所成交表通过 BuyOrderNo/SellOrderNo 直接指向委托表 OrderNo,关联路径最短;深交所需注意委托序号的分段编号与撤单记录,关联前应先完成分片合并与撤单标记。