订单簿模拟:订单簿数据结构、盘口深度模拟、订单簿更新逻辑、流动性模型
做市商策略的核心战场,就是订单簿。你想想看,我们所有的报价、撤单、吃单,最终都要反映在订单簿上。如果回测框架里的订单簿模拟不够真实,那策略表现再好也是空中楼阁。今天我们就来聊聊,怎么把这个核心模块做扎实。
订单簿数据结构:别小看这个基础
我个人习惯用价格优先、时间优先的原则来组织订单簿。说白了,买单价格高的排前面,卖单价格低的排前面;价格一样,先来的排前面。
数据结构上,我推荐用红黑树或者跳表来实现。为什么?因为订单簿需要频繁的插入、删除和查询操作,这些数据结构能在 O(log n) 时间内搞定。我在项目中遇到过用数组硬扛的,结果回测到一半内存爆了,订单量一上来直接卡死。
一个典型的订单簿结构长这样:
class OrderBook:
def __init__(self):
self.bids = SortedDict() # 买单,键为价格,值为订单列表
self.asks = SortedDict() # 卖单,键为价格,值为订单列表
self.order_map = {} # 订单ID到订单对象的映射
def add_order(self, order):
# 根据订单方向插入到 bids 或 asks
pass
def cancel_order(self, order_id):
# 从订单簿中移除指定订单
pass
def match_order(self, order):
# 尝试与对手盘成交
pass
盘口深度模拟:让订单簿活起来
盘口深度,就是订单簿上每个价格档位的挂单量。模拟盘口深度时,不能简单用均匀分布。真实市场的深度分布是有规律的——越靠近中间价,流动性越集中。
我常用的方法是指数衰减模型:
def simulate_depth(mid_price, spread, depth_levels=10):
depths = {}
for i in range(1, depth_levels + 1):
price = mid_price + i * spread / 2 # 卖盘
volume = base_volume * math.exp(-i * decay_factor)
depths[price] = volume
price = mid_price - i * spread / 2 # 买盘
volume = base_volume * math.exp(-i * decay_factor)
depths[price] = volume
return depths
嗯,这里要注意:decay_factor 这个参数很关键。我做过统计,BTC/USDT 的衰减因子大概在 0.3-0.5 之间,而一些山寨币可能只有 0.1-0.2。说白了,流动性越差的币,深度衰减得越慢。
订单簿更新逻辑:事件驱动的艺术
订单簿不是静态的,它每时每刻都在变化。更新逻辑主要处理三类事件:
- 新增订单:插入到对应价格档位
- 撤销订单:从订单簿中移除
- 成交订单:减少对应档位的挂单量,如果量归零则删除该档位
我曾经踩过一个坑:回测时把订单簿更新和策略决策放在同一个时间步里。结果策略看到的价格和实际成交价格总是差那么一点点。后来我改成先更新订单簿,再让策略做决策,问题就解决了。
流动性模型:从微观到宏观
流动性模型决定了订单簿的「生命力」。我把它分为三个层次:
| 层次 | 描述 | 实现方式 |
|---|---|---|
| 基础流动性 | 由做市商和散户提供的稳定挂单 | 泊松过程生成订单到达 |
| 事件驱动流动性 | 新闻、大单引发的流动性变化 | 事件触发 + 临时深度调整 |
| 自适应流动性 | 根据市场波动率动态调整 | 波动率越高,深度越薄 |
我个人最常用的是混合模型。基础流动性用泊松过程模拟,然后叠加事件驱动层。举个例子,当一个大买单进来时,我会临时增加卖盘深度,模拟做市商趁机出货的行为。
def update_liquidity(order_book, event):
if event.type == 'large_buy':
# 模拟做市商反应:增加卖盘深度
for i in range(1, 5):
price = order_book.asks[i].price
order_book.asks[i].volume *= 1.2
elif event.type == 'volatility_spike':
# 波动率飙升时,整体深度缩减
for level in order_book.asks:
level.volume *= 0.8
for level in order_book.bids:
level.volume *= 0.8
知识体系总览
下面这张图,是我对订单簿模拟整个知识体系的梳理。你可以把它当作一个检查清单,看看自己还有哪些地方没做到位。
这张图把订单簿模拟的四个核心模块串起来了。你从数据结构出发,逐步构建盘口深度,然后通过更新逻辑让订单簿动起来,最后用流动性模型赋予它「生命力」。每一步都环环相扣,缺一不可。