3. 做市策略设计原理:库存管理、报价宽度、报价更新频率、最优报价策略
做市策略的核心,说白了就是回答三个问题:报什么价?报多少量?什么时候更新?
这三个问题背后,藏着四个关键设计维度——库存管理、报价宽度、报价更新频率、最优报价策略。我做了几年量化做市,踩过不少坑,今天就把这些经验掰开揉碎讲给你听。
3.1 库存管理:做市商的命门
库存管理,是做市策略的基石。你想想看,做市商本质上就是个「中间商」,赚的是买卖价差。但中间商最怕什么?怕货砸手里。
我刚开始做市时,有一次在ETH上挂了大量买单,结果行情突然跳水,库存瞬间变成负值——也就是我手里全是高价买的货,卖不出去。那次教训让我明白:库存管理不是「要不要持仓」,而是「持多少、持多久」。
3.1.1 库存目标与偏离惩罚
每个做市策略都应该有一个「目标库存水平」。通常设为0,也就是中性库存。但实际中,你可以根据市场观点调整这个目标。
偏离目标库存时,策略需要惩罚报价。怎么惩罚?我习惯用这个公式:
# 库存偏离惩罚系数
inventory_penalty = -gamma * (current_inventory - target_inventory)
# 调整后的报价
adjusted_bid = mid_price + spread/2 + inventory_penalty
adjusted_ask = mid_price - spread/2 + inventory_penalty
这里的 gamma 是库存厌恶系数。值越大,库存偏离时报价调整越激进。
关键点:库存惩罚不是对称的。手里货多时,要压低卖价、抬高买价,鼓励卖出、抑制买入。反之亦然。
3.1.2 库存再平衡策略
当库存偏离到一定程度,光靠报价调整可能不够。这时候需要主动再平衡。
我常用的三种方式:
- 激进报价:在偏离方向加大报价偏移,加速库存回归
- 对冲交易:在相关品种上做反向操作(比如BTC和ETH联动)
- 暂停做市:极端情况下,直接撤单,等市场恢复再说
我的经验:别等到库存爆了才动手。设置一个「警戒线」,比如偏离超过目标库存的20%就开始激进调整。我曾经吃过亏,等到偏离50%才动手,结果滑点大得吓人。
3.2 报价宽度:赚多少 vs 成交概率
报价宽度,就是买卖价差。这个参数直接决定了你的盈利能力和成交概率。
价差太宽,赚得多但成交少;价差太窄,成交多但赚得少。这是个典型的权衡问题。
3.2.1 动态价差模型
固定价差是新手做法。真正有效的策略,应该根据市场状态动态调整价差。
我常用的模型:
# 动态价差计算
base_spread = 2 * (tick_size + alpha * volatility)
# 波动率调整
volatility = std(returns, window=20) * sqrt(365)
# 最终价差
dynamic_spread = base_spread * (1 + beta * order_imbalance)
其中:
tick_size:最小价格变动单位alpha:波动率敏感系数(我一般设0.5-1.5)beta:订单簿不平衡调整系数
注意:波动率越高,价差应该越宽。但别调得太激进,否则你会被高频交易者「剥头皮」。我见过有人把alpha设到3,结果价差宽到根本没人成交。
3.2.2 价差与库存的联动
价差不是独立参数,它和库存管理是联动的。库存偏离大时,不仅要调整报价位置,还要调整价差宽度。
| 库存状态 | 价差调整 | 原因 |
|---|---|---|
| 中性库存 | 正常价差 | 正常赚取买卖价差 |
| 多头偏离 | 收窄卖价、放宽买价 | 鼓励卖出、抑制买入 |
| 空头偏离 | 收窄买价、放宽卖价 | 鼓励买入、抑制卖出 |
| 极端偏离 | 单边报价 | 只挂库存回归方向的单 |
3.3 报价更新频率:快 vs 稳
报价更新频率,决定了你的策略对市场变化的响应速度。
频率太高,容易产生大量撤单费(交易所收的);频率太低,报价可能过时,被市场「吃掉」。
3.3.1 事件驱动 vs 时间驱动
我习惯用事件驱动的方式更新报价:
- 成交事件:我的单子被吃了,立即更新
- 订单簿变化:最佳买卖价变化超过阈值,更新
- 市场波动:波动率突变,更新
- 定时更新:兜底策略,比如每500ms强制更新一次
# 伪代码:事件驱动的报价更新
def on_market_event(event):
if event.type == 'TRADE' and event.price in [my_bid, my_ask]:
update_quotes() # 我的单被吃了,立即更新
elif event.type == 'ORDERBOOK_CHANGE':
if abs(event.new_best_bid - last_best_bid) > threshold:
update_quotes() # 市场变了,更新
elif event.type == 'TIMER':
if time_since_last_update > 500: # ms
update_quotes() # 兜底更新
避坑指南:我曾经把更新频率设到10ms一次,结果一天下来撤单费比盈利还高。后来改成事件驱动+500ms兜底,效果好了很多。记住:不是越快越好,是「该快的时候快,该稳的时候稳」。
3.4 最优报价策略:把上面三个串起来
库存管理、报价宽度、更新频率,这三个东西不是孤立的。最优报价策略,就是把它们整合成一个有机整体。
3.4.1 核心框架
我用的框架是这样的:
class OptimalMarketMaker:
def __init__(self, gamma, alpha, beta, target_inventory=0):
self.gamma = gamma # 库存厌恶系数
self.alpha = alpha # 波动率敏感系数
self.beta = beta # 订单簿不平衡系数
self.target = target_inventory
def calculate_quotes(self, market_state):
# 1. 计算基础价差
vol = self._estimate_volatility(market_state)
base_spread = 2 * (market_state.tick_size + self.alpha * vol)
# 2. 库存调整
inventory_deviation = market_state.my_inventory - self.target
inventory_penalty = -self.gamma * inventory_deviation
# 3. 订单簿不平衡调整
imbalance = market_state.bid_volume - market_state.ask_volume
spread_adjustment = self.beta * imbalance
# 4. 最终报价
spread = base_spread * (1 + spread_adjustment)
mid = market_state.mid_price + inventory_penalty
bid = mid - spread / 2
ask = mid + spread / 2
return bid, ask
3.4.2 参数优化
这些参数(gamma、alpha、beta)怎么设?我建议用历史数据做回测优化。
优化目标通常是:夏普比率或收益/风险比。别只看总收益,风险控制才是做市商的长久之道。
我的经验:参数优化时,记得做「稳健性检验」。也就是在多个市场周期上测试同一组参数。我见过有人在一个月的数据上优化出完美参数,换到另一个月就亏成狗。说白了,就是过拟合了。
3.5 知识体系总览
下面这张图,把做市策略设计的核心逻辑串起来了:
嗯,到这里,做市策略设计的四个核心维度就讲完了。库存管理是「方向盘」,报价宽度是「油门」,更新频率是「变速箱」,最优报价策略就是那个「老司机」——把三者协调好,才能稳稳地赚钱。
最后一句:别想着一次就把参数调完美。做市是个动态博弈的过程,市场在变,你的策略也得跟着变。多回测、多复盘,慢慢就能找到感觉。
公众号:蓝海资料掘金营,微信deep3321