市场微观结构:订单簿深度、买卖价差、流动性分层与滑点计算
各位同学,今天我们来聊聊做市引擎最底层的那些事儿——市场微观结构。
说实话,我刚开始做量化那会儿,觉得策略就是找规律、写代码、跑回测。直到有一次实盘,我的做市单被市场瞬间吃掉,滑点直接吞掉了两周的利润。嗯,从那以后我才真正明白:不理解微观结构,做市就是闭着眼睛开车。
一、订单簿深度:市场的真实面貌
订单簿是什么?说白了,就是所有挂在交易所上的买单和卖单的集合。每一档价格上挂了多少钱,一目了然。
我个人习惯把订单簿分成三个区域来看:
- 近端流动性:距离当前价格最近的3-5档,这是做市商的主战场
- 中段流动性:5-20档,机构大单和套利者常在这里埋伏
- 远端流动性:20档以外,通常是止损单和长期限价单
你想想看,如果近端只有薄薄一层,中段突然变厚,这说明什么?说明有大户在等着接货或者砸盘。我在做BTC永续合约时遇到过好几次这种情况,每次都是行情反转的前兆。
二、买卖价差:做市商的利润来源
买卖价差(Bid-Ask Spread),就是买一价和卖一价之间的差值。做市商赚的就是这个差价。
但这里有个坑——名义价差和实际价差是两码事。
名义价差就是买一卖一的价格差。但实际交易中,你挂单不一定能立刻成交,中间可能隔着好几档。我建议用加权平均价差来评估真实成本:
def weighted_spread(order_book, depth=5):
"""
计算加权平均价差
order_book: 订单簿数据,包含bids和asks
depth: 考虑几档深度
"""
bids = order_book['bids'][:depth]
asks = order_book['asks'][:depth]
bid_volume = sum([b[1] for b in bids])
ask_volume = sum([a[1] for a in asks])
bid_price = sum([b[0]*b[1] for b in bids]) / bid_volume
ask_price = sum([a[0]*a[1] for a in asks]) / ask_volume
return ask_price - bid_price
这段代码我用了好几年,简单但实用。它告诉你:如果你想吃掉前5档的所有流动性,实际要付出的价差是多少。
三、流动性分层:谁在跟你做对手盘?
流动性不是均匀分布的。我把它分成三个层次:
| 层次 | 特征 | 典型参与者 |
|---|---|---|
| 第一层 | 高频做市商,挂单薄、撤单快 | 量化基金、专业做市商 |
| 第二层 | 中频交易者,挂单较厚、停留时间长 | 套利者、趋势交易者 |
| 第三层 | 低频大单,隐藏在远端 | 机构投资者、矿工 |
为什么会分层?因为不同参与者的交易目标和时间尺度不一样。高频做市商可能几秒钟就撤单,而机构的大单可能挂一整天。
四、滑点计算:从理论到实战
滑点,就是预期成交价和实际成交价之间的差值。做市策略最怕的就是滑点,因为它直接吃掉你的利润。
滑点主要来自三个方面:
- 市场冲击:你的单子太大,吃掉了多档流动性
- 延迟:从下单到成交,价格已经变了
- 对手盘行为:有人在你前面抢单
我常用的滑点计算模型是这样的:
def slippage_estimate(order_book, trade_volume):
"""
估算给定交易量的滑点
order_book: 订单簿
trade_volume: 交易量(正数为买入,负数为卖出)
"""
if trade_volume > 0:
# 买入,从asks侧吃单
levels = order_book['asks']
side = 'asks'
else:
# 卖出,从bids侧吃单
levels = order_book['bids']
side = 'bids'
remaining = abs(trade_volume)
total_cost = 0
executed_volume = 0
for price, volume in levels:
if remaining <= 0:
break
take = min(remaining, volume)
total_cost += take * price
executed_volume += take
remaining -= take
if executed_volume < abs(trade_volume):
# 流动性不足,用最后一档价格估算剩余部分
total_cost += remaining * levels[-1][0]
executed_volume += remaining
avg_price = total_cost / executed_volume
mid_price = (order_book['bids'][0][0] + order_book['asks'][0][0]) / 2
slippage = abs(avg_price - mid_price) / mid_price * 10000 # 返回bp
return slippage
五、知识体系总览
下面这张图是我自己整理的,把本章的核心逻辑串起来了:
这张图我画了好几次才满意。你看,四个要素是相互关联的:订单簿深度影响价差,流动性分层决定滑点大小,而滑点又反过来影响你做市的报价策略。
好了,这一章的内容就到这里。记住一句话:微观结构不是理论,是你每天都要面对的现实。下次实盘前,先跑一遍滑点计算代码,看看你的策略到底能承受多大的交易量。
公众号:蓝海资料掘金营,微信deep3321