做市策略核心指标:买卖价差、市场深度、库存风险、skew与delta
做市策略说白了就是「低买高卖」的自动化版本。但真要把这件事做好,你得盯住几个核心指标。我做了这么多年低延迟做市系统,发现很多新手一上来就写策略逻辑,结果跑起来才发现——连最基本的价差都没算对。
今天咱们就把这几个指标掰开揉碎讲清楚。嗯,每个指标我都踩过坑,有些坑现在想起来还肉疼。
买卖价差(Bid-Ask Spread)
买卖价差,就是市场上最优买价和最优卖价之间的差值。公式很简单:
Spread = Ask_Price - Bid_Price
但实际做市时,我们更关心的是有效价差。什么意思?
举个例子。假设某股票最优买价是10.00,最优卖价是10.02,名义价差是2分钱。但如果你挂单10.00买入,成交概率可能只有30%。真正能成交的价差,往往比名义价差大。
我个人习惯:用加权平均价差来评估流动性。把每个价位的挂单量考虑进去,算出来的才是「真实价差」。
我在项目中遇到过一种情况:某个币种在交易所显示价差只有0.01%,但实际一成交,滑点直接吃掉0.05%。为什么?因为价差虽然窄,但深度极浅,大单根本吃不到。
所以,价差要结合深度一起看。后面会讲。
市场深度(Market Depth)
市场深度描述的是「在某个价格水平上,有多少订单等着成交」。说白了,就是订单簿上每一档的挂单量。
深度越厚,大单对价格的冲击越小。深度越薄,一个100手的单子就能把价格打穿好几档。
我常用的深度指标有两个:
- 总深度:从最优价到第N档的总挂单量
- 深度斜率:价格每变动一个tick,挂单量的变化率
举个例子,假设订单簿长这样:
| 档位 | 买价 | 买量 | 卖价 | 卖量 |
|---|---|---|---|---|
| 1 | 10.00 | 1000 | 10.02 | 800 |
| 2 | 9.99 | 2000 | 10.03 | 1500 |
| 3 | 9.98 | 3000 | 10.04 | 2500 |
前3档的总买深度是6000,总卖深度是4800。买盘明显比卖盘厚。这时候如果你做市,挂买单的风险比挂卖单小——因为万一价格下跌,下面有更厚的买盘撑着。
避坑指南:我曾经在深度薄的品种上同时挂了双边订单,结果一个突发消息导致价格瞬间跳空,两边都被吃掉,库存直接爆仓。后来我加了个深度阈值——深度低于某个值,只做单边。
库存风险(Inventory Risk)
做市商最怕什么?不是价格涨跌,而是库存不对称。
你想想看,做市策略本质上是赚价差,不是赌方向。但如果你的库存里全是多头,价格一跌,账面亏损就来了。这就是库存风险。
衡量库存风险,我一般用两个维度:
- 库存价值:当前持仓的总市值
- 库存敞口:净持仓相对于目标库存的偏离度
举个例子。假设你的目标库存是0(中性),但实际持有了1000股多头。这时候库存敞口就是1000股。如果股价跌1%,你就亏1000股×1%的市值。
怎么控制?我常用的方法是动态调整报价:
# 伪代码示例
if inventory > target:
# 库存偏多,降低买价,提高卖价
bid_price = fair_price - spread/2 - skew
ask_price = fair_price + spread/2 + skew
else:
# 库存偏空,提高买价,降低卖价
bid_price = fair_price - spread/2 + skew
ask_price = fair_price + spread/2 - skew
说白了,库存多了就压价卖,库存少了就提价买。这个skew就是调节力度。
注意:skew不能设太大,否则你的报价会偏离市场太远,根本成交不了。我见过有人把skew设成价差的2倍,结果挂了一整天一单没成。
Skew与Delta
Skew和Delta是做市策略里最容易被混淆的两个概念。我简单说清楚。
Skew:报价偏移量。用来调节买卖报价,以控制库存风险。skew越大,报价越偏向于「去库存」的方向。
Delta:价格敏感度。更准确地说,是持仓价值对价格变动的敏感度。对于现货,delta就是持仓数量。对于期权,delta是期权价格对标的物价格的偏导数。
两者有什么关系?
Skew是主动调节的手段,Delta是被动暴露的结果。你通过调整skew来影响delta,最终目标是让delta趋近于0(中性)。
举个例子:
- 当前delta = +500(多头500股)
- 你希望delta = 0
- 于是你设置skew = 0.01,让卖价降低0.01,吸引卖出成交
- 成交后,delta下降,skew也随之减小
这是一个闭环反馈系统。我习惯用PID控制器来调节skew:
class SkewController:
def __init__(self, kp, ki, kd):
self.kp = kp # 比例系数
self.ki = ki # 积分系数
self.kd = kd # 微分系数
self.prev_error = 0
self.integral = 0
def update(self, current_delta, target_delta):
error = current_delta - target_delta
self.integral += error
derivative = error - self.prev_error
self.prev_error = error
skew = (self.kp * error +
self.ki * self.integral +
self.kd * derivative)
return skew
这个控制器会根据delta偏离程度,自动计算合适的skew。比例项处理当前偏差,积分项消除稳态误差,微分项抑制震荡。
我个人经验:kp、ki、kd这三个参数,千万别一上来就调。先固定kp,等策略稳定了再加ki。kd我一般设得很小,甚至为0——因为高频做市里,微分项容易放大噪声。
指标之间的联动关系
这几个指标不是孤立的。它们互相影响,形成一个动态系统。
举个例子:
- 市场深度突然变薄(比如大单撤单)
- 价差扩大,成交难度增加
- 库存无法快速调整,delta偏离增大
- skew被迫调大,报价偏离市场
- 进一步降低成交概率,库存风险累积
你看,一个深度变化,能引发连锁反应。所以做市系统必须实时监控所有指标,任何一个指标超出阈值,都要触发保护机制。
我常用的保护逻辑:
- 价差 > 阈值 → 暂停做市
- 深度 < 阈值 → 只做单边
- delta > 阈值 → 强制平仓
- skew > 阈值 → 报警人工干预
嗯,说到报警,我记得有一次凌晨3点,系统报警说skew超过了0.05。我爬起来一看,原来是交易所的撮合引擎出了bug,订单簿数据全乱了。要不是这个指标报警,那天晚上库存得亏掉几十万。
所以,指标不只是用来赚钱的,更是用来保命的。
最后说一句:这些指标的计算,一定要在低延迟路径上完成。我见过有人把指标计算放在Python层,结果每次计算要花几微秒——对于高频做市来说,这几微秒足够让订单飞走了。建议用C++实现核心指标计算,Python只做监控和日志。