2、订单簿不平衡定义:OBI 的概念、计算公式、核心逻辑
好,我们直接进入正题。订单簿不平衡(Order Book Imbalance,简称 OBI),这个名字听起来有点唬人,但说白了,它就是一个非常直观的东西——衡量当前市场上,买单和卖单谁更强势。
我刚开始做量化的时候,总喜欢盯着盘口深度看,但看久了眼睛花。后来我发现,其实只需要一个数字,就能快速判断当前的多空力量对比。这个数字,就是 OBI。
2.1 什么是订单簿不平衡?
想象一下,你面前有一个大水池。左边是买家的钱,右边是卖家的货。如果左边水位高,说明买家更着急,价格容易涨;如果右边水位高,说明卖家更想出手,价格容易跌。
订单簿不平衡,就是量化这个「水位差」的指标。它计算的是买一档到买五档的总挂单量与卖一档到卖五档的总挂单量之间的差值比例。
核心逻辑:OBI 值越高,说明买方力量越强,价格向上突破的概率越大;OBI 值越低(负值),说明卖方力量越强,价格向下砸盘的概率越大。
嗯,这里要注意:OBI 不是预测未来价格的「水晶球」,它只是告诉你当前市场的短期供需失衡状态。我个人习惯把它当作一个「情绪温度计」——温度高了,可能过热;温度低了,可能过冷。
2.2 计算公式:别怕,很简单
公式其实就一行,我直接给你写出来:
OBI = (BidVolume - AskVolume) / (BidVolume + AskVolume)
其中:
- BidVolume = 买一到买五档的挂单总量
- AskVolume = 卖一到卖五档的挂单总量
这个公式的结果范围是 [-1, 1]:
- OBI = 1:全是买单,没有卖单(极端看多)
- OBI = -1:全是卖单,没有买单(极端看空)
- OBI = 0:买卖力量均衡(市场犹豫期)
我的小技巧:在实际项目中,我通常只取前五档深度。为什么?因为再往后的挂单量太稀疏,噪音太大,反而会干扰判断。你想想看,一个挂在买十档的 0.1 BTC 单子,能代表什么力量?
2.3 核心逻辑:为什么 OBI 有效?
你可能会问:为什么只看挂单量就能判断价格方向?
原因其实很简单:订单簿是市场最真实的「意愿池」。每一笔挂单,都是真金白银的承诺。买单多,说明有人愿意在这个价位接盘;卖单多,说明有人想在这个价位出货。
我曾经在实盘中踩过一个坑:只看 OBI 的绝对值,忽略了挂单的「厚度」。比如 OBI 是 0.8,看起来买方很强,但如果买一档只有 0.5 BTC,卖一档却有 100 BTC,那这个 0.8 其实很虚。所以后来我加了一个条件:必须同时检查前五档的总深度是否超过某个阈值。
避坑指南:我曾经因为 OBI 值突然从 -0.3 跳到 0.7 就追了进去,结果被瞬间打脸。后来复盘发现,那只是一个大户撤单再挂单造成的假象。记住:OBI 要结合成交量变化一起看,单看 OBI 容易被骗线。
2.4 知识体系结构图
下面我用一张 SVG 图,把 OBI 的核心逻辑串起来。你看完应该能一目了然:
2.5 实战中的 OBI 阈值参考
光知道公式还不够,你得知道什么数值该动手。我根据过去几年的回测经验,整理了一个参考表:
| OBI 范围 | 市场状态 | 我的操作建议 |
|---|---|---|
| 0.6 ~ 1.0 | 极度买方主导 | 可考虑追多,但需警惕回调 |
| 0.3 ~ 0.6 | 温和买方主导 | 适合顺势开多 |
| -0.3 ~ 0.3 | 均衡状态 | 观望,或等待突破信号 |
| -0.6 ~ -0.3 | 温和卖方主导 | 适合顺势开空 |
| -1.0 ~ -0.6 | 极度卖方主导 | 可考虑追空,但需警惕反弹 |
个人经验:我一般不会在 OBI 绝对值超过 0.8 时入场。为什么?因为太极端了,往往意味着行情已经走了大半,进去就是接盘侠。我更倾向于在 0.3~0.6 这个区间寻找机会,性价比最高。
2.6 代码实现:30 秒算出 OBI
最后,给你一个可以直接用的 Python 代码片段。假设你已经从交易所拿到了订单簿数据:
def calculate_obi(bids, asks, depth=5):
"""
计算订单簿不平衡值
:param bids: 买单列表,格式 [[price, volume], ...]
:param asks: 卖单列表,格式 [[price, volume], ...]
:param depth: 取前几档深度,默认5
:return: OBI 值 (-1 ~ 1)
"""
bid_volume = sum([b[1] for b in bids[:depth]])
ask_volume = sum([a[1] for a in asks[:depth]])
if bid_volume + ask_volume == 0:
return 0.0
obi = (bid_volume - ask_volume) / (bid_volume + ask_volume)
return round(obi, 4)
# 示例用法
bids = [[100.0, 1.5], [99.9, 2.0], [99.8, 1.2], [99.7, 0.8], [99.6, 0.5]]
asks = [[100.1, 1.0], [100.2, 1.8], [100.3, 0.9], [100.4, 0.6], [100.5, 0.3]]
obi = calculate_obi(bids, asks)
print(f"当前 OBI: {obi}") # 输出: 当前 OBI: 0.2195
这段代码我用了好几年,没出过问题。你直接复制到你的策略里,改一下数据源就能跑。