高频交易数据与流动性特征

各位同学,今天我们来聊聊债券交易中最底层、也最刺激的东西——高频数据。

说实话,我刚入行那会儿,觉得债券交易就是看看收益率曲线,听听宏观消息。直到有一次,我在做日内策略回测时,发现模型在上午10点和下午3点的表现天差地别。这才意识到,流动性在一天之内是活的,不是死的

这一章,我们就来拆解Tick级数据、逐笔成交与委托、日内流动性模式,以及那些让人头疼的数据清洗问题。

Tick级数据结构:最细颗粒度的战场

什么是Tick级数据?说白了,就是每一笔成交或每一次报价变动,都记录下来的数据。在债券市场,尤其是国债期货和活跃券,Tick数据能精确到毫秒甚至微秒。

我习惯把Tick数据分成两类:

  • 成交Tick:每一笔实际成交的价格、数量、时间
  • 报价Tick:买卖盘口的每一次变动,包括最优买卖价和深度

一个典型的成交Tick长这样:

时间戳          价格    数量    方向
2024-01-15 09:30:01.123  102.35  1000    B
2024-01-15 09:30:01.456  102.36  500     S
2024-01-15 09:30:02.001  102.35  2000    B

注意那个时间戳,精度到毫秒。为什么这么重要?因为在高频世界里,谁先看到数据,谁就赢了一半

核心要点:Tick数据是流动性的“心电图”。每一笔成交都在告诉你,当前市场是愿意买还是愿意卖,愿意以什么价格成交多少量。

逐笔成交与逐笔委托:看穿市场的“底牌”

逐笔成交数据,就是上面说的成交Tick。但逐笔委托数据,是更高级的东西——它告诉你谁在挂单,挂了多少,什么时候撤单

举个例子。假设你看到逐笔成交显示:

  • 09:30:01 成交1000手,价格102.35
  • 09:30:02 成交2000手,价格102.35

光看这个,你可能觉得“嗯,有人在买”。但如果你同时看逐笔委托:

  • 09:30:00 买方挂单5000手,价格102.35
  • 09:30:01 吃掉1000手,还剩4000手
  • 09:30:02 又吃掉2000手,还剩2000手

这时候你就能判断:这个买方是真心想买,不是虚晃一枪。我曾经在交易中吃过亏,只看成交不看委托,结果被大单诱多给骗了。

我的经验:逐笔委托数据能帮你识别“虚假流动性”。有些做市商会在盘口挂大单,但一有人吃就撤单。这种“幽灵单”在Tick数据里根本看不出来,只有逐笔委托才能暴露。

日内流动性模式:U型曲线

这是债券交易员必须刻在脑子里的东西。

什么叫U型曲线?就是流动性在开盘和收盘时最好,中午最差。画出来像个字母U。

为什么会这样?

  • 开盘:隔夜信息集中释放,交易员们急着调整仓位
  • 中午:大家都在吃饭、休息,交易量骤降
  • 收盘:机构要平头寸、做估值,交易再次活跃

我做过一个统计,在活跃国债期货上,开盘后30分钟和收盘前30分钟的交易量,占了全天的40%以上。中间那两小时,买卖价差能扩大一倍。

下面这张图,是我用真实数据画的日内流动性模式:

债券日内流动性模式(U型曲线) 流动性 9:30 10:30 11:30 14:00 15:00 开盘高峰 午间低谷 收盘高峰

注意:U型曲线不是一成不变的。在数据发布日、央行议息日,流动性模式会被彻底打乱。我曾经在非农数据公布那天,看到中午流动性突然飙升——因为大家都在等数据。

事件驱动下的流动性突变

说到事件驱动,这是高频交易里最刺激的部分。

流动性突变,通常发生在以下几种情况:

  • 宏观数据发布:CPI、GDP、PMI,数据一出,流动性瞬间消失或暴增
  • 央行操作:降息、降准、公开市场操作,市场情绪瞬间逆转
  • 突发事件:黑天鹅事件,比如疫情、战争、违约

我记得有一次,某只信用债突然传出违约消息。前一秒还挂着的买盘,后一秒全撤了。买卖价差从2个bp直接跳到50个bp。如果你还在用之前的流动性模型做交易,那真是要亏到姥姥家。

怎么应对?我的做法是:在事件窗口期,降低交易频率,或者干脆暂停。等流动性恢复稳定了再进场。

数据清洗与预处理实战

好了,前面讲了这么多理论,现在来点实际的。高频数据清洗,是每个量化交易员的必修课。

我见过太多人,模型建得漂漂亮亮,结果数据一进去就崩了。为什么?因为原始数据太脏了

常见的坑有:

问题类型 具体表现 我的处理方法
时间戳错乱 后一笔成交的时间戳比前一笔还早 按时间排序,删除异常点
价格异常 成交价偏离市场均价超过3个标准差 用中位数过滤,或者直接剔除
重复数据 同一笔成交被记录两次 按时间+价格+数量去重
缺失数据 某段时间内完全没有成交 用前一笔报价填充,或者标记为缺失

下面是我常用的一个清洗流程,用Python写的:

import pandas as pd
import numpy as np

def clean_tick_data(df):
    """
    清洗Tick级成交数据
    """
    # 1. 排序
    df = df.sort_values('timestamp')
    
    # 2. 去重
    df = df.drop_duplicates(subset=['timestamp', 'price', 'volume'])
    
    # 3. 过滤价格异常
    mean_price = df['price'].median()
    std_price = df['price'].std()
    df = df[(df['price'] > mean_price - 3*std_price) & 
            (df['price'] < mean_price + 3*std_price)]
    
    # 4. 填充缺失时间戳(可选)
    df = df.set_index('timestamp')
    df = df.resample('1S').ffill()  # 按秒填充
    
    return df

避坑指南:我曾经在清洗数据时,直接用均值填充缺失值,结果把流动性低谷期的数据全给抹平了。后来改用前向填充,才保留了真实的流动性特征。记住:不要用统计量去填充高频数据,要用市场行为去填充

最后说一句,数据清洗不是一次性的工作。每次拿到新数据,我都会先跑一遍可视化,看看有没有明显的异常。比如价格跳空、成交量突变,这些在图表上一眼就能看出来。

好了,这一章的内容就到这里。Tick数据、逐笔委托、U型曲线、事件驱动、数据清洗——这些是高频交易的基础,也是你理解债券流动性的起点。下一章,我们会深入讨论如何用这些数据构建交易信号。


专注资料整理