2. 高频行情数据基础

在进入 Numba 与 Cython 的加速实战之前,必须先建立对高频行情数据本身的准确认知。加速的前提是数据模型清晰:如果连一条逐笔成交的字段语义、盘口快照的更新方式、订单簿的维护规则都不清楚,那么后续无论用多快的编译手段,都只是在错误的结构上做无效优化。本节围绕四类核心对象展开:逐笔成交、盘口快照、订单簿数据结构,以及时间戳与序列化格式。

一、核心原理:三类行情对象与一条数据链路

交易所对外发布的行情,本质上是对“订单簿状态变化”的不同粒度描述。逐笔成交(Trade/Tick)记录的是撮合引擎实际发生的成交事件,通常包含成交价、成交量、成交方向(主动买/主动卖)、成交编号与时间戳。盘口快照(Snapshot/Quote)记录的是某一时刻订单簿前 N 档的买卖报价与挂单量,例如 Level-1 只有一档最优买卖价,Level-2 提供十档甚至更多。订单簿(Order Book)则是把逐笔委托与逐笔成交按价格优先、时间优先规则重建出的完整限价簿结构。

三者关系可以概括为:订单簿是“状态”,逐笔是“事件”,快照是“状态的周期采样”。事件驱动状态变化,快照用于校验与快速初始化。理解这条链路,是后续设计增量更新与批量计算的基础。

高频行情数据链路:事件 → 状态 → 采样 逐笔委托/成交 Event 价格·数量·方向·序号 订单簿 State 买卖档位·队列·深度 盘口快照 Snapshot 前N档·周期采样 时间戳与序列化: 交易所时间戳(Exchange TS)→ 网关接收时间(Recv TS)→ 本地处理时间(Local TS) 序列化格式:二进制(SBE/FAST/自定义)优先,文本(JSON/CSV)仅用于调试 关键约束:字段对齐、字节序、变长字段、时间精度(纳秒/微秒)

二、方法流程:从原始报文到可用结构

高频数据处理通常遵循一条固定流程:接收原始报文 → 解析序列化格式 → 提取字段 → 更新订单簿或生成特征 → 输出到策略或存储。每一步都影响后续加速策略的选择。

  1. 接收与缓冲:使用环形缓冲区或内存映射文件接收原始字节流,避免频繁分配内存。
  2. 解析:按协议定义逐字段读取,注意字节序与对齐。二进制协议通常用 struct 或 memoryview 解析。
  3. 时间戳归一:将交易所时间、接收时间、本地处理时间统一到同一时间基准,便于延迟分析。
  4. 状态更新:逐笔成交更新最近成交价与成交量;逐笔委托更新订单簿对应档位。
  5. 快照生成:按固定周期或按事件数触发,输出前 N 档盘口。

关键点:解析阶段应尽量使用零拷贝(memoryview、numpy.frombuffer),把字段提取与结构更新分离,便于后续用 Numba 对纯计算部分加速。

三、案例/场景:逐笔成交与盘口快照的字段设计

下面给出一个典型的逐笔成交与盘口快照字段清单,便于在代码中定义结构化 dtype 或 Cython cdef 结构体。

对象字段类型说明
逐笔成交ts_exchangeint64交易所时间戳(纳秒)
逐笔成交pricefloat64成交价
逐笔成交volumeint64成交量(股/手)
逐笔成交sideint81=主动买,-1=主动卖
逐笔成交seqint64成交序号,用于去重与排序
盘口快照tsint64快照时间戳
盘口快照bid_px[10]float64买十档价格
盘口快照bid_sz[10]int64买十档数量
盘口快照ask_px[10]float64卖十档价格
盘口快照ask_sz[10]int64卖十档数量

在 Python 中可以用 numpy 结构化数组定义,在 Cython 中则用 cdef packed struct 保证内存布局紧凑:

import numpy as np

trade_dtype = np.dtype([
    ('ts_exchange', 'i8'),
    ('price', 'f8'),
    ('volume', 'i8'),
    ('side', 'i1'),
    ('seq', 'i8'),
])

snapshot_dtype = np.dtype([
    ('ts', 'i8'),
    ('bid_px', 'f8', (10,)),
    ('bid_sz', 'i8', (10,)),
    ('ask_px', 'f8', (10,)),
    ('ask_sz', 'i8', (10,)),
])

四、误区/复盘:时间戳与序列化常见陷阱

误区一:混用不同精度的时间戳。交易所可能用纳秒,网关用微秒,本地用毫秒。直接相减会得到错误延迟。必须统一到同一单位,并明确基准。

误区二:忽略字节序与对齐。二进制协议若未按 packed 布局解析,字段偏移会错位,导致价格与数量完全错乱。

误区三:用文本格式做高频解析。JSON/CSV 解析开销大且不稳定,仅适合调试。生产环境应使用二进制协议。

误区四:订单簿更新未处理撤单与改单。只处理成交会导致簿状态漂移,必须按委托编号维护队列。

复盘建议:先用小样本逐条打印解析结果,与交易所官方回放工具比对;确认字段无误后,再引入 Numba/Cython 加速。加速应作用于“已正确的逻辑”,而不是用来掩盖数据模型错误。