10. 高频数据下的深度分析:Tick级数据、逐笔成交与订单簿快照、数据清洗

做量化交易的朋友都知道,低频数据看的是趋势,高频数据看的是博弈。而博弈最真实的战场,就在Tick级数据里。

我个人习惯把高频数据比作市场的「心电图」。你想想看,日线级别的K线,就像医生每天给你量一次血压,能看出你有没有高血压,但看不出你心脏早搏了几次。而Tick级数据,就是24小时动态心电监护仪,每一跳都记录得清清楚楚。

这一章,我们就来拆解高频数据的三个核心要素:Tick数据、逐笔成交、订单簿快照。以及——嗯,这里要注意——数据清洗这个环节,我敢说80%的量化团队在这上面踩过坑。

10.1 Tick级数据:市场最原始的呼吸

Tick数据是什么?说白了,就是交易所每一次行情变动的最小记录单元。它不像分钟线那样做了聚合,而是「有变就记,不变不记」。

一个标准的Tick数据行,通常包含这些字段:

字段名 含义 示例值
Symbol 合约代码 rb2410
Timestamp 时间戳(精确到毫秒或微秒) 2024-09-15 09:30:00.123
LastPrice 最新成交价 3725
Volume 当前累计成交量 128450
Turnover 当前累计成交额 478562300
BidPrice1 ~ BidPrice5 买一到买五价格 3724, 3723, ...
AskPrice1 ~ AskPrice5 卖一到卖五价格 3726, 3727, ...

我在项目中遇到过一个问题:某家数据商提供的Tick数据,时间戳只精确到秒。你想想看,一秒内可能发生几十笔成交,这数据基本没法用。后来我换了一家精度到微秒的供应商,才真正开始做高频分析。

避坑指南: 我曾经因为Tick数据的时间戳精度不够,导致回测出来的策略收益曲线漂亮得不像话。结果实盘一跑,直接亏了三天。后来才发现,数据的时间戳精度不足,导致订单簿重建时出现了大量「幻影订单」。

10.2 逐笔成交:看清每一笔交易的「真面目」

逐笔成交和Tick数据有什么区别?很多人搞混了。我简单解释一下:

  • Tick数据:是行情快照,告诉你「现在价格是多少,买卖盘口长什么样」
  • 逐笔成交:是每一笔实际成交的记录,告诉你「谁买了谁卖了,成交了多少手」

逐笔成交的核心字段包括:

TradeID: 202409150000123
Timestamp: 09:30:01.456
Price: 3725
Volume: 10
Side: B (买方主动吃单)
BuyOrderID: 12345678
SellOrderID: 87654321

为什么要区分买方主动还是卖方主动?这涉及到「订单流」的概念。买方主动吃单,说明买方更着急,市场情绪偏多;卖方主动砸单,说明卖方更强势。这个信号,在Tick数据里是看不出来的。

我记得有一次做股指期货的微观结构分析,发现某个品种在开盘前3分钟,逐笔成交中买方主动的比例突然从55%飙升到82%。我当时就觉得不对劲,果然,5分钟后一个大单砸下来,价格瞬间跳水。这就是逐笔成交数据的价值——它能提前暴露大资金的意图。

10.3 订单簿快照:市场的「实时地图」

订单簿快照,就是交易所每隔一段时间(通常是10毫秒、100毫秒或500毫秒)发布的当前所有挂单情况。它告诉你:

  • 买一到买十(或更深)的价格和挂单量
  • 卖一到卖十的价格和挂单量
  • 总买量、总卖量

订单簿快照的核心用途有两个:

  1. 计算市场深度:比如你想买100手,需要吃掉几个价位?成本是多少?
  2. 计算价格弹性:一个大单进来,价格会滑点多少?市场能「消化」多大的订单?

下面这张图,是我自己画的高频数据知识体系结构,帮你理清这三者的关系:

高频数据三大核心要素 Tick级数据 行情快照 + 最新成交 逐笔成交 每一笔交易的细节 订单簿快照 挂单深度与分布 数据清洗层 输出:市场深度指标 · 价格弹性指标 · 订单流分析 三者缺一不可,数据清洗是连接原始数据与有效分析的桥梁

10.4 数据清洗:高频分析中最脏最累的活

做高频分析,80%的时间花在数据清洗上,这话一点都不夸张。我见过太多团队,策略逻辑写得漂漂亮亮,结果数据一进来全是坑。

高频数据常见的「脏数据」问题,我列几个典型的:

  • 时间戳错乱:某笔成交的时间戳比前一笔还早,明显是数据源搞错了
  • 价格异常:突然出现一个0元成交,或者价格比前一秒跳了10%
  • 重复数据:同一笔成交被推送了两次
  • 缺失数据:某个时间段的订单簿快照丢了
  • 订单簿不一致:买一价高于卖一价,这明显是数据错位了
核心原则: 数据清洗不是「删掉异常值」就完事了。你要理解这个异常值是怎么产生的——是交易所的bug?是网络延迟?还是数据商的处理问题?不同的原因,处理方式完全不同。

我分享一个我自己常用的数据清洗流程:

# 伪代码:高频数据清洗流水线
def clean_tick_data(df):
    # 1. 时间戳排序与去重
    df = df.sort_values('Timestamp')
    df = df.drop_duplicates(subset=['Timestamp', 'LastPrice', 'Volume'])
    
    # 2. 价格合理性检查
    # 剔除价格 <= 0 的记录
    df = df[df['LastPrice'] > 0]
    
    # 3. 价格跳变检测(超过3个标准差视为异常)
    price_changes = df['LastPrice'].pct_change()
    abnormal = price_changes.abs() > 0.03  # 3%阈值
    df.loc[abnormal, 'LastPrice'] = np.nan
    df['LastPrice'] = df['LastPrice'].ffill()  # 向前填充
    
    # 4. 订单簿一致性检查
    mask = df['BidPrice1'] < df['AskPrice1']
    df = df[mask]
    
    return df

你可能会问:为什么不用插值法填充异常价格?嗯,这里要注意——高频数据里,价格跳变可能是真实的「闪崩」或「拉升」,你把它插值平滑掉了,真实的市场信号就丢了。我建议的做法是:标记异常,但不修改,让策略自己去决定怎么处理。

10.5 实战中的几个坑

最后,我总结几个高频数据清洗中容易踩的坑:

Tip 1: 不要相信数据商给的「已清洗」数据。我接过好几家数据商的「清洗版」数据,结果一检查,该有的问题一个不少。自己动手,丰衣足食。
Tip 2: 逐笔成交数据里,注意「撤单」和「成交」的区分。有些数据商会把撤单也当成成交推送,这会导致成交量虚高。
Warning: 我曾经因为没处理好「集合竞价」阶段的数据,导致开盘前几分钟的订单簿深度计算完全错误。集合竞价阶段的订单簿结构和连续竞价阶段不一样,一定要分开处理。

好了,这一章的内容就到这里。高频数据是微观结构分析的基石,数据清洗是基石上的基石。下一章我们会深入讨论如何从这些清洗后的数据中,提取出真正有交易价值的市场深度指标。