4. Tick数据与快照数据: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数据 | 快照数据 |
|---|---|---|
| 驱动方式 | 事件驱动(成交触发) | 时间驱动(定时生成) |
| 时间间隔 | 不均匀(毫秒到秒不等) | 均匀(固定间隔) |
| 数据粒度 | 单笔成交 | 整个订单簿 |
| 数据量 | 极大(活跃合约每天数亿条) | 较小(每天数万到数百万条) |
| 包含信息 | 价格、数量、方向、时间 | 所有买卖盘口的价格和数量 |
| 主要用途 | 订单流分析、微观结构 | 订单簿重建、流动性分析 |
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']]
}
这两种数据,一个像流水账,一个像照片。理解它们的区别,是做订单流分析的第一步。