订单流特征工程:从原始数据到交易信号

做暗池交易这些年,我越来越觉得——订单流才是真正的"金矿"。价格可以骗人,成交量可以注水,但订单流里的微观结构,很难伪装。今天我就带你拆解订单流特征工程的五个核心模块。

核心观点:订单流特征不是越多越好,而是要找到那些能反映"交易对手真实意图"的指标。我见过太多人堆了上百个特征,结果过拟合得一塌糊涂。

1. 订单到达率建模

说白了,订单到达率就是"单位时间内来了多少订单"。但这里有个坑——暗池里的订单到达往往呈现"突发性"特征,不是均匀分布的。

我个人习惯用泊松过程做基础建模,但实际数据往往有"过分散"现象。这时候我会改用负二项分布来拟合。

import numpy as np
from scipy import stats

# 假设我们有一分钟的订单到达计数
arrival_counts = np.array([12, 8, 15, 3, 22, 9, 11, 7, 18, 5])

# 泊松拟合
mu = np.mean(arrival_counts)
print(f"泊松参数 λ = {mu:.2f}")

# 负二项拟合(处理过分散)
n, p = stats.nbinom.fit(arrival_counts)
print(f"负二项参数 n={n:.2f}, p={p:.2f}")

实战经验:我在处理某交易所的暗池数据时发现,开盘后15分钟和收盘前15分钟的到达率会飙升3-5倍。如果你用全天平均参数去建模,那基本等于在"刻舟求剑"。

2. 订单大小分布分析

订单大小分布,说白了就是"大单多还是小单多"。暗池里的大单往往藏着机构投资者的真实意图。

我一般把订单分成三类:

  • 小单(< 500股):散户或算法拆单的碎片
  • 中单(500-5000股):可能是机构的部分成交
  • 大单(> 5000股):大概率是机构在"扫货"或"砸盘"

这里有个技巧——看订单大小的偏度。如果偏度突然变大,说明有大资金在进场。

import pandas as pd

# 假设order_sizes是订单大小序列
order_sizes = pd.Series([100, 200, 5000, 300, 10000, 150, 8000, 400])

skewness = order_sizes.skew()
print(f"订单大小偏度: {skewness:.2f}")

# 如果偏度 > 2,警惕大单异常
if skewness > 2:
    print("⚠️ 检测到大单异常,可能有大资金在活动")

避坑指南:我曾经犯过一个错误——直接用原始订单大小做特征。后来发现,不同股票的"大单"标准完全不同。茅台的一手和工商银行的一手,能一样吗?建议先做市值标准化

3. 订单时间间隔分析

订单时间间隔,反映的是"交易者的耐心程度"。你想想看,如果一个人每隔0.1秒就下一个单,那大概率是算法在跑。如果间隔突然拉长,可能是人在手动操作。

我常用的指标有两个:

指标 含义 异常信号
平均间隔 订单到达的平均时间差 突然缩短 → 算法交易活跃
间隔变异系数 间隔的波动程度 突然增大 → 可能有"钓鱼单"
import numpy as np

# 计算时间间隔
timestamps = np.array([0.0, 0.3, 0.8, 1.2, 2.0, 2.1, 3.5])
intervals = np.diff(timestamps)

mean_interval = np.mean(intervals)
cv_interval = np.std(intervals) / mean_interval

print(f"平均间隔: {mean_interval:.3f}秒")
print(f"间隔变异系数: {cv_interval:.3f}")

4. 订单方向预测特征

预测订单方向(买还是卖),是暗池交易的核心问题。我常用的特征包括:

  • 买卖压力差:最近N笔订单中买单占比 - 卖单占比
  • 价格动量:过去5笔成交的价格变化方向
  • 订单簿不平衡:买一卖一的挂单量差异

嗯,这里要注意——暗池里没有公开的订单簿,所以"订单簿不平衡"这个特征需要从成交数据里反推。我一般用Tick数据来近似估计。

# 假设我们有最近10笔订单的方向(1=买,-1=卖)
directions = [1, -1, 1, 1, -1, -1, 1, 1, -1, 1]

# 计算买卖压力差
buy_ratio = sum(1 for d in directions if d == 1) / len(directions)
sell_ratio = 1 - buy_ratio
pressure = buy_ratio - sell_ratio

print(f"买卖压力差: {pressure:.2f}")
# 正值表示买方主导,负值表示卖方主导

5. 订单流毒性指标:VPIN 和 PIN

这两个指标,是判断"对手是不是在割你韭菜"的核心工具。

PIN(Probability of Informed Trading):衡量知情交易的概率。值越高,说明你越可能在和"知道内幕的人"做对手盘。

VPIN(Volume-synchronized PIN):PIN的改进版,按成交量分桶计算。我个人更爱用VPIN,因为它对市场微观结构的变化更敏感。

# VPIN的简化计算逻辑
def calculate_vpin(trades, bucket_size=1000):
    """
    trades: 每笔交易的方向和成交量
    bucket_size: 每个桶的成交量阈值
    """
    vpin_values = []
    current_volume = 0
    buy_volume = 0
    sell_volume = 0
    
    for trade in trades:
        direction, volume = trade
        current_volume += volume
        
        if direction == 1:
            buy_volume += volume
        else:
            sell_volume += volume
        
        if current_volume >= bucket_size:
            # 计算该桶的VPIN
            vpin = abs(buy_volume - sell_volume) / current_volume
            vpin_values.append(vpin)
            
            # 重置
            current_volume = 0
            buy_volume = 0
            sell_volume = 0
    
    return np.mean(vpin_values)

# 示例数据
trades = [(1, 200), (-1, 300), (1, 500), (-1, 100), (1, 400)]
vpin = calculate_vpin(trades, bucket_size=1000)
print(f"VPIN值: {vpin:.3f}")

实战阈值参考:

  • VPIN < 0.3:正常市场,毒性较低
  • VPIN 0.3 - 0.6:警惕,可能有知情交易
  • VPIN > 0.6:高度毒性,建议暂停交易

我的经验:VPIN不是万能的。有一次我在某个小市值股票上看到VPIN飙到0.8,吓得我赶紧平仓。结果发现是某个大户在拆单交易,根本不是知情交易。所以,VPIN要结合成交量一起看——如果成交量很小,VPIN高可能是噪音。

知识体系总览

下面这张图,是我做订单流特征工程时的核心框架。你可以把它当作"作战地图"来用。

订单流特征工程知识体系 原始订单流数据 订单到达率建模 订单大小分布分析 订单时间间隔分析 订单方向预测特征 订单流毒性指标(VPIN/PIN) 交易信号 & 风险预警 五个模块相互独立,但输出信号需要综合判断 建议:先做到达率和大小分布,再做毒性指标

这五个模块,每个都能单独写一篇文章。但实战中,我建议你先跑通到达率建模和大小分布分析——这两个是基础,数据也最容易获取。等跑通了,再上VPIN这些高阶指标。

记住一句话:特征工程不是堆砌,而是理解市场微观结构后的精炼表达。你做得越深,越能感受到订单流里那些"看不见的手"在怎么运作。

专注资料整理