21、订单流与高频交易:Tick级订单流数据的处理与策略

说实话,很多做订单流的朋友都问过我一个问题:Tick级数据到底有什么用?

我个人的看法是,如果你只做日线级别的交易,那Tick数据确实有点大材小用。但如果你想把订单流做到极致,想捕捉那些机构资金在毫秒级别内的动作——那Tick级数据就是你的显微镜。

这一章,我们就来聊聊Tick级订单流数据的处理,以及怎么用它构建高频策略。

什么是Tick级数据?

先明确一个概念。Tick数据,就是每一笔成交的记录。每一笔交易,无论大小,都会生成一条Tick。

举个例子,某只股票在10:00:00.123这个时间点成交了100股,价格是50.01元。这就是一条Tick。

而订单流数据,是在Tick数据的基础上,进一步拆解了买卖方向。也就是我们常说的「逐笔成交」数据。

核心区别:

  • Tick数据:记录每一笔成交的价格、数量、时间
  • 订单流数据:在Tick基础上,标记每一笔是主动买还是主动卖

说白了,Tick数据告诉你「发生了什么」,订单流数据告诉你「谁在推动价格」。

Tick级数据的处理难点

我在项目中遇到过最头疼的问题,就是数据量太大。

一只活跃的股票,一天能产生几十万条Tick。如果是期货或者加密货币,这个数字能到几百万。你想想看,如果同时监控几十个品种,数据量直接爆炸。

处理Tick数据,有几个绕不开的坎:

  1. 时间对齐:不同交易所的时间戳精度不一样,有的精确到毫秒,有的精确到微秒
  2. 数据清洗:经常会有重复数据、错误数据、延迟数据
  3. 存储压力:一天的数据可能就几个G,长期存储是个大问题
  4. 计算效率:在Tick级别做计算,普通循环根本跑不动

避坑指南:我曾经因为没处理好时间对齐,导致策略在回测时表现完美,实盘却一塌糊涂。后来才发现,是不同数据源的时间戳差了2毫秒。2毫秒,在高频交易里就是天壤之别。

Tick级订单流的处理流程

我一般把处理流程分成三步:

第一步:数据清洗与标准化

原始数据拿过来,先做三件事:

  • 去重:删除完全相同的重复Tick
  • 排序:按时间戳严格排序
  • 标记方向:根据成交价格与买卖盘口的对比,标记主动买/主动卖
import pandas as pd
import numpy as np

def clean_tick_data(df):
    """
    清洗Tick级订单流数据
    """
    # 去重
    df = df.drop_duplicates(subset=['timestamp', 'price', 'volume'])
    
    # 排序
    df = df.sort_values('timestamp').reset_index(drop=True)
    
    # 标记买卖方向
    # 假设我们有买卖盘口数据
    df['side'] = np.where(df['price'] >= df['ask_price'], 'buy',
                          np.where(df['price'] <= df['bid_price'], 'sell', 'mid'))
    
    return df

第二步:聚合与降采样

原始Tick数据太密了,直接分析会疯掉。我习惯把它聚合到更粗的时间粒度上。

常用的聚合方式:

聚合粒度 适用场景 数据量
1秒 高频策略、做市 中等
100毫秒 超高频策略 较大
10毫秒 极高频、套利 非常大
def aggregate_tick(df, freq='1S'):
    """
    将Tick数据聚合到指定频率
    """
    # 按时间分组
    grouped = df.groupby(pd.Grouper(key='timestamp', freq=freq))
    
    # 计算聚合指标
    result = grouped.agg({
        'price': ['first', 'last', 'max', 'min', 'mean'],
        'volume': 'sum',
        'side': lambda x: (x == 'buy').sum()  # 主动买次数
    })
    
    return result

第三步:特征工程

聚合完之后,就可以提取特征了。我常用的Tick级特征有:

  • 买卖压力比:主动买成交量 / 主动卖成交量
  • Tick成交量分布:大单占比、小单占比
  • 价格冲击系数:每单位成交量引起的价格变化
  • 订单流不平衡度:买卖订单的净差值

个人经验:买卖压力比这个指标,我用了好几年。当这个比值突然飙升到3以上,同时价格还在低位,那大概率是机构在吃货。这时候跟着进场,胜率很高。

基于Tick级订单流的高频策略

策略这块,我分享一个我自己实盘跑过的思路。

核心逻辑很简单:捕捉大单的痕迹

机构资金进场,不可能悄无声息。他们会在Tick级数据上留下痕迹——比如连续几笔大额主动买单,或者买卖盘口的快速变化。

策略框架

class TickOrderFlowStrategy:
    def __init__(self, window=100, threshold=2.5):
        self.window = window  # 观察窗口
        self.threshold = threshold  # 触发阈值
    
    def on_tick(self, tick):
        # 更新订单流数据
        self.update_orderflow(tick)
        
        # 计算买卖压力比
        pressure_ratio = self.calc_pressure_ratio()
        
        # 判断是否触发信号
        if pressure_ratio > self.threshold:
            # 检查价格位置
            if self.is_at_support():
                return 'buy'
        
        return None
    
    def calc_pressure_ratio(self):
        """计算最近window笔Tick的买卖压力比"""
        recent_ticks = self.ticks[-self.window:]
        buy_vol = sum(t['volume'] for t in recent_ticks if t['side'] == 'buy')
        sell_vol = sum(t['volume'] for t in recent_ticks if t['side'] == 'sell')
        
        if sell_vol == 0:
            return float('inf')
        return buy_vol / sell_vol

策略的注意事项

嗯,这里要注意几个点:

  • 滑点控制:高频策略对滑点极其敏感,0.1个tick的滑点就能吃掉所有利润
  • 延迟问题:从数据接收到策略执行,延迟必须控制在毫秒级
  • 容量限制:Tick级策略通常容量有限,别想着用大资金去跑

血的教训:我曾经写过一个Tick级策略,回测年化收益200%。结果实盘第一天就亏了5%。后来排查发现,是回测时没考虑交易所的撮合延迟。真实市场里,你的订单根本抢不到那个价格。

知识体系总览

下面这张图,是我对Tick级订单流处理与策略的总结:

Tick级订单流处理与策略知识体系 原始Tick数据 逐笔成交数据 买卖盘口数据 数据处理流程 数据清洗 时间对齐 聚合降采样 特征提取 核心特征指标 买卖压力比 成交量分布 价格冲击系数 订单流不平衡度 高频策略:大单痕迹捕捉 + 买卖压力比阈值触发 数据来源 → 数据处理 → 特征提取 → 策略执行

写在最后

Tick级订单流处理,说白了就是跟时间赛跑。数据量大、计算复杂、延迟敏感,每一个环节都可能成为瓶颈。

但我个人觉得,这恰恰是它的魅力所在。当你真正掌握了Tick级数据的处理能力,你会发现市场在你面前变得透明了——那些大资金的动向,就像黑夜里的萤火虫一样明显。

当然,这条路不好走。我见过太多人,数据还没处理好就急着上策略,结果亏得一塌糊涂。我的建议是:先把数据处理这关过了,再谈策略。

无相订单流研究社 微信Lucian808555