4、订单簿价格与数量分布:深度图(Depth Chart)的绘制
做市商这行,说白了就是跟订单簿打交道。你每天盯着那些跳动的数字,其实背后藏着一个核心问题:市场的流动性到底分布在哪些价位上?深度图就是回答这个问题的利器。
我记得刚入行那会儿,带我的老交易员指着屏幕说:「小子,别光看最新成交价,你得学会看深度图。那才是市场的真实面貌。」当时我还不理解,后来自己写策略踩了不少坑,才明白这句话的分量。
4.1 什么是深度图?
深度图,英文叫 Depth Chart。它把订单簿里的挂单数据,按照价格从低到高排列,然后累加每个价位的挂单数量。你想想看,这就像在价格轴上堆沙子——买盘从低往高堆,卖盘从高往低堆。
具体来说:
- 买盘(Bid):从当前最高买价往下累加,价格越低,累计量越大
- 卖盘(Ask):从当前最低卖价往上累加,价格越高,累计量越大
两条曲线在中间交汇,形成一个类似「V」字或「U」字的形状。这个形状的陡峭程度,直接反映了市场的深度和流动性。
核心概念:深度图的横轴是价格,纵轴是累计挂单数量。曲线越陡,说明该价位附近的流动性越集中;曲线越平缓,说明流动性分布越分散。
4.2 为什么要画深度图?
我个人的习惯是,每天开盘前先扫一眼深度图。为什么?因为它能告诉你三件事:
- 支撑位和阻力位在哪——买盘密集区就是潜在支撑,卖盘密集区就是潜在阻力
- 大单挂在哪——深度图上突然的「台阶」往往意味着有大户在埋伏
- 市场情绪如何——买盘深度远大于卖盘,说明买方意愿强;反之亦然
有一次我在做 BTC 的做市策略,发现深度图上 30000 这个价位附近突然堆了 500 个 BTC 的买单。我当时就觉得不对劲——这明显是有人在护盘。后来果然,价格跌到 30050 就开始反弹。嗯,这就是深度图的价值。
4.3 深度图的数学原理
说白了,深度图就是两个累加函数:
# 买盘累计深度
cum_bid[p] = sum(volume for all bids with price >= p)
# 卖盘累计深度
cum_ask[p] = sum(volume for all asks with price <= p)
这里要注意:买盘是从高价往低价累加,卖盘是从低价往高价累加。为什么?因为你想知道的是:如果价格跌到某个位置,还有多少买单在等着?如果价格涨到某个位置,还有多少卖单在压着?
小技巧:在实际绘制时,我通常会把价格精度控制在交易所的最小 tick size。比如 BTC/USDT 是 0.1 USDT,那就按 0.1 的粒度来采样。太细了图会毛刺太多,太粗了会丢失细节。
4.4 代码实现:从订单簿到深度图
下面是我常用的一个深度图绘制函数。它接受订单簿数据,返回可绘制的 x、y 坐标。
import numpy as np
import matplotlib.pyplot as plt
def compute_depth(orderbook, price_step=0.1):
"""
从订单簿计算深度曲线
orderbook: {'bids': [[price, vol], ...], 'asks': [[price, vol], ...]}
price_step: 价格采样步长
"""
bids = np.array(orderbook['bids'], dtype=float)
asks = np.array(orderbook['asks'], dtype=float)
# 确定价格范围
min_price = min(bids[:, 0].min(), asks[:, 0].min())
max_price = max(bids[:, 0].max(), asks[:, 0].max())
# 生成价格网格
prices = np.arange(min_price, max_price + price_step, price_step)
# 计算买盘累计深度
cum_bid = np.zeros_like(prices)
for i, p in enumerate(prices):
# 所有价格 >= p 的买单
mask = bids[:, 0] >= p
cum_bid[i] = bids[mask, 1].sum()
# 计算卖盘累计深度
cum_ask = np.zeros_like(prices)
for i, p in enumerate(prices):
# 所有价格 <= p 的卖单
mask = asks[:, 0] <= p
cum_ask[i] = asks[mask, 1].sum()
return prices, cum_bid, cum_ask
# 示例用法
orderbook = {
'bids': [[100.0, 10], [99.9, 20], [99.8, 15]],
'asks': [[100.1, 12], [100.2, 18], [100.3, 8]]
}
prices, cum_bid, cum_ask = compute_depth(orderbook, price_step=0.05)
注意:上面的实现是教学用的简化版。在实际生产环境中,订单簿可能有几万条数据,用循环遍历会非常慢。我建议用 numpy 的向量化操作或者 pandas 的 groupby 来加速。曾经我有个学生直接用循环处理 10 万条数据,结果程序卡了 3 分钟...
4.5 绘制深度图
有了数据,画图就简单了。我用 matplotlib 来展示:
def plot_depth_chart(prices, cum_bid, cum_ask, title='Depth Chart'):
plt.figure(figsize=(12, 6))
# 买盘用绿色,卖盘用红色
plt.plot(prices, cum_bid, color='green', linewidth=2, label='Bid Depth')
plt.plot(prices, cum_ask, color='red', linewidth=2, label='Ask Depth')
# 填充区域
plt.fill_between(prices, cum_bid, alpha=0.1, color='green')
plt.fill_between(prices, cum_ask, alpha=0.1, color='red')
# 标记当前价格
mid_price = (prices[len(prices)//2])
plt.axvline(x=mid_price, color='gray', linestyle='--', alpha=0.5)
plt.xlabel('Price')
plt.ylabel('Cumulative Volume')
plt.title(title)
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
画出来的图长这样:左边是绿色买盘曲线,从右往左逐渐上升;右边是红色卖盘曲线,从左往右逐渐上升。两条曲线在中间交汇,形成一个「V」形缺口。这个缺口的宽度,就是当前的买卖价差(spread)。
4.6 深度图的进阶用法
光画图还不够,你得会读图。我总结了几个实战中常用的指标:
| 指标 | 计算方法 | 含义 |
|---|---|---|
| 深度比 | 买盘总深度 / 卖盘总深度 | >1 表示买方力量强,<1 表示卖方力量强 |
| 价格弹性 | 价格变动 1% 对应的深度变化 | 弹性越大,说明市场越容易滑点 |
| 大单检测 | 深度曲线上的突变点 | 某个价位突然堆了大量挂单,可能是大户行为 |
| 深度斜率 | 深度曲线的一阶导数 | 斜率越大,该价位附近的流动性越集中 |
举个例子。我曾经在监控 ETH 的深度图时,发现卖盘深度在 2000 USDT 附近突然出现一个「台阶」——深度从 1000 ETH 瞬间跳到 5000 ETH。这说明有人在 2000 这个价位挂了 4000 ETH 的卖单。我当时判断这是个强阻力位,于是调整了我的做市策略,把卖单都挂在了 1995 以下。结果价格果然在 2000 附近反复试探但没突破。
4.7 深度图的知识体系
下面这张 SVG 图,是我自己梳理的深度图核心逻辑。你可以把它当作一个思维导图来看:
4.8 避坑指南
最后,分享几个我踩过的坑:
- 数据更新频率:订单簿是实时变化的,深度图也得跟着刷新。我建议至少每秒更新一次,否则你看到的可能是「过期」的深度。
- 价格精度问题:不同交易所的 tick size 不一样。比如 Binance 的 BTC 是 0.01,而某些小交易所可能是 0.1。采样步长一定要跟交易所保持一致。
- 深度图的「假象」:有些大户会挂单后马上撤单,制造深度很大的假象。我曾经就被这种「幽灵单」骗过,后来加了撤单检测逻辑才解决。
- 不要只看深度图:深度图反映的是当前挂单情况,不代表未来。你得结合成交量、盘口变动速度等指标一起看。
我的习惯:每天收盘后,我会把当天的深度图数据存下来,然后回放一遍。看看哪些关键价位被突破了,哪些价位形成了支撑。久而久之,你对市场的「感觉」会越来越准。
好了,深度图的内容就这些。记住一句话:深度图不是预测工具,而是描述工具。它告诉你市场现在是什么样子,至于未来会怎样,那是你结合其他信息去判断的事。
公众号:蓝海资料掘金营,微信deep3321