2. 行情数据体系概览
在量化交易、行情终端和交易系统的开发中,我们几乎每天都会接触 Level1、Level2 和 Tick 这三类行情数据。很多初学者会把它们简单理解为“快照、盘口、逐笔”三种粒度,但在真实工程里,它们并不是简单的包含关系,而是由交易所撮合机制、行情发布协议和业务需求共同塑造的三层数据体系。理解它们的区别与联系,是后续解析字段、设计存储和构建策略的基础。
核心原理:三层数据的生成逻辑
交易所的撮合引擎在每一笔委托进入、成交或撤单时,都会产生内部事件。这些事件经过行情发布系统加工后,形成不同粒度的对外数据:
- Level1(L1):通常指最优一档买卖盘及最新成交价、成交量、成交额等。它是“结果快照”,按固定频率(如每3秒)或事件触发推送,字段少、带宽低,适合展示和轻量策略。
- Level2(L2):在 L1 基础上扩展为多档买卖盘(如十档、二十档),并常包含委托队列、逐笔委托、逐笔成交等更细的订单簿信息。它描述的是“市场深度”,适合做盘口分析、大单监控和做市策略。
- Tick:严格来说,Tick 是“逐笔数据”的统称,包括逐笔成交(Trade)和逐笔委托(Order)。它记录每一笔撮合事件,是粒度最细、信息最完整的原始数据,也是还原订单簿和回测的基石。
三者的关系可以概括为:Tick 是原始事件流,L2 是 Tick 的聚合与深度扩展,L1 是 L2 的进一步压缩与快照。越靠近 Tick,信息越完整、频率越高、存储与处理成本越大;越靠近 L1,信息越精简、越易用,但细节丢失也越多。
方法流程:从 Tick 到 L1 的加工链路
理解数据体系,最好的方式是看一条完整的加工链路。以股票市场为例:
- 采集原始 Tick:通过交易所行情网关或行情商 API 接收逐笔成交和逐笔委托。每条记录包含时间戳、证券代码、价格、数量、买卖方向、委托编号等。
- 维护订单簿:用逐笔委托和逐笔成交实时更新买卖盘队列,计算每一档的价格和挂单量,形成 L2 深度数据。
- 生成 L1 快照:从订单簿中取最优一档,结合最新成交价、成交量、成交额等,按固定频率打包成 L1 快照。
- 分发与存储:L1 用于前端展示和轻量策略;L2 用于盘口监控和做市;Tick 落库用于回测和合规审计。
下面是一段简化的伪代码,展示如何从逐笔成交更新最新价和成交量:
# 逐笔成交处理示例
def on_trade(tick):
code = tick.symbol
price = tick.price
volume = tick.volume
# 更新最新价
latest_price[code] = price
# 累加成交量与成交额
total_volume[code] += volume
total_amount[code] += price * volume
# 更新 L1 快照
l1_snapshot[code] = {
"last": price,
"volume": total_volume[code],
"amount": total_amount[code],
"bid1": order_book[code].bid1,
"ask1": order_book[code].ask1
}
案例/场景:不同数据在各业务中的选择
| 业务场景 | 推荐数据 | 原因 |
|---|---|---|
| 行情展示终端 | Level1 | 字段少、刷新快、带宽低,满足普通用户看盘需求 |
| 盘口深度分析 | Level2 | 需要多档买卖盘和委托队列,判断支撑压力 |
| 高频回测 | Tick | 需要逐笔事件还原订单簿,保证回测精度 |
| 做市策略 | Level2 + Tick | 既要深度盘口,又要逐笔成交判断库存风险 |
| 合规审计 | Tick | 逐笔记录可追溯,满足监管要求 |
提示:选择数据粒度时,不要盲目追求 Tick。如果策略只需要分钟级信号,使用 L1 或 L2 快照即可,Tick 会带来巨大的存储和计算开销。
误区/复盘:常见认知偏差
- 误区一:L2 一定包含 Tick。实际上,部分行情商的 L2 只提供多档盘口快照,并不包含逐笔委托和逐笔成交。需要仔细查看接口文档。
- 误区二:Tick 数据没有延迟。Tick 虽然粒度细,但同样存在网络延迟和交易所发布延迟,高频场景下需要做时间戳对齐。
- 误区三:L1 快照可以还原订单簿。L1 只有最优一档,无法还原深度,不能用于精细回测。
- 误区四:所有市场的 Tick 字段一致。股票、期货、期权、数字货币的 Tick 字段差异很大,解析前必须确认字段定义。
注意:在实盘系统中,Tick 数据的乱序和重复是常见问题。建议在入库前做去重和排序,并以交易所时间戳为准,避免用本地接收时间导致回测偏差。