第 2 章 · 01 ITCH 订单簿重建 本节摘要:本节是「市场与基本面数据」的开篇,讲怎么从 NASDAQ TotalView ITCH 这种最原始的二进制 tick 消息流重建出真实的限价订单簿。ITCH 是 NASDAQ 的原生直连数据协议,允许订阅者追踪每一笔限价订单从下达到成交或撤销的完整生命周期。本节讲三件事:ITCH v5.0 的二十多种消息类型长什么样、用 Python 标准库 怎么按字段切二进制、以及如何按消息顺序维护订单簿与成交逐笔。读完本节,你能解析一份约 12GB 的 ITCH 二进制样本文件,统计出当日各消息类型的频次,并为下一节的订单簿重建打下基础。 内容来源:原项目 下的 、 、 ,汉化并套用体系化模板。
本节摘要:本节是「市场与基本面数据」的开篇,讲怎么从 NASDAQ TotalView ITCH 这种最原始的二进制 tick 消息流重建出真实的限价订单簿。ITCH 是 NASDAQ 的原生直连数据协议,允许订阅者追踪每一笔限价订单从下达到成交或撤销的完整生命周期。本节讲三件事:ITCH v5.0 的二十多种消息类型长什么样、用 Python 标准库
struct怎么按字段切二进制、以及如何按消息顺序维护订单簿与成交逐笔。读完本节,你能解析一份约 12GB 的 ITCH 二进制样本文件,统计出当日各消息类型的频次,并为下一节的订单簿重建打下基础。
内容来源:原项目
02_market_and_fundamental_data/01_NASDAQ_TotalView-ITCH_Order_Book/下的01_parse_itch_order_flow_messages.ipynb、02_rebuild_nasdaq_order_book.ipynb、03_normalize_tick_data.ipynb,汉化并套用体系化模板。
⚠️ 风险提示:ITCH 样本文件约 12GB,部分步骤在 4 核 i7 + 32GB RAM 上要跑数小时,务必先小样本试跑;本节内容仅供学习,订单簿数据涉及交易所版权,实盘需取得合法授权。
阅读完本节,你应当能够:
struct 模块按偏移+长度+类型切二进制消息。订单簿(Order Book)是市场数据的源头——它实时记录每个价位上挂着的买单与卖单,反映市场深度。NASDAQ 提供三级行情:
| 级别 | 内容 |
|---|---|
| Level I | 实时最优买/卖价 |
| Level II | 各做市商报价 + 成交明细 |
| Level III | 可直接下单/改单(限做市商) |
订单簿的更新通过消息流传递。消息流的主流协议有两个:
💡 核心心法:FIX 是「行业普通话」,ITCH 是「交易所方言」。方言更细更快,适合做订单簿级微观结构研究;原书选 ITCH,正是因为它能让订阅者从下单到成交或撤销全程跟踪每一笔限价订单。
ITCH v5.0 规范定义了二十多种消息类型,覆盖系统事件、股票特征、限价订单的生命周期、成交、以及开盘/收盘集合竞价的净订单失衡(NOII)。在样本日(原书用的 2019-03-27 样本)出现频次最高的几类:
| 类型 | 含义 | 订单簿影响 |
|---|---|---|
A |
新增未归属限价订单 | 加入订单簿 |
F |
新增归属限价订单(带做市商) | 加入订单簿 |
U |
订单撤销并替换 | 删旧加新 |
D |
订单撤销 | 从簿中删除 |
X |
部分撤销 | 减数量 |
E |
部分或全部成交 | 减数量(可能多次) |
C |
以非展示价成交 | 减数量并改价 |
P |
非集合竞价成交 | 成交逐笔 |
Q |
集合竞价成交 | 开/收盘交叉 |
💡 核心心法:
A和D是订单簿的「加」和「删」;E/X是「减量」;P/Q是「成交」。重建订单簿本质就是把这些消息按时间顺序回放,维护一张订单号 → (价, 量, 方向)的字典。
每条消息的结构由规范文档用一张表定义。以系统事件消息为例:
| 字段 | 偏移 | 长度 | 类型 | 说明 |
|---|---|---|---|---|
| Message Type | 0 | 1 | Alpha | 如 S 表示系统事件 |
| Stock Locate | 1 | 2 | Integer | 永远 0 |
| Tracking Number | 3 | 2 | Integer | NASDAQ 内部追踪号 |
| Timestamp | 5 | 6 | Integer | 自午夜起的纳秒数 |
| ... | ... | ... | ... | ... |
struct 切二进制Python 标准库 struct 用「格式字符串」描述 C 结构体的内存布局,ITCH 解析全靠它。原 notebook 把 ITCH 的字段类型映射到 struct 格式字符:
# 来自 01_parse_itch_order_flow_messages.ipynb format_chars = { ('integer', 2): 'H', # 2 字节整数 => 'H' ('integer', 4): 'I', # 4 字节整数 => 'I' ('integer', 8): 'Q', # 8 字节整数 => 'Q' ('integer', 6): '6s', # 6 字节时间戳 => 先按字符串读再转 ('alpha', 1): 's', ('alpha', 8): '8s', }
然后从规范表(原项目附带 message_types.xlsx)生成 namedtuple 和格式串:
# 每条消息解析为 namedtuple,字段名直接来自规范 # alpha 类型字段还需 format_alpha 后处理(去空格、补 NULL) def format_alpha(m): return m.decode('ascii').rstrip('\x00').strip()
解析主循环的关键步骤(伪码):
with open(binary_path, 'rb') as f: while True: msg_type = f.read(1) # 首字节定类型 msg_len = spec[msg_type]['size'] msg = f.read(msg_len - 1) fields = struct.unpack(spec[msg_type]['fmt'], msg) # ... 转 DataFrame,处理 alpha 字段,parse timestamp
⚠️ 警告:二进制解析对偏移极其敏感,字节错位后面全乱。务必严格按规范表的
offset/length来;时间戳是「自午夜起的纳秒数」,不是 Unix 时间戳。
02_rebuild_nasdaq_order_book.ipynb 把解析好的消息按时间顺序回放,维护两张表:
{order_id: (side, shares, price, stock)}E/P/Q 消息累积。按这个状态机回放一整天的消息,任意时刻都能查到某只股票在某个价位的挂单量——这就是「重建订单簿」。
03_normalize_tick_data.ipynb 解决一个新问题:tick 数据按纳秒索引、噪声极大(买卖价来回弹跳,即 bid-ask bounce),不适合直接喂给大多数模型。需要重采样规整化:
| bar 类型 | 切分依据 | 适用 |
|---|---|---|
| 时间 bar | 固定时间窗口(1 分钟/5 分钟) | 最常见,但掩盖了活跃时段 |
| 成交量 bar | 累计成交量达阈值 | 改善分布,方差更稳 |
| 信息量 bar | 累计信息量(如价格变化) | Lopez de Prado 推荐 |
每个 bar 聚合出 open/high/low/close/volume,以及成交量加权均价 VWAP,后续章节做日内策略的基础。
💡 核心心法:时间 bar 简单但失真,成交量/信息量 bar 更贴近「市场真实活跃度」。Marcos Lopez de Prado 在《Advances in Financial Machine Learning》中系统论证过非时间 bar 的优越统计性质,原书采纳这一思路。
A/F(加)、D/X(删/减)、U(替换)、E/P/Q(成交)。struct 解析:用格式字符串按 offset/length/type 切二进制,alpha 字段要 format_alpha 后处理。{order_id: (side, shares, price)}。下一节,我们看 日内 bar 数据 AlgoSeek——ITCH 自己重建 bar 又慢又重,AlgoSeek 直接提供规整好的分钟 bar 数据,带丰富的供需属性,适合做日内策略。