做市策略核心算法:定价模型、库存管理与风险控制

做市策略的核心,说白了就是回答三个问题:报什么价?报多少量?什么时候改价? 这三个问题环环相扣,任何一个环节出问题,轻则亏钱,重则爆仓。今天我就把这套逻辑拆开揉碎了讲清楚。

核心公式:做市商利润 = 买卖价差收入 - 库存风险成本 - 交易损耗

定价模型解决「价差收入」,库存管理解决「库存风险」,报价频率解决「交易损耗」。

3.1 Avellaneda-Stoikov 定价模型

这个模型是我个人最常用的基准模型。为什么?因为它把做市问题转化成了一个数学上可解的最优控制问题。

模型的核心思想很简单:你的报价应该围绕「合理价格」上下浮动,浮动幅度取决于你的库存和风险偏好。

具体来说,假设当前市场中间价为 S,你的库存为 q(正数表示多头,负数表示空头),风险厌恶系数为 γ,那么你的最优买价和卖价分别是:

# 伪代码示例
mid_price = get_market_mid_price()
inventory = get_current_inventory()  # 正数=多头,负数=空头
gamma = 0.1  # 风险厌恶系数,越大越保守
sigma = 0.02  # 波动率
T = 1.0  # 剩余时间(年化)

# 库存偏移量
inventory_skew = -gamma * sigma^2 * T * inventory

# 最优报价
bid_price = mid_price + inventory_skew - spread/2
ask_price = mid_price + inventory_skew + spread/2

嗯,这里要注意:inventory_skew 是负的。也就是说,当你持有多头(q > 0)时,你的买价和卖价都会向下偏移。为什么?因为你手里已经有很多货了,你更想卖出去而不是继续买。反过来,空头时报价向上偏移。

我的经验: 我在实盘中发现,γ 这个参数特别敏感。设大了,报价偏移太猛,成交率低;设小了,库存风险控制不住。我一般先用历史数据回滚优化,上线后再用在线学习慢慢调。

3.2 库存管理:别让库存绑架你

定价模型告诉你报什么价,但库存管理告诉你什么时候该强制平仓

我个人习惯把库存管理分成三层:

  1. 目标库存区间:比如 [-100, 100] 张合约。在这个区间内,正常做市,靠定价模型自动调节。
  2. 警戒线:比如 [-300, 300]。一旦触及,启动「库存消化模式」——缩小价差、主动往不利方向报价,加速平仓。
  3. 硬止损线:比如 [-500, 500]。到了这个位置,别犹豫,直接市价平仓。亏钱总比爆仓强。

我曾经吃过一次大亏。那次行情剧烈波动,库存瞬间冲到警戒线以上,我还在犹豫要不要调参数,结果继续往不利方向走了几十个tick。嗯,从那以后我写死了硬止损逻辑,程序自动执行,不给人犹豫的机会。

# 库存管理逻辑示例
def manage_inventory(current_inventory):
    HARD_LIMIT = 500
    WARN_LIMIT = 300
    TARGET_LIMIT = 100
    
    if abs(current_inventory) >= HARD_LIMIT:
        # 强制市价平仓
        market_order(-current_inventory)
        return "FORCED_LIQUIDATION"
    
    elif abs(current_inventory) >= WARN_LIMIT:
        # 缩小价差,加速平仓
        set_spread_multiplier(0.5)
        return "AGGRESSIVE"
    
    elif abs(current_inventory) >= TARGET_LIMIT:
        # 正常做市,但略微偏向平仓方向
        set_spread_multiplier(1.0)
        return "NORMAL"
    
    else:
        # 完全正常做市
        return "COMFORT"

3.3 风险控制:不止是止损

很多人以为风控就是设个止损线。其实远不止这些。我总结了三道防线:

防线 内容 触发条件
第一道 报价合理性检查 报价偏离市场中间价超过N个标准差
第二道 库存限额 库存绝对值超过阈值
第三道 总亏损限额 当日累计亏损超过设定值

第一道防线很多人会忽略。你想想看,如果行情数据出现异常(比如交易所的撮合引擎抽风),你的定价模型可能会算出离谱的报价。我曾经遇到过,某次数据源推送了一个错误的价格,我的模型瞬间报出了低于市场价10%的买单。还好报价合理性检查拦截了,不然那一单吃进去,够我喝一壶的。

避坑指南: 风控逻辑一定要独立于交易逻辑运行。别把风控写在主循环里,万一主循环卡住了,风控也跟着失效。我习惯单独开一个线程跑风控监控,心跳检测,5秒没收到心跳就自动断开所有连接。

3.4 报价更新频率:快与稳的平衡

报价频率这个问题,其实没有标准答案。你想想看,频率太高,容易给交易所造成压力,还可能被判定为「过度报价」;频率太低,你的报价可能已经过时了,被市场甩在后面。

我个人建议分场景处理:

  • 正常行情:每 100-500 毫秒更新一次报价。这个频率足够应对大部分行情变化,又不会给系统太大负担。
  • 剧烈波动:缩短到 50-100 毫秒。行情变化快,你的报价也得跟上。
  • 盘整行情:可以延长到 1-2 秒。没必要频繁更新,省点计算资源。

怎么判断行情状态?我一般用波动率指标。当波动率超过某个阈值时,自动切换到高频模式。

# 报价频率自适应逻辑
def get_update_interval():
    current_volatility = calculate_volatility(window=20)
    
    if current_volatility > HIGH_VOL_THRESHOLD:
        return 50  # 毫秒
    elif current_volatility > MED_VOL_THRESHOLD:
        return 200
    else:
        return 1000

我的经验: 别把报价更新和策略计算放在同一个循环里。我习惯用两个独立的定时器:一个负责计算最优报价(可以慢一点,比如每秒一次),另一个负责把算好的报价发到交易所(可以快一点,比如每100毫秒一次)。这样即使计算偶尔延迟,报价也能保持更新。

3.5 知识体系总览

下面这张图把今天讲的内容串起来了。你可以看到,定价模型、库存管理、风险控制、报价频率这四个模块是相互影响的。

做市策略核心算法架构 Avellaneda-Stoikov 定价模型 库存管理 目标区间 → 警戒线 → 硬止损 风险控制 报价检查 → 库存限额 → 亏损限额 报价更新频率 库存影响定价偏移 风控约束报价范围 频率影响报价时效性 四个模块相互影响,共同决定最终报价

你看,这四个模块不是孤立的。定价模型算出来的报价,要经过库存管理的偏移修正,再经过风险控制的合规检查,最后按照合适的频率发出去。任何一个环节出问题,整个系统都会受影响。

好了,这一章的内容就到这里。定价模型、库存管理、风险控制、报价频率,这四个点你吃透了,做市策略的核心算法就算入门了。剩下的就是不断优化参数、积累经验。

专注资料整理