2. Tick数据结构解析:Level1/Level2行情Tick字段详解

高频交易与风控系统的基石是Tick数据。不同交易所、不同数据等级(Level1/Level2)的Tick结构存在显著差异。本章将逐字段拆解Tick数据包,明确每个字段在坏账率监控中的实际用途。

2.1 Level1 vs Level2 行情核心差异

对比维度 Level1(基础行情) Level2(深度行情)
数据频率 通常3秒或1秒快照 逐笔成交 + 逐笔委托,毫秒级推送
盘口深度 仅最优买卖5档(买一~买五,卖一~卖五) 全量委托队列(50档/100档/全档位)
成交量信息 累计成交量 + 单笔成交量 逐笔成交明细(每笔成交价、量、方向)
时间戳精度 秒级或百毫秒级 微秒级或纳秒级(交易所撮合时间)
坏账监控价值 可发现分钟级异常 可发现秒级/毫秒级异常,精准定位坏账
实战建议:坏账率监控必须依赖Level2数据。Level1的快照频率不足以捕捉闪电崩盘、虚假流动性、对倒交易等高频坏账行为。

2.2 Tick核心字段详解

一个标准的Level2 Tick数据包通常包含以下字段组。每个字段在坏账率计算中都有明确的角色。

2.2.1 时间戳字段

  • Exchange Timestamp(交易所时间戳):撮合引擎生成时间,精度微秒/纳秒。用于计算订单延迟、成交间隔、流动性突变时间点。
  • Received Timestamp(接收时间戳):本地网关收到数据的时间。用于评估网络延迟、数据乱序、重复包。
  • Sequence Number(序列号):交易所或网关分配的递增序号。用于检测丢包、乱序、重复推送。
坏账风险点:如果交易所时间戳与接收时间戳偏差超过阈值(如>100ms),可能表明数据经过缓存或重路由,该Tick的成交价/量不可信,应标记为“时间戳坏账”。

2.2.2 价格字段

  • Last Price(最新成交价):最后一笔成交价格。用于计算实时价差、价格突变。
  • Bid Price[1..N](买盘价格):各档位买入价格。Level2可提供全档位。
  • Ask Price[1..N](卖盘价格):各档位卖出价格。
  • Open / High / Low / Close(开盘/最高/最低/收盘):用于计算日内价格区间,辅助判断价格是否异常。

2.2.3 成交量与持仓量字段

  • Volume(累计成交量):当日累计成交合约/股数。用于计算换手率、成交量突变。
  • Turnover(成交额):当日累计成交金额。
  • Open Interest(持仓量):期货/期权未平仓合约数。持仓量异常增减常伴随对倒或逼仓。
  • Bid Volume[1..N] / Ask Volume[1..N](各档位委托量):Level2核心字段,用于计算订单簿不平衡、虚假挂单。

2.2.4 买卖盘口(Order Book)字段

  • Bid/Ask Queue(委托队列):每个价格档位上的委托单明细(部分交易所提供)。用于识别大单撤单、冰山订单。
  • Trade Direction(成交方向):主动买/主动卖标记。用于计算资金流向、识别对倒。
  • Trade Flag(成交标记):是否为FOK(Fill or Kill)、FAK(Fill and Kill)等特殊订单。特殊订单占比过高可能暗示操纵。

2.3 Tick数据结构示意图

下图展示了一个标准Level2 Tick数据包在内存中的字段布局,以及各字段在坏账率监控中的角色映射。

Level2 Tick 数据包字段结构 & 坏账监控映射 时间戳组 Exchange Timestamp (μs) Received Timestamp (μs) Sequence Number → 检测延迟、乱序、丢包 → 时间戳坏账标记 价格组 Last Price Bid Price[1..N] Ask Price[1..N] → 价格突变、价差异常 → 价格坏账标记 成交量组 Volume / Turnover Open Interest Bid/Ask Volume[1..N] → 成交量突变、虚假挂单 → 流动性坏账标记 盘口组 Bid/Ask Queue Trade Direction Trade Flag → 对倒、冰山订单、撤单 → 操纵行为坏账标记 坏账聚合判定引擎 输入:时间戳组 + 价格组 + 成交量组 + 盘口组 输出:坏账标记(BadTickFlag) + 坏账类型(BadType) 坏账类型枚举:TIME_BAD / PRICE_BAD / VOL_BAD / ORDER_BOOK_BAD 坏账率 = 坏账Tick数 / 总Tick数 × 100%

2.4 Tick数据坏账率计算流程

基于上述字段,坏账率监控的典型处理流程如下:

  1. 数据接入:接收Level2 Tick流,解析各字段到结构化对象。
  2. 字段校验:检查时间戳单调性、价格非负、成交量非负、序列号连续性。
  3. 坏账判定:对每个Tick,根据预设规则(如价格超过前收盘±10%、成交量突增100倍、时间戳间隔>500ms)标记坏账。
  4. 坏账聚合:按时间窗口(1分钟/5分钟/1小时)统计坏账Tick数,计算坏账率。
  5. 告警输出:当坏账率超过阈值(如>0.1%)时,触发风控告警。
关键指标:坏账率 = (坏账Tick数量 / 总Tick数量) × 100%。Level2数据下,正常市场坏账率应低于0.01%;超过0.1%需立即排查数据源或市场异常。

2.5 常见坏账场景与对应字段

坏账场景 涉及字段 判定逻辑示例
时间戳回退 Exchange Timestamp, Sequence Number 当前时间戳 < 前一条时间戳,或序列号不连续
价格零值或负值 Last Price, Bid/Ask Price 价格 ≤ 0
成交量异常暴增 Volume, Bid/Ask Volume 单Tick成交量 > 前N个Tick均值 × 阈值
盘口倒挂 Bid Price, Ask Price 买一价 > 卖一价(正常市场不可能)
虚假挂单后撤单 Bid/Ask Queue, Sequence Number 大单出现后快速撤单,且无成交

2.6 代码示例:Tick字段解析与坏账标记

以下Python代码演示如何解析一个简化的Level2 Tick字典,并执行基础坏账判定。

import time
from typing import Dict, List

class TickValidator:
    """Tick数据坏账校验器"""
    
    def __init__(self, price_threshold: float = 0.1, vol_multiplier: float = 100.0):
        self.last_timestamp = 0
        self.last_seq = 0
        self.price_threshold = price_threshold  # 价格变动阈值(比例)
        self.vol_multiplier = vol_multiplier    # 成交量暴增倍数
        self.volume_history: List[float] = []
    
    def validate_tick(self, tick: Dict) -> Dict:
        """
        校验单个Tick,返回坏账标记和类型
        :param tick: 包含字段的字典
        :return: {'is_bad': bool, 'bad_type': str, 'reason': str}
        """
        result = {'is_bad': False, 'bad_type': '', 'reason': ''}
        
        # 1. 时间戳校验
        ts = tick.get('exchange_timestamp', 0)
        seq = tick.get('seq_num', 0)
        if ts < self.last_timestamp:
            result['is_bad'] = True
            result['bad_type'] = 'TIME_BAD'
            result['reason'] = '时间戳回退'
            return result
        if seq <= self.last_seq:
            result['is_bad'] = True
            result['bad_type'] = 'TIME_BAD'
            result['reason'] = '序列号不递增'
            return result
        self.last_timestamp = ts
        self.last_seq = seq
        
        # 2. 价格校验
        price = tick.get('last_price', 0)
        if price <= 0:
            result['is_bad'] = True
            result['bad_type'] = 'PRICE_BAD'
            result['reason'] = '价格非正'
            return result
        
        # 3. 成交量校验
        volume = tick.get('volume', 0)
        if volume > 0 and len(self.volume_history) >= 10:
            avg_vol = sum(self.volume_history[-10:]) / 10
            if volume > avg_vol * self.vol_multiplier:
                result['is_bad'] = True
                result['bad_type'] = 'VOL_BAD'
                result['reason'] = f'成交量暴增: {volume} vs 均值 {avg_vol:.2f}'
                return result
        self.volume_history.append(volume)
        
        # 4. 盘口校验
        bid = tick.get('bid_price_1', 0)
        ask = tick.get('ask_price_1', 0)
        if bid > 0 and ask > 0 and bid > ask:
            result['is_bad'] = True
            result['bad_type'] = 'ORDER_BOOK_BAD'
            result['reason'] = '盘口倒挂'
            return result
        
        return result

# 使用示例
validator = TickValidator()
sample_tick = {
    'exchange_timestamp': int(time.time() * 1_000_000),
    'seq_num': 1001,
    'last_price': 5000.0,
    'volume': 10,
    'bid_price_1': 4999.5,
    'ask_price_1': 5000.5
}
result = validator.validate_tick(sample_tick)
print(f"坏账标记: {result['is_bad']}, 类型: {result['bad_type']}, 原因: {result['reason']}")
生产环境注意:实际Level2数据流每秒可达数千笔,校验逻辑必须使用C++或高性能Python(如Cython、Numba)实现,避免在Python层逐笔同步校验导致延迟堆积。

2.7 本章小结

  • Level2 Tick数据包含时间戳、价格、成交量、盘口四大字段组,每个组都对应特定的坏账风险。
  • 坏账率监控的核心是逐字段校验 + 聚合统计,Level2的细粒度数据让秒级异常无处遁形。
  • 时间戳回退、价格异常、成交量暴增、盘口倒挂是最常见的四种坏账类型。
  • 代码实现时需注意性能,高频场景下校验逻辑必须接近零开销。