4. Tick数据与快照数据

做高频交易的朋友,每天打交道最多的就是这两类数据——Tick和快照。我刚开始接触订单流分析时,也经常把两者搞混,直到有一次回测策略时发现结果跟实盘差了好几个数量级,才意识到问题出在数据源的理解上。

说白了,Tick数据是交易所最原始的“流水账”,而快照数据是某个时间点的“快照”。今天我们就来彻底搞清楚它们。

4.1 Tick数据的结构

Tick数据,也叫逐笔成交数据。它记录的是每一笔成交的详细信息。你可以把它想象成超市收银台的每一笔交易小票——谁买了什么、多少钱、多少数量、什么时候买的,一清二楚。

一个标准的Tick数据结构通常包含以下字段:

字段名 含义 示例值
Symbol 合约代码 BTCUSDT
Timestamp 成交时间(纳秒级) 2024-01-15 09:30:00.123456789
Price 成交价格 42850.12
Volume 成交量(股/张) 100
Side 成交方向(Buy/Sell) Buy
TradeID 成交编号 12345678

这里有个细节需要注意——成交方向。它表示这笔成交是由买方主动发起的,还是卖方主动发起的。这个信息在订单流分析中至关重要,因为它能告诉我们谁在“主动吃单”。

核心要点:Tick数据是“事件驱动”的——有成交才产生一条记录。没有成交,就没有Tick。所以Tick数据的时间间隔是不均匀的。

我举个例子,假设某只股票在09:30:00.000到09:30:00.001这一毫秒内成交了3笔,那就会产生3条Tick记录。而接下来可能整整100毫秒都没有成交,那就一条Tick都没有。

4.2 快照数据的生成

快照数据,也叫Order Book Snapshot。它记录的是某个时间点整个订单簿的状态——当前所有的买单和卖单,以及它们的价格和数量。

快照数据是怎么生成的?说白了,就是交易所每隔一段时间(比如100毫秒、500毫秒或1秒),把当前订单簿的“快照”拍下来,然后推送给订阅者。

一个标准的快照数据结构通常包含:

字段名 含义 示例值
Symbol 合约代码 BTCUSDT
Timestamp 快照时间 2024-01-15 09:30:00.100
Bids 买单列表(价格, 数量) [[42850.00, 500], [42849.50, 300], ...]
Asks 卖单列表(价格, 数量) [[42850.50, 400], [42851.00, 600], ...]
BidDepth 买单总深度 10
AskDepth 卖单总深度 10

快照数据是“时间驱动”的——不管有没有成交,到时间了就生成一条。所以快照数据的时间间隔是均匀的。

我的经验:在实际项目中,我通常同时订阅Tick和快照两个数据流。Tick用来分析微观的订单流行为,快照用来维护本地的订单簿状态。两者配合使用,才能还原市场的全貌。

4.3 两者的核心区别

为了让你更直观地理解,我画了一张对比图:

Tick数据 vs 快照数据 对比 Tick数据 事件驱动 有成交才产生 时间间隔不均匀 记录单笔成交细节 数据量巨大(每天数亿条) 快照数据 时间驱动 定时生成(如100ms一次) 时间间隔均匀 记录整个订单簿状态 数据量相对较小 关键区别 Tick数据告诉你“发生了什么”,快照数据告诉你“当前是什么状态” Tick适用场景 订单流分析、微观结构研究 快照适用场景 订单簿重建、流动性分析

为了让你更清楚地理解,我整理了一个对比表格:

对比维度 Tick数据 快照数据
驱动方式 事件驱动(成交触发) 时间驱动(定时生成)
时间间隔 不均匀(毫秒到秒不等) 均匀(固定间隔)
数据粒度 单笔成交 整个订单簿
数据量 极大(活跃合约每天数亿条) 较小(每天数万到数百万条)
包含信息 价格、数量、方向、时间 所有买卖盘口的价格和数量
主要用途 订单流分析、微观结构 订单簿重建、流动性分析

4.4 实际项目中的选择

我记得有一次做策略回测,用的是快照数据。结果发现策略在实盘时表现完全不一样。后来排查才发现,快照数据丢失了两次快照之间的所有成交细节——而这些细节恰恰是策略的核心信号来源。

避坑指南:千万不要用快照数据做订单流分析!快照数据丢失了两次快照之间的所有成交信息,你根本看不到谁在主动吃单、吃了多少。订单流分析必须用Tick数据。

反过来,如果你只是想了解某个时间点的市场深度,那快照数据就足够了。比如你想知道当前买一价和卖一价的价差是多少,或者某个价格档位有多少挂单,快照数据直接给你答案。

在实际项目中,我通常的做法是:

  • Tick数据:用于实时订单流分析、微观结构研究、高频策略信号生成
  • 快照数据:用于维护本地订单簿、计算流动性指标、做中低频策略
  • 两者结合:用Tick数据更新订单簿(增量更新),用快照数据做校验(全量同步)

嗯,这里要注意一点——如果你同时订阅Tick和快照,一定要处理好两者的时间对齐问题。我曾经遇到过Tick和快照的时间戳相差几十毫秒的情况,导致订单簿状态混乱。后来我加了一个时间同步机制,才解决了这个问题。

最后,给你一个简单的代码示例,展示如何解析Tick数据和快照数据:

# Tick数据解析示例
def parse_tick(tick_raw):
    return {
        'symbol': tick_raw['symbol'],
        'timestamp': tick_raw['timestamp'],
        'price': float(tick_raw['price']),
        'volume': int(tick_raw['volume']),
        'side': tick_raw['side'],  # 'Buy' or 'Sell'
        'trade_id': tick_raw['trade_id']
    }

# 快照数据解析示例
def parse_snapshot(snapshot_raw):
    return {
        'symbol': snapshot_raw['symbol'],
        'timestamp': snapshot_raw['timestamp'],
        'bids': [(float(p), int(q)) for p, q in snapshot_raw['bids']],
        'asks': [(float(p), int(q)) for p, q in snapshot_raw['asks']]
    }

这两种数据,一个像流水账,一个像照片。理解它们的区别,是做订单流分析的第一步。