第四章 市场微观结构:订单簿深度、买卖价差、交易量分布、信息不对称模型
做市算法设计,说白了就是在跟市场微观结构打交道。你想想看,我们每天面对的订单簿、价差、成交量,这些不是冷冰冰的数字,而是市场参与者的博弈痕迹。我个人习惯把微观结构比作市场的「心电图」——读懂它,你才能知道市场是健康跳动还是即将骤停。
4.1 订单簿深度:市场的「承重墙」
订单簿深度,就是挂在各个价位上的买卖单子总量。我在项目中遇到过最典型的场景:某个信用衍生品看起来流动性不错,但一拆开订单簿,发现深度全集中在头两层,第三层往后直接断崖式下跌。这种结构非常脆弱,一个大单就能把价格打穿。
做市算法里,我通常用深度斜率来衡量订单簿的健康度:
def depth_slope(order_book, levels=5):
"""
计算订单簿深度斜率
斜率越陡,说明深度集中在浅层,风险越大
"""
prices = []
volumes = []
for i in range(levels):
bid = order_book['bids'][i]
ask = order_book['asks'][i]
prices.append((bid[0] + ask[0]) / 2)
volumes.append(bid[1] + ask[1])
# 用线性回归算斜率
slope = np.polyfit(range(levels), volumes, 1)[0]
return slope
嗯,这里要注意:斜率绝对值越小,说明深度分布越均匀,市场越有「韧性」。我曾经用这个指标躲过一次闪崩——当时斜率突然从-0.3掉到-1.2,我果断把做市报价撤了,三分钟后市场暴跌。
核心要点:订单簿深度不是看总量,而是看分布形态。均匀分布 > 金字塔分布 > 悬崖分布。
4.2 买卖价差:做市商的「饭碗」
买卖价差就是你的利润空间,但也是你的风险敞口。我刚开始做信用衍生品做市时,总想赚大价差,结果被高频玩家反复收割。后来我学乖了——价差不是越大越好,而是越「合理」越好。
一个经典的价差模型是:
spread = 2 * (inventory_cost + adverse_selection_cost + order_processing_cost)
其中,逆向选择成本是最难估算的。我个人习惯用价差分解法来实时估算:
def spread_decomposition(trade_data, window=100):
"""
用交易数据分解价差成分
返回:逆向选择成本占比
"""
# 计算有效价差
effective_spread = abs(trade_data['price'] - trade_data['mid_price']) * 2
# 计算实现价差(考虑价格冲击后的实际收益)
realized_spread = effective_spread.shift(-1) * np.sign(trade_data['price'] - trade_data['mid_price'])
# 逆向选择 = 有效价差 - 实现价差
adverse_selection = effective_spread - realized_spread
return adverse_selection.mean() / effective_spread.mean()
实战技巧:当逆向选择成本占比超过40%时,说明市场里有大量知情交易者在跟你对赌。这时候应该扩大价差,或者干脆暂停做市。
4.3 交易量分布:藏在数据里的「指纹」
交易量分布不是简单的统计,它反映了市场参与者的行为模式。我做过一个有意思的分析:把信用衍生品的交易量按小时切片,发现上午10点和下午3点有两个明显的峰值——这不是巧合,而是机构投资者的调仓窗口。
做市算法里,我常用交易量轮廓来动态调整报价策略:
class VolumeProfile:
def __init__(self, lookback_days=20):
self.profile = {} # 每个时间段的平均交易量
self.lookback = lookback_days
def update(self, trades):
for trade in trades:
time_bucket = trade['timestamp'].hour * 4 + trade['timestamp'].minute // 15
if time_bucket not in self.profile:
self.profile[time_bucket] = []
self.profile[time_bucket].append(trade['volume'])
def get_volume_ratio(self, current_time):
"""返回当前时间段的交易量占比"""
bucket = current_time.hour * 4 + current_time.minute // 15
if bucket not in self.profile:
return 1.0
avg = np.mean(self.profile[bucket])
total_avg = np.mean([np.mean(v) for v in self.profile.values()])
return avg / total_avg
为什么这个重要?因为交易量分布直接决定了你的库存风险。在低交易量时段,你的订单可能挂半天都成交不了,这时候应该缩小报价规模,而不是傻等。
避坑指南:我曾经在交易量分布上吃过亏——以为某个时段交易量小就放松了监控,结果一个大户突然进场,把我的库存全部吃掉。后来我加了一个「异常交易量检测」模块,当实际交易量超过历史均值3个标准差时,自动切换为防御模式。
4.4 信息不对称模型:跟「聪明钱」博弈
信息不对称是做市商最大的敌人。市场里总有比你更了解标的物真实价值的人——可能是内部人士,可能是研究更深入的机构。你需要一个模型来识别他们。
我最常用的模型是PIN(Probability of Informed Trading)模型。它把订单流分为知情交易和不知情交易,然后估算知情交易的概率:
def estimate_pin(order_flow, buy_orders, sell_orders):
"""
估算知情交易概率
基于Easley et al. (1996) 的PIN模型
"""
# 简化版:用买卖订单的不平衡度来近似
imbalance = abs(buy_orders - sell_orders) / (buy_orders + sell_orders)
# 用EWMA平滑
alpha = 0.1
pin = alpha * imbalance + (1 - alpha) * prev_pin
return pin
嗯,这个简化版虽然不够精确,但在实战中够用了。我一般设定一个阈值:当PIN超过0.6时,说明市场里有明显的知情交易者,这时候我会:
- 缩小报价规模,减少暴露
- 扩大价差,补偿逆向选择风险
- 降低报价更新频率,避免被「钓鱼」
核心洞察:信息不对称不是静态的。在财报发布前、重大事件发生时,PIN会急剧上升。做市算法需要能感知这种变化,而不是用同一套参数跑全天。
4.5 知识体系总览
下面这张图是我自己梳理的市场微观结构知识框架,做市算法的每个模块都能在这里找到对应位置:
这张图把四个核心维度串起来了。你想想看,订单簿深度告诉你市场能「扛」多少,价差告诉你利润空间,交易量分布告诉你什么时候该出手,信息不对称模型告诉你谁在跟你玩。四个维度缺一不可。
我的建议:刚开始做信用衍生品做市时,别急着上复杂模型。先把订单簿深度和价差这两个基础指标跑通,跑三个月积累数据,再慢慢加入交易量分布和信息不对称模型。一步一个脚印,比什么都重要。
公众号:蓝海资料掘金营,微信deep3321