4、Tick级数据与时间序列:Tick数据结构(时间、价格、成交量)、逐笔成交与逐笔委托、Level 1/Level 2/Level 3数据区别、数据清洗与对齐

聊到美股微观结构,Tick级数据是绕不开的硬骨头。我刚开始接触这个领域时,以为Tick数据就是简单的「时间、价格、成交量」三列。后来在实盘回测中被坑过几次,才明白这里面门道有多深。

说白了,Tick数据是市场最原始的呼吸记录。每一笔成交、每一条委托单,都是市场参与者的真实投票。你想想看,如果连这些原始数据都处理不好,后面那些高阶策略根本无从谈起。

4.1 Tick数据结构:时间、价格、成交量

先看最基础的Tick数据结构。美股交易所通常以微秒甚至纳秒级精度记录数据。我见过不少新手直接把Tick数据当1分钟K线用,这其实浪费了太多信息。

一个标准的逐笔成交Tick,通常包含以下字段:

字段 说明 示例
Timestamp 交易所时间戳(纳秒级) 2024-01-15 09:30:00.123456789
Price 成交价格(精确到美分) 185.23
Volume 成交量(股数) 100
Trade Condition 成交条件标记 @(常规)、F(非显示)
Exchange Code 交易所代码 N(NYSE)、Q(NASDAQ)

这里有个坑——不同数据商的时间戳精度不一样。我遇到过一家数据商给的是毫秒级,另一家是微秒级。对齐时如果不做精度统一,回测结果会差很多。

核心要点:Tick数据的时间戳精度直接影响订单簿重建的准确性。我个人习惯统一转为纳秒级处理,避免精度丢失。

4.2 逐笔成交与逐笔委托

很多人分不清逐笔成交(Trade)和逐笔委托(Quote/Order)的区别。我简单解释一下:

  • 逐笔成交:记录每一笔实际发生的交易。谁买了、谁卖了、多少钱、多少股。
  • 逐笔委托:记录每一笔订单的挂单、撤单、修改行为。包括限价单、市价单、冰山订单等。

为什么要区分?因为成交是「果」,委托是「因」。你想分析主力动向,只看成交数据是不够的。我曾经在分析某只中概股时,发现成交数据显示大单买入,但委托数据却显示有人在偷偷撤单。嗯,这就是典型的「挂单诱多」手法。

逐笔委托的数据结构更复杂一些:

// 逐笔委托示例(JSON格式)
{
  "timestamp": "2024-01-15 09:30:01.123456",
  "order_id": "ORD123456789",
  "side": "BUY",
  "price": 185.20,
  "size": 500,
  "order_type": "LIMIT",
  "action": "ADD",  // ADD, CANCEL, MODIFY
  "exchange": "NASDAQ"
}

实战技巧:如果你只有逐笔成交数据,可以尝试用「成交量分布」反推委托行为。但精度肯定不如直接拿逐笔委托数据。我建议有条件的话,两者都拿。

4.3 Level 1 / Level 2 / Level 3 数据区别

这个知识点是很多人的盲区。我直接画个图,一目了然:

Level 1 / Level 2 / Level 3 数据层级对比 Level 1 最佳买卖价 最新成交价 当日成交量 涨跌幅 --- 无深度信息 无委托明细 数据量:小 延迟:低 免费/基础版 Level 2 多档买卖盘口 逐笔成交明细 市场深度 交易所来源 --- 能看到10档报价 无逐笔委托 数据量:中 延迟:中 付费版 Level 3 逐笔委托全量 订单簿重建 冰山订单识别 撤单分析 --- 能看到所有委托 可还原订单簿 数据量:极大 延迟:高 机构版

简单总结一下:

  • Level 1:就是你在券商APP上看到的那种。只有最佳买卖价和最新成交价。说实话,做量化交易基本不够用。
  • Level 2:能看到多档盘口和逐笔成交。很多个人交易者觉得这就够了。但我想说,如果你只做趋势跟踪,Level 2确实够用。但要做高频或统计套利,还差得远。
  • Level 3:全量委托数据。能看到每一笔挂单、撤单、修改。这才是真正意义上的「市场微观结构」数据。我曾经用Level 3数据重建过某只股票的完整订单簿,那种掌控感是Level 2给不了的。

注意:Level 3数据不是所有券商都提供的。而且数据量极大,一只活跃股票一天可能产生上亿条委托记录。存储和计算成本都不低。我建议先评估你的策略需求,再决定是否上Level 3。

4.4 数据清洗与对齐

这部分是我踩坑最多的。数据清洗听起来简单,做起来全是细节。

常见问题一:时间戳对齐

不同交易所的时间戳基准不一样。NYSE用东部时间,NASDAQ用UTC。我遇到过最离谱的一次,某数据商把时间戳混用了,导致回测结果完全失真。

我的处理流程:

# 伪代码:时间戳统一处理
def align_timestamps(df):
    # 1. 统一转为UTC
    df['timestamp_utc'] = pd.to_datetime(df['timestamp'], utc=True)
    
    # 2. 对齐到微秒级
    df['timestamp_aligned'] = df['timestamp_utc'].dt.floor('us')
    
    # 3. 检查是否有重复时间戳
    dup_mask = df['timestamp_aligned'].duplicated(keep=False)
    if dup_mask.any():
        # 微调:按顺序加1纳秒
        df.loc[dup_mask, 'timestamp_aligned'] += pd.Timedelta(nanoseconds=1)
    
    return df

常见问题二:异常值处理

Tick数据里经常出现一些「幽灵数据」。比如价格突然跳到0,或者成交量是负数。我曾经在分析某只低价股时,发现一笔成交价是0.01美元,明显是数据错误。

我的清洗规则:

  • 价格必须在合理范围内(比如当日涨跌幅限制内)
  • 成交量必须大于0
  • 时间戳不能是未来时间
  • 交易所代码必须合法

常见问题三:数据对齐

当你同时有成交数据和委托数据时,对齐是个大问题。成交数据可能比委托数据晚几微秒到达。如果你直接按时间戳合并,会得到错误的结果。

我建议的做法是:

  1. 先按时间戳排序
  2. 用「最近邻」方式匹配成交和委托
  3. 设置一个时间窗口(比如100微秒),窗口内的数据视为同一事件

个人经验:数据清洗这一步,我建议至少花30%的项目时间。别急着跑策略,先把数据搞干净。我曾经因为一个时间戳对齐问题,浪费了整整两周的算力。嗯,从那以后我再也不敢跳过数据清洗了。

最后说一句,Tick级数据是微观结构分析的基石。你花在数据清洗上的每一分钟,都会在后续的策略开发中得到回报。别嫌麻烦,这是必经之路。


公众号:蓝海资料掘金营,微信deep3321