Tick级数据结构:Level1/Level2/Level3行情数据、Order Book深度解析、Tick数据的存储格式
做高频交易这些年,我踩过最大的坑,就是没把Tick数据结构当回事。刚入行那会儿,我总觉得行情数据不就是价格和成交量嘛,有什么好研究的?直到有一次,我的策略在回测里跑得风生水起,一上实盘就亏得亲妈都不认识。查了三天三夜,最后发现是Tick数据的时间戳精度不够,导致信号延迟了2毫秒。嗯,2毫秒,在高频世界里,这足够让市场吃掉你所有的利润。
所以今天,咱们就好好聊聊Tick级数据。说白了,这是高频交易的「原材料」。原材料不好,菜做得再好也是白搭。
一、Level1 / Level2 / Level3 行情数据
这三个级别,我习惯叫它们「行情数据的三个世界」。你想想看,不同级别的数据,看到的市场深度完全不一样。
Level1:普通玩家的视角
这是最基础的数据,散户们天天看的就是这个。包含什么?最新成交价、成交量、涨跌幅、买一卖一价和量。说白了,就是告诉你「现在有人愿意用多少钱买,多少钱卖」,但你看不到更深层次的挂单。
我个人习惯把Level1叫做「冰山一角」——你只看到了海面上那一小块,海底下藏着什么,完全不知道。
Level2:进阶玩家的武器
Level2就厉害多了。它提供了买卖前10档甚至前50档的挂单数据。你能看到谁在什么价位挂了多大的单子,挂单是在增加还是在撤单。
我在项目中遇到过一件事:有一次策略只用了Level1数据做判断,结果被一个大户的「冰山订单」给骗了。什么叫冰山订单?就是表面上只挂了一点点单,实际上底下藏着巨量。Level1根本看不到,Level2才能发现端倪。
Level3:内行人的显微镜
Level3数据,说白了就是交易所内部的全量数据。它包含了订单簿的每一次变化——每一笔挂单、每一笔撤单、每一笔成交,精确到微秒甚至纳秒级别。
我曾经做过一个统计:同样的策略,用Level2数据回测年化收益是15%,换成Level3数据后变成了22%。为什么?因为Level3能捕捉到那些「瞬间出现又消失」的流动性,这些信息在Level2里已经被聚合了,看不到了。
| 数据级别 | 包含内容 | 更新频率 | 适用场景 |
|---|---|---|---|
| Level1 | 最新价、成交量、买一卖一 | 秒级 | 普通交易、低频策略 |
| Level2 | 前10-50档挂单、逐笔成交 | 毫秒级 | 日内交易、中频策略 |
| Level3 | 全量订单簿、逐笔挂撤单 | 微秒/纳秒级 | 高频做市、套利策略 |
二、Order Book(订单簿)深度解析
订单簿,英文叫Order Book,其实就是交易所里所有未成交订单的集合。我经常跟团队里的人说:「订单簿就是市场的X光片,能让你看到市场的骨架。」
一个典型的订单簿长这样:左边是买单(Bid),从高到低排列;右边是卖单(Ask),从低到高排列。中间那个缝隙,就是买卖价差(Spread)。
订单簿有几个关键指标,我每次做策略都会盯着看:
- 订单簿深度:某个价位上挂了多少单。深度越大,价格越难被打穿。
- 订单簿斜率:不同价位的挂单量变化速度。斜率陡峭,说明市场对价格变化很敏感。
- 买卖压力比:买单总量除以卖单总量。大于1说明买方强势,小于1说明卖方强势。
避坑指南:我曾经犯过一个错误,只看买卖压力比就开仓。结果发现,那个压力比是假的——有人在挂单后马上撤单,制造了虚假的买卖压力。后来我加了一个「挂单存活时间」的过滤条件,才把这个问题解决掉。
三、Tick数据的存储格式:Parquet vs Arrow
说到存储,我得先吐槽一句:很多人的Tick数据存储方式,简直是在浪费硬盘和内存。我见过有人用CSV存Tick数据,一个文件几十个G,读一次要等半小时。这在高频交易里,根本没法用。
目前业界主流的方案有两个:Parquet和Arrow。我两个都用过,各有千秋。
Parquet:磁盘上的王者
Parquet是一种列式存储格式。什么叫列式存储?就是同一列的数据放在一起。这样做的好处是:如果你只需要读取「时间戳」和「价格」两列,Parquet可以只加载这两列的数据,其他列直接跳过。
我在项目中用Parquet存储历史Tick数据,压缩比能达到10:1。什么意思?原来100G的CSV数据,存成Parquet只要10G。而且读取速度还快了5倍以上。
# 用Pandas读取Parquet文件
import pandas as pd
# 只读取需要的列,节省内存
df = pd.read_parquet(
'tick_data.parquet',
columns=['timestamp', 'price', 'volume']
)
print(f"加载了 {len(df)} 条Tick数据")
Arrow:内存里的闪电
Arrow跟Parquet不一样,它主要用在内存中。Arrow的核心理念是「零拷贝」——数据在不同系统之间传递时,不需要序列化和反序列化,直接共享内存地址。
我记得有一次做实时行情处理,用Python的列表存数据,处理延迟在50微秒左右。换成Arrow之后,延迟降到了5微秒。为什么?因为Arrow底层是用C++写的,而且数据在内存中是连续存储的,CPU缓存命中率极高。
| 特性 | Parquet | Arrow |
|---|---|---|
| 存储位置 | 磁盘 | 内存 |
| 压缩率 | 高(10:1) | 低(无压缩) |
| 读取速度 | 快(列式读取) | 极快(零拷贝) |
| 适用场景 | 历史数据存储、回测 | 实时数据处理、流式计算 |
四、知识体系总览
说了这么多,我画了一张图,帮你把整个知识体系串起来。你看完这张图,应该就能明白Tick数据从采集到存储再到使用的全链路了。
嗯,这张图基本把今天的内容串起来了。从数据来源到订单簿解析,再到存储格式的选择,每一步都有讲究。我个人觉得,搞高频交易的人,至少要把Level2和Parquet/Arrow玩明白。Level3嘛,看你的策略需求,不是所有人都需要那么精细的数据。
好了,今天就聊到这儿。记住,数据质量决定策略上限。别像我当年那样,在数据结构上栽跟头。