高频数据基础:Tick数据与Level2行情
做量化交易这些年,我越来越觉得——高频数据就像石油,得先知道它埋在哪、长什么样,才能谈怎么提炼。今天咱们就从最底层的Tick数据说起。
什么是Tick数据?
说白了,Tick就是交易所每笔成交的原始记录。每一笔交易,都会生成一条Tick。它记录的是:
- 成交时间:精确到毫秒甚至微秒
- 成交价格:这笔交易实际成交价
- 成交量:这笔交易成交了多少手
- 成交方向:主动买还是主动卖(这个很重要)
举个例子,A股市场一天的Tick数据量,大概在几千万条到上亿条不等。嗯,你没看错,光一个股票一天就能产生几千条Tick。
核心区别:Tick数据是「逐笔成交」,而分钟线是「聚合统计」。你想想看,一根1分钟K线,可能包含了上百笔成交,但只保留了开高低收四个价格。中间那些细节,全丢了。
Level2行情 vs Level1行情
我记得刚入行时,用的还是Level1数据,也就是每3秒刷新一次的快照。后来接触到Level2,才真正打开了新世界。
| 对比项 | Level1(基础行情) | Level2(深度行情) |
|---|---|---|
| 刷新频率 | 3秒一次 | 实时逐笔 |
| 买卖盘口 | 5档 | 10档(甚至全档) |
| 逐笔成交 | 无 | 有 |
| 委托队列 | 无 | 有(前50笔委托) |
| 数据量 | 小 | 大(约Level1的50-100倍) |
Level2里最值钱的是什么?我个人认为是「委托队列」。它能告诉你:在某个价位上,到底有多少单子在排队。我曾经靠这个特征,抓过好几次盘口异动。
数据频率与时间框架
做高频策略,你得先想清楚:你要在什么时间尺度上做决策?
- Tick级(毫秒-秒):做市商、高频套利,对延迟极度敏感
- 秒级(1秒-10秒):短线动量策略,需要捕捉微观结构
- 分钟级(1分钟-5分钟):日内趋势跟踪,兼顾信号质量与交易成本
- 小时级及以上:其实已经不算高频了,属于中低频
我的建议:刚开始做高频研究,别一上来就搞Tick级。先试试1秒或5秒的聚合数据,把策略逻辑跑通,再逐步降频到Tick。否则数据量太大,调试起来很痛苦。
数据存储格式:Parquet vs Arrow
高频数据量太大了,用CSV存?我劝你趁早放弃。我曾经用CSV存了一个月的Tick数据,结果一个文件就几十个GB,加载一次要等半小时。
现在业界主流就两个格式:
Parquet
- 列式存储,压缩率高(通常能压到原始大小的20%-30%)
- 适合「读多写少」的场景
- 支持谓词下推(只读取需要的列)
- 我习惯用它做历史数据归档
Arrow
- 内存列式格式,零拷贝读取
- 适合「实时计算」和「进程间通信」
- 加载速度比Parquet快10倍以上
- 我一般在策略回测的中间环节用它
实战建议:历史数据存Parquet,实时数据用Arrow。两者可以无缝转换,Pandas和Polars都原生支持。
数据源获取与清洗
数据源这块,我踩过不少坑。简单说几个靠谱的渠道:
- 交易所直连:最权威,但门槛高(需要券商资质)
- 第三方数据商:如万得、聚宽、Tushare,适合个人研究
- 开源数据集:如Kaggle上的高频数据,适合练手
数据清洗才是重头戏。我总结了一套「高频数据清洗三板斧」:
# 伪代码示例:Tick数据清洗流程
def clean_tick_data(df):
# 第一步:去重(同一毫秒的重复成交)
df = df.drop_duplicates(subset=['time', 'price', 'volume'])
# 第二步:异常值过滤(价格超出合理范围)
df = df[(df['price'] >= df['price'].quantile(0.001)) &
(df['price'] <= df['price'].quantile(0.999))]
# 第三步:时间对齐(补齐缺失的毫秒)
df = df.set_index('time').asfreq('1ms', method='ffill')
return df
避坑指南:我曾经因为没处理「集合竞价数据」,导致策略在开盘前5分钟疯狂报单。后来才发现,集合竞价的Tick和连续竞价的Tick,撮合逻辑完全不同。一定要分开处理!
知识体系总览
下面这张图,是我自己梳理的高频数据知识框架。你可以把它当作学习路线图:
嗯,这张图基本概括了本章的核心内容。从Tick数据出发,到Level2的深度行情,再到怎么存、怎么取、怎么洗,每一步都有坑,但也都有解法。
最后说一句:高频数据研究,80%的时间花在数据准备上,20%的时间才是策略开发。别嫌麻烦,把基础打牢了,后面会顺很多。