2. Tick数据基础

在进入乱序、重复与延迟处理之前,必须先建立对Tick数据本身的准确认知。很多数据质量问题的根源,并不是处理算法不够复杂,而是对Tick的字段语义、时间戳来源和传输链路缺乏清晰理解。本节从定义、数据结构、时间戳类型、数据源与协议四个层面,为后续实战打下基础。

一、Tick的定义与本质

Tick是市场行情的最小可观测事件单元,通常表示一次成交、一次委托簿变更或一次快照推送。它不等同于“每秒一条”或“固定频率数据”,而是由市场事件驱动、时间间隔不均匀的离散记录。理解这一点非常关键:Tick的到达节奏本身带有信息,间隔的疏密、突发与静默都可能反映流动性变化。

从数据工程视角看,Tick是一条带有时间标记的状态变更消息。它至少包含:标的标识、事件类型、价格、数量、方向以及时间信息。不同市场、不同数据源对字段的定义存在差异,但核心语义相对稳定。

核心认知:Tick是事件流,不是时间序列采样点。它的顺序、重复与延迟问题,本质上来自“事件发生时间”与“事件被记录/接收时间”之间的偏差。

二、Tick的典型数据结构

以常见的逐笔成交为例,一条Tick通常包含以下字段:

字段含义典型类型注意事项
symbol标的代码string需统一交易所后缀
exchange_time交易所撮合时间int64/纳秒权威事件时间
local_time本地接收时间int64/纳秒受本机时钟影响
price成交价decimal避免浮点误差
volume成交量int单位需确认
side买卖方向enum部分源用主动方标识
seq序列号int64判断乱序与丢包的关键

实际落地时,建议在原始字段之外增加采集时间、来源标识和入库时间,形成可追溯的数据血缘。下面是一个简化的Tick结构定义:

struct Tick {
    string  symbol;
    int64   exchange_time_ns;   // 交易所时间
    int64   local_time_ns;      // 本地接收时间
    int64   collect_time_ns;    // 采集落盘时间
    double  price;
    int64   volume;
    int8    side;               // 1买 -1卖 0未知
    int64   seq;                // 交易所序列号
    string  source;             // 数据源标识
}

三、三类时间戳:交易所时间、本地时间、采集时间

时间戳是Tick处理中最容易出错、也最值得深入理解的部分。同一笔成交在链路上会留下多个时间标记,它们语义不同,不能混用。

  • 交易所时间:由交易所撮合系统在事件发生时打上,是判断事件真实顺序的权威依据。它通常精度高、单调递增,但可能因交易所侧批量推送而出现同一时间戳多条记录。
  • 本地时间:行情网关或客户端收到消息时打的本地时钟时间。它反映“我什么时候看到”,受本机NTP同步质量影响,可能出现回拨或漂移。
  • 采集时间:数据被写入采集队列或落盘时记录的时间。它包含排队、序列化、批处理等内部延迟,适合做链路监控,不适合作为事件排序依据。

实践建议:排序优先使用交易所时间加序列号;本地时间用于延迟统计;采集时间用于排查内部处理瓶颈。三者混用会导致乱序判断失真。

四、常见数据源与传输协议

不同数据源的Tick在完整性、延迟和字段丰富度上差异明显。常见来源包括交易所直连行情、券商柜台转发、第三方数据商以及历史归档文件。传输协议方面,低延迟场景多用UDP组播,可靠场景多用TCP或专有二进制协议,历史回放则常见CSV、Parquet等格式。

# 典型组播接收配置示例
group=239.1.1.1
port=30001
protocol=UDP
buffer_size=8MB
reconnect=false

UDP组播延迟低但可能丢包和乱序,TCP可靠但存在队头阻塞。选择协议时,需要结合业务对延迟与完整性的容忍度。无论哪种协议,都应在入库前保留原始报文或原始字段,便于后续复盘。

五、案例与常见误区

某团队在回测中发现策略收益异常偏高,排查后确认是Tick按本地时间排序,而本地时钟曾发生回拨,导致部分成交被错误地排到未来。改为按交易所时间加序列号排序后,收益回归正常。这个案例说明:时间戳选择直接决定数据顺序,进而影响策略逻辑。

常见误区:把本地时间当作事件时间;忽略序列号导致无法识别丢包;认为同一时间戳一定重复;直接用采集时间做延迟评估却不校准时钟。

Tick数据链路与三类时间戳 交易所撮合 事件发生 打交易所时间 行情网关 接收报文 打本地时间 采集队列 排队与批处理 打采集时间 存储与处理 排序/去重 延迟统计 时间轴上的三类时间戳 交易所时间 事件真实发生 本地时间 网关收到 采集时间 落盘入库 网络传输延迟 内部处理延迟

总结来看,Tick数据基础决定了后续所有处理逻辑的边界。明确字段语义、区分三类时间戳、理解数据源与协议特性,才能在面对乱序、重复与延迟时做出正确判断,而不是依赖经验猜测。