订单流特征工程:从原始数据到交易信号
做暗池交易这些年,我越来越觉得——订单流才是真正的"金矿"。价格可以骗人,成交量可以注水,但订单流里的微观结构,很难伪装。今天我就带你拆解订单流特征工程的五个核心模块。
核心观点:订单流特征不是越多越好,而是要找到那些能反映"交易对手真实意图"的指标。我见过太多人堆了上百个特征,结果过拟合得一塌糊涂。
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这些高阶指标。
记住一句话:特征工程不是堆砌,而是理解市场微观结构后的精炼表达。你做得越深,越能感受到订单流里那些"看不见的手"在怎么运作。