3、订单簿特征提取:买卖价差(Spread)、市场深度(Depth)、订单簿不平衡(Order Book Imbalance)

做市的核心,说白了就是跟订单簿打交道。

你每天盯着盘口,看到的那些跳动的数字,其实藏着很多信息。我个人习惯,拿到一个订单簿数据,先不看价格,先看三个东西:价差、深度、不平衡。这三个特征,基本能告诉我当前市场的「脾气」。

3.1 买卖价差(Spread)—— 市场的「呼吸」

价差,就是卖一价减去买一价。听起来简单,但这里面门道不少。

为什么价差重要?

价差直接反映了市场的流动性成本。价差越小,说明买卖双方越「和气」,你进出场的成本就越低。价差突然拉大,往往意味着有大事要发生,或者流动性 provider 在撤退。

核心公式:

Spread = Ask_Price_1 - Bid_Price_1

相对价差 = Spread / Mid_Price

我在项目中遇到过一个问题:只看绝对价差,有时候会误判。比如一个100块的股票,价差0.01,看起来很窄;但一个1块的股票,价差0.01,其实已经很宽了。所以,我建议你同时关注相对价差。

实战小技巧:

我个人习惯用「加权平均价差」—— 把卖一到卖五的价差按挂单量加权。这样能更真实地反映你实际成交的成本。

3.2 市场深度(Depth)—— 市场的「厚度」

深度,就是订单簿上各个价位的挂单量。它告诉你:如果你想砸一笔大单,市场能接住多少。

深度怎么量化?

我一般看两个维度:

  • 档位深度: 比如买一、买二、买三的挂单量
  • 累计深度: 从买一到买N的累计挂单量

举个例子,假设我们想看看买盘前5档的深度:

def calculate_depth(order_book, levels=5, side='bid'):
    """
    计算指定方向的累计深度
    :param order_book: 订单簿数据,格式为 [(price, volume), ...]
    :param levels: 考虑的档位数
    :param side: 'bid' 或 'ask'
    """
    total_volume = 0
    for i in range(min(levels, len(order_book))):
        price, volume = order_book[i]
        total_volume += volume
    return total_volume

# 使用示例
bid_depth = calculate_depth(bid_orders, levels=5, side='bid')
ask_depth = calculate_depth(ask_orders, levels=5, side='ask')
print(f"买盘前5档深度: {bid_depth}")
print(f"卖盘前5档深度: {ask_depth}")

嗯,这里要注意:深度不是越大越好。深度太大,说明市场可能处于「僵持」状态,价格不容易突破。深度突然变浅,往往是变盘的信号。

避坑指南:

我曾经犯过一个错误:只看深度绝对值,忽略了深度变化的速度。有一次,一个品种的深度在10秒内从1000手缩到100手,我还在按原来的策略做市,结果被一波流直接打穿。后来我加了一个「深度衰减率」指标,专门监控深度的变化速度。

3.3 订单簿不平衡(Order Book Imbalance)—— 市场的「情绪」

不平衡,说白了就是买盘和卖盘谁更强。这个指标,我个人觉得是做市策略里最有「灵魂」的一个。

计算公式:

def order_book_imbalance(bid_volume, ask_volume):
    """
    计算订单簿不平衡度
    返回值范围:[-1, 1]
    正值表示买盘强,负值表示卖盘强
    """
    if bid_volume + ask_volume == 0:
        return 0
    return (bid_volume - ask_volume) / (bid_volume + ask_volume)

# 示例
bid_depth = 1500  # 买盘总深度
ask_depth = 800   # 卖盘总深度
imbalance = order_book_imbalance(bid_depth, ask_depth)
print(f"订单簿不平衡度: {imbalance:.3f}")  # 输出: 0.304

你想想看,当 imbalance 接近 1 时,说明买盘远远强于卖盘,价格大概率要涨。但这里有个陷阱:

为什么不能只看 imbalance?

因为大户会「挂假单」。我曾经见过一个场景:某品种的 imbalance 一直维持在 0.8 以上,看起来买盘很强。但那些买单都是「冰山订单」,真正能成交的只有表面那一点点。结果价格一涨,那些买单全撤了,变成了卖单。

我的改进方案:

用「加权不平衡度」—— 给近档的挂单更高的权重,远档的挂单更低的权重。这样能减少远端假单的干扰。

def weighted_imbalance(bid_orders, ask_orders, decay=0.9):
    """
    加权订单簿不平衡度
    :param bid_orders: 买单列表 [(price, volume), ...]
    :param ask_orders: 卖单列表 [(price, volume), ...]
    :param decay: 衰减系数,越远档权重越低
    """
    weighted_bid = 0
    weighted_ask = 0
    
    for i, (price, volume) in enumerate(bid_orders):
        weighted_bid += volume * (decay ** i)
    
    for i, (price, volume) in enumerate(ask_orders):
        weighted_ask += volume * (decay ** i)
    
    if weighted_bid + weighted_ask == 0:
        return 0
    return (weighted_bid - weighted_ask) / (weighted_bid + weighted_ask)

# 使用示例
bid_orders = [(100.0, 100), (99.9, 200), (99.8, 150)]
ask_orders = [(100.1, 80), (100.2, 120), (100.3, 90)]
w_imbalance = weighted_imbalance(bid_orders, ask_orders, decay=0.8)
print(f"加权不平衡度: {w_imbalance:.3f}")

3.4 三个特征的综合运用

单独看一个指标,很容易被误导。我习惯把这三个特征放在一起看:

场景 价差 深度 不平衡 市场含义
正常交易 适中 接近0 流动性好,适合做市
大单进场 突然变宽 一侧变深 偏向一侧 可能有机构在操作
流动性危机 极宽 极浅 剧烈波动 赶紧撤单,别玩了
假突破 先窄后宽 远端挂单多 突然反转 可能是陷阱,别追

说白了,这三个特征就是做市商的「三原色」。你把这三种颜色调好了,就能画出市场的真实面貌。

我的个人经验:

我一般会在策略里设置一个「特征监控面板」,实时显示这三个指标的变化曲线。当三个指标同时出现异常时,我会手动干预策略。比如,价差突然扩大 + 深度骤减 + 不平衡剧烈波动,这通常意味着市场要出大事,我会暂停所有做市活动,先观察再说。

最后,送你一张我总结的知识结构图,帮你理清这三个特征的关系:

订单簿特征 买卖价差 (Spread) 市场深度 (Depth) 订单簿不平衡 (OBI) 衡量流动性成本 窄 → 流动性好 宽 → 可能有异常 衡量市场承载力 深 → 能接大单 浅 → 容易滑点 衡量买卖力量对比 正 → 买盘强 负 → 卖盘强 三者结合使用效果最佳 价差判断成本,深度判断容量,不平衡判断方向

这三个特征,你吃透了,做市策略的底层逻辑就通了。剩下的,就是怎么把这些特征用到你的策略里去。


专注资料整理