1. 课程导入与数据环境搭建

沪深两市的逐笔委托数据,是Level-2行情中最接近“市场原始意图”的一类数据。它记录的是每一笔委托在进入交易所撮合主机时的原始状态:谁在什么时间、以什么价格、委托了多少数量、是买入还是卖出、是限价还是市价、是新增还是撤单。与逐笔成交相比,逐笔委托保留了“未成交的意图”,因此它既能用于还原订单簿的演化过程,也能用于分析撤单行为、大单拆分、算法交易痕迹等微观结构问题。

但真正动手处理这份数据时,第一个拦路虎往往不是策略逻辑,而是字段映射。上交所与深交所的逐笔委托在字段命名、字段数量、编码方式、甚至“委托”这一概念本身的边界上都不一致。同一个“买卖方向”,深市用字符编码,沪市用数字;同一个“订单号”,两市的位数和生成规则不同;深市逐笔委托中还包含“撤单”类型的记录,而沪市的撤单则体现在独立的成交/撤单消息里。如果不先把这些差异梳理清楚,后续任何订单簿重建都会在第一步就错位。

本课程的学习目标可以概括为三层。第一层是能读懂:拿到一份原始的逐笔委托文件,知道每个字段的含义、取值范围和单位。第二层是能对齐:建立沪深两套字段之间的映射关系,把两路异构数据归一化成统一的内部结构。第三层是能用对:在映射正确的前提下,完成订单簿重建、委托生命周期追踪等实战任务,并能定位映射错误引发的异常。这三层目标贯穿全部30节,而本节要完成的是最基础也最关键的一步——把数据环境搭起来,把第一份原始数据读进来、看清楚。

数据环境的组成与搭建思路

一个可用的逐笔委托研究环境,通常由三部分组成:行情数据源、本地存储、读取与解析工具链。数据源方面,实盘接入需要券商提供的Level-2行情授权与对应的API(如上交所的Binary行情、深交所的Binary/STEP行情),这类接入涉及权限申请和网络配置,成本较高;对于学习和研究,更现实的做法是使用历史逐笔委托文件,交易所或数据商提供的逐笔委托数据一般以按日、按股票或按时段的二进制/文本文件形式落盘。

本地存储建议按“交易所/日期/证券代码”的层级组织目录,避免所有文件堆在一个文件夹里。读取工具链方面,Python生态中的pandas适合处理文本或已解析的表格数据,而二进制原始文件则需要按交易所公布的字段结构做定长解析。本节我们以一个示例性的文本格式逐笔委托文件为对象,演示从读取到初步观察的完整过程;示例中的字段名、取值和记录均为教学构造,不代表任何真实交易日的实际行情。

下面这张图展示了本节数据环境的整体结构与数据流向:从行情源到本地文件,再经过解析层进入统一字段结构,最终支撑订单簿重建。图中同时标出了沪深两路数据在解析层汇合的位置,这正是后续字段映射工作的落点。

逐笔委托数据环境:从行情源到订单簿 上交所 Level-2 Binary 逐笔委托 数字编码方向 深交所 Level-2 Binary/STEP 逐笔委托 字符编码方向 + 撤单类型 本地文件目录(示例) data/SSE/20240115/600000.csv data/SZSE/20240115/000001.csv 解析与字段映射层 定长/分隔符解析 → 字段重命名 → 方向与类型归一化 统一结构:时间 / 订单号 / 方向 / 价格 / 数量 / 类型 统一逐笔委托表(DataFrame) 每行一笔委托,沪深字段已对齐,可直接进入订单簿重建 订单簿重建 / 委托生命周期追踪

读取第一份原始数据并做初步观察

假设我们已经拿到一份示例文件 data/SZSE/20240115/000001.csv,采用逗号分隔,每行一笔委托。示例字段包括:seq(消息序号)、time(时间,精确到毫秒)、order_no(订单号)、side(方向,B/S)、price(委托价,元)、qty(委托数量,股)、order_type(委托类型,1限价/2市价/3撤单)。读取代码如下:

import pandas as pd

path = "data/SZSE/20240115/000001.csv"
df = pd.read_csv(path, dtype={"order_no": str, "side": str})

print(df.shape)
print(df.head(8))
print(df["side"].value_counts())
print(df["order_type"].value_counts())
print(df["time"].min(), df["time"].max())

读取后要做的第一轮观察,重点看四件事。第一是规模与时间范围:行数是否与当日该股票的活跃度大致匹配,时间是否落在连续竞价时段(示例中若为 09:30:00.000 至 14:57:00.000 之间,说明文件覆盖了主要交易时段)。第二是方向取值:side 是否只有 B 和 S 两种,若出现空值或其它字符,说明存在需要单独处理的记录。第三是委托类型分布:order_type 中是否出现 3(撤单),撤单占比是否合理——示例数据中若撤单占比在百分之几到十几之间,属于常见量级;若接近一半,则要怀疑是否把成交记录误读成了撤单。第四是订单号唯一性:同一订单号是否在新增和撤单中各出现一次,这决定了后续能否用订单号做生命周期关联。

这里有一个容易被忽略的细节:价格字段的单位与精度。深市逐笔委托的原始价格常以“分”为单位的整数存储,而文本导出后可能已转为元。示例中 price 若出现 10.35 这样的两位小数,说明已是元;若出现 1035 这样的整数,则需要在解析时除以 100。这个判断必须在读取阶段就确认,否则后续订单簿的价位聚合会整体错位一百倍。同理,数量字段要确认单位是“股”还是“手”,示例中若单笔数量动辄上万,基本可判定为股。

初步观察阶段建议把 df.head()、value_counts()、describe() 三件事固定做一遍,并把结果记录在当日的观察笔记里。字段的单位、编码、取值范围一旦确认,就写进解析配置,后续所有日期复用同一套配置,避免每天重新猜。

从“看清楚”到“能对齐”

完成上述观察后,我们手里就有了一份“看得懂”的深市逐笔委托数据。但本课程的核心任务是沪深映射,所以下一步要做的,是把上交所的同类文件也读进来,逐字段对照。上交所示例文件 data/SSE/20240115/600000.csv 的字段可能是 seq、time、order_no、bs_flag(1买/2卖)、price、qty、order_kind(A限价/B市价)。把两份 head() 并排放在一起,差异立刻显现:方向字段一个用字符、一个用数字;委托类型一个含撤单、一个不含;订单号位数不同。这些差异就是后续每一节要逐一解决的映射点。

本节不急于给出完整映射表,而是先把环境和方法立起来:数据源清楚、目录清楚、读取代码可复现、初步观察有固定检查项。做到这一步,读者应当能够独立地把任意一个交易日的沪深逐笔委托文件读入内存,并用自己的话描述出这份数据的规模、时段、方向构成和类型构成。这是后续所有映射与订单簿工作的地基。