第十一章:高频做市策略
做市商,说白了就是「两边报价,赚差价」的生意。但高频做市不是简单的低买高卖,而是一场与市场博弈的精密游戏。我做了这么多年,最大的体会是:做市策略的核心不是预测价格涨跌,而是管理你手里的库存和报价风险。
做市商定价模型
先聊聊定价模型。经典的做市商定价模型,我习惯用 Avellaneda-Stoikov 框架。这个模型的核心思想是:你的报价不仅要考虑当前市场价格,还要考虑你的库存水平。
公式其实不复杂:
# 做市商最优报价计算
def calculate_quotes(mid_price, inventory, inventory_target,
risk_aversion, order_book_imbalance):
"""
mid_price: 当前中间价
inventory: 当前库存(正数表示多头)
inventory_target: 目标库存(通常为0)
risk_aversion: 风险厌恶系数
order_book_imbalance: 订单簿不平衡度
"""
# 库存偏移量
inventory_skew = risk_aversion * (inventory - inventory_target)
# 订单簿偏移量
order_book_skew = 0.5 * order_book_imbalance
# 最优买价和卖价
bid_price = mid_price - inventory_skew - order_book_skew
ask_price = mid_price - inventory_skew + order_book_skew
return bid_price, ask_price
嗯,这里要注意:risk_aversion 这个参数很关键。我刚开始做的时候,把这个参数设得太小,结果库存风险敞口太大,一次黑天鹅事件差点爆仓。后来我学乖了,会根据历史波动率动态调整这个参数。
核心要点:做市商定价模型本质上是在「赚取价差」和「控制库存风险」之间找平衡。你的报价越宽,赚的差价越大,但成交概率越低;报价越窄,成交概率高,但库存风险也高。
库存风险管理
库存管理是做市策略的命门。我见过太多做市商,策略在回测时表现完美,一到实盘就亏钱,问题基本都出在库存管理上。
我个人习惯用以下几种方法管理库存:
- 库存阈值控制:设定库存上下限,一旦触及就强制平仓或调整报价
- 动态对冲:利用期货或期权对冲库存风险
- 报价偏移:根据库存水平动态调整报价,库存多就压低买价、抬高卖价
我曾经犯过一个错误:在某个流动性较差的品种上,库存阈值设得太宽松,结果库存积累到总资产的30%。那天市场突然跳水,我根本来不及平仓,损失惨重。从那以后,我给自己定了个规矩:任何品种的库存上限不超过总资产的5%。
避坑指南:库存管理不是事后补救,而是事前预防。你的策略在回测时一定要加入「极端行情下的库存压力测试」。我曾经见过一个策略,回测年化收益50%,但库存压力测试显示最大回撤80%——这种策略上实盘就是送钱。
报价更新策略
报价更新频率是做市策略的另一个关键点。更新太快,容易产生大量撤单费用;更新太慢,容易被市场「吃掉」。
我常用的报价更新策略有几种:
| 策略类型 | 触发条件 | 适用场景 |
|---|---|---|
| 时间驱动 | 固定时间间隔(如100ms) | 流动性好的品种 |
| 事件驱动 | 订单簿变化、成交、新消息 | 波动较大的品种 |
| 混合驱动 | 时间+事件双重触发 | 大多数情况 |
我个人更倾向于混合驱动策略。举个例子:
class QuoteUpdater:
def __init__(self, update_interval_ms=100):
self.last_update_time = 0
self.update_interval = update_interval_ms
self.pending_events = []
def should_update(self, current_time, order_book_event):
# 时间驱动:至少每100ms更新一次
time_trigger = (current_time - self.last_update_time) >= self.update_interval
# 事件驱动:订单簿变化超过阈值
event_trigger = self._is_significant_change(order_book_event)
return time_trigger or event_trigger
def _is_significant_change(self, event):
# 判断订单簿变化是否显著
# 比如价格变动超过0.1%,或者深度变化超过10%
return event.price_change_pct > 0.001 or event.depth_change_pct > 0.1
你想想看,如果只用时间驱动,市场剧烈波动时你可能反应太慢;如果只用事件驱动,市场平静时你又在频繁更新,白白浪费手续费。混合驱动就是取两者的优点。
做市商损益分析
最后聊聊损益分析。做市商的损益来源其实就三个:
- 价差收益:买卖价差带来的稳定收入
- 库存损益:持有库存期间价格波动带来的盈亏
- 手续费返还:交易所给做市商的返佣
我习惯用这个公式来评估做市策略的盈利能力:
def calculate_pnl(trades, inventory_history, fee_rate, rebate_rate):
"""
trades: 成交记录列表
inventory_history: 库存变化记录
fee_rate: 手续费率
rebate_rate: 做市商返佣率
"""
spread_pnl = 0
inventory_pnl = 0
fee_cost = 0
rebate_income = 0
for trade in trades:
# 价差收益:买入价和卖出价的差值
if trade.side == 'buy':
spread_pnl -= trade.price
else:
spread_pnl += trade.price
# 手续费和返佣
fee_cost += trade.amount * fee_rate
if trade.is_maker: # 如果是挂单成交
rebate_income += trade.amount * rebate_rate
# 库存损益:期末库存按市价估值
final_inventory = inventory_history[-1]
final_price = get_current_mid_price()
inventory_pnl = final_inventory * final_price
total_pnl = spread_pnl + inventory_pnl - fee_cost + rebate_income
return total_pnl
实战经验:很多新手做市商只盯着价差收益,忽略了库存损益。其实在波动大的市场中,库存损益往往比价差收益大得多。我建议每天收盘后做一次完整的损益归因分析,看看你的利润到底来自哪里。
做市策略的损益分析还有一个容易被忽视的点:机会成本。你的资金被占用在做市上,如果拿去投资其他品种可能收益更高。我一般会用夏普比率来评估做市策略的性价比,低于1.5的策略我会考虑优化或放弃。
做市策略说到底,就是一个不断平衡的过程。你既要赚取价差,又要控制库存风险;既要快速响应市场,又要控制成本。没有完美的策略,只有不断优化的过程。我做了这么多年,最大的感悟就是:做市不是靠预测市场赚钱,而是靠管理风险赚钱。