订单簿深度解析:限价订单簿(LOB)结构、买卖盘口与价差、订单簿动态变化、订单簿数据获取

做量化交易这些年,我越来越觉得——订单簿就是市场的X光片。你想想看,K线图告诉你价格去了哪,但订单簿告诉你价格为什么去了那。今天咱们就把订单簿这层窗户纸捅破。

一、限价订单簿(LOB)的核心结构

限价订单簿,说白了就是一个价格-数量的二维排队系统。买方挂单在左边排队,卖方挂单在右边排队,中间就是成交价。

我个人习惯把LOB想象成一个多层停车场

  • 买盘(Bid):从高到低排列,最高价在最上面
  • 卖盘(Ask):从低到高排列,最低价在最上面
  • 价差(Spread):最高买价和最低卖价之间的空隙

来看一个典型的BTC/USDT订单簿快照:

卖盘(Ask):
价格      数量      累计
10005.0   0.5 BTC   2.3 BTC
10004.5   1.0 BTC   1.8 BTC
10004.0   0.8 BTC   0.8 BTC
-------------------------------
价差 = 10004.0 - 10003.5 = 0.5 USDT
-------------------------------
买盘(Bid):
10003.5   1.2 BTC   1.2 BTC
10003.0   0.6 BTC   1.8 BTC
10002.5   0.4 BTC   2.2 BTC

这里有个细节——价格档位。交易所通常按最小价格变动单位(tick size)来划分档位。比如BTC的tick size是0.5 USDT,那价格就是10000.0、10000.5、10001.0这样跳。

关键点:订单簿的深度不是看单笔挂单,而是看累计深度。比如你想买2个BTC,看卖一档只有0.8个,那你就得吃掉卖一到卖三档,成交均价会更高。

二、买卖盘口与价差——市场的呼吸

盘口数据里,我最关注三个指标:

  1. 买卖盘口(Bid-Ask):最高买价和最低卖价,这是市场的"门面"
  2. 价差(Spread):买卖价差,流动性越好的品种价差越小
  3. 盘口深度(Depth):各档位的挂单量,决定了你能吃多少货

价差这东西,我踩过坑。有一次做ETH的套利,看到价差只有0.01 USDT,觉得流动性很好。结果一进去发现——价差是假的。为什么?因为卖一档只有0.1个ETH,买一档也只有0.1个,真正的流动性在第三档以后。所以我现在看价差,一定会同时看盘口前五档的累计深度

实战技巧:真正的流动性指标是加权价差。比如你想交易1个BTC,计算吃掉1个BTC所需的平均价格与当前买一价的差值,这才是你实际要付出的成本。

三、订单簿的动态变化——市场在说话

订单簿不是静止的,它每毫秒都在变。我总结了几种常见的变化模式:

变化类型 表现 含义
价差收窄 买一上移,卖一下移 多空博弈激烈,即将变盘
深度堆积 某一价格档位挂单突然增多 可能是大资金在"筑墙"
冰山订单 小单吃掉后,同价位又出现新单 大资金在隐藏真实意图
撤单潮 大量挂单同时消失 市场情绪突变,小心闪崩

我曾经遇到过一个经典场景:某山寨币的买一档突然出现一个超级大单,价格比当前买一高了2%。很多人以为是利好,跟着追涨。结果呢?那是庄家在挂单诱多,等散户把价格推上去,他瞬间撤单反手做空。嗯,这就是为什么我总说——别只看挂单,要看挂单的持续性

避坑指南:我曾经因为没注意冰山订单,在ETH上吃了大亏。当时看到卖一档只有0.5个ETH,觉得可以轻松吃掉。结果连续吃了5次,每次吃完又冒出0.5个,最后发现是同一个地址在反复挂单。从那以后,我写代码时一定会检测同价位重复挂单的模式。

四、订单簿数据获取——从理论到实战

数据获取这块,我建议分两步走:

  1. WebSocket实时流:用于做高频策略
  2. REST API快照:用于做历史回测

以币安为例,获取订单簿数据的代码长这样:

import requests
import json

# 获取订单簿快照
def get_orderbook(symbol='BTCUSDT', limit=100):
    url = f'https://api.binance.com/api/v3/depth'
    params = {
        'symbol': symbol,
        'limit': limit  # 可选5/10/20/50/100/500/1000
    }
    resp = requests.get(url, params=params)
    data = resp.json()
    
    # 解析数据
    bids = data['bids']  # 买盘 [价格, 数量]
    asks = data['asks']  # 卖盘 [价格, 数量]
    
    # 计算价差
    best_bid = float(bids[0][0])
    best_ask = float(asks[0][0])
    spread = best_ask - best_bid
    
    return {
        'bids': bids[:5],  # 前五档
        'asks': asks[:5],
        'spread': spread,
        'mid_price': (best_bid + best_ask) / 2
    }

# 使用示例
orderbook = get_orderbook('BTCUSDT', 10)
print(f"买一: {orderbook['bids'][0]}")
print(f"卖一: {orderbook['asks'][0]}")
print(f"价差: {orderbook['spread']}")

这里有个坑——数据延迟。REST API的订单簿快照通常有100-500ms的延迟,做高频策略根本不够用。我个人的做法是:

  • 用WebSocket维持一个本地订单簿
  • 每收到一个增量更新(增删改),就更新本地数据
  • 每隔30秒用REST API做一次全量校验

为什么这么做?因为WebSocket偶尔会丢包,导致本地订单簿和交易所不一致。全量校验就是用来纠偏的。

核心要点:订单簿数据是微结构套利的原材料。数据质量直接决定策略成败。我建议你至少缓存前20档的订单簿数据,因为很多套利机会藏在深度里,而不是表面。

五、订单簿知识体系总览

下面这张图是我自己梳理的订单簿知识框架,你可以把它当作学习路线图:

订单簿深度解析知识体系 限价订单簿(LOB) 买卖盘口与价差 动态变化 核心要素 • 价格档位(tick size) • 挂单队列(FIFO/Pro-rata) • 累计深度 关键指标 • 买卖盘口(Bid-Ask) • 价差(Spread) • 加权价差 变化模式 • 价差收窄/扩大 • 深度堆积/撤单 • 冰山订单识别 数据获取:WebSocket + REST API 实战应用:微结构套利策略 知识体系总览:从结构到数据,从理论到实战

这张图把订单簿的知识分成了四个层次:结构 → 指标 → 变化 → 数据。我个人建议你按照这个顺序来学习,每一步都动手写代码验证一下。

学习建议:别只看理论。打开交易所的WebSocket,订阅一个交易对的订单簿数据,盯着屏幕看10分钟。你会发现——市场比你想象的更有规律。那些大单的进出、价差的收窄、深度的变化,都在告诉你下一步该怎么走。

好了,订单簿这块就聊到这。记住一句话:订单簿是市场的底层语言。读懂了它,你就能听懂市场在说什么。


公众号:蓝海数据掘金营,微信deep3321