本页为简体中文译文。如有歧义,请以英文原文为准。 阅读英文版 →
跳转到主要内容

做市商保护 (MMP)

面向做市商的成交窗口限额与自动撤单行为。

所有钱包范围的 MMP 端点均需要 EIP-712 认证。配置写入操作接受钱包所有者或该钱包的授权代理签名。读取操作仅限所有者,拒绝授权代理签名。

MMP 作用于持有成交的交易账户。对于组合保证金管理者,以管理者钱包签名的读取和写入操作会解析到其 Account.sol 交易账户,即下单所使用的同一账户。响应在 wallet_address 中报告该账户,MMP nonce 序列也归属于该账户。

如需写后读一致性,请在任何 MMP 变更请求中发送 X-Hypercall-Fence-Wait: 1。成功的响应将包含 X-Hypercall-Fence;请在经认证的 GET 请求中将该值作为 X-Hypercall-Fence 回传。未携带该可选等待请求头的变更请求有意不返回 fence。

概述​

MMP 通过以下方式保护做市商免受快速不利成交的影响:

  1. 在滚动时间窗口内跟踪累计成交指标
  2. 在突破限额时撤销订单
  3. 自动撤销同一钱包+标的资产下所有其他启用 MMP 的订单

配置​

设置 MMP 配置​

端点:POST /mmp-config

请求:SetMmpConfigRequest

{
"wallet": "0x...",
"currency": "BTC",
"interval_ms": 60000,
"frozen_time_ms": 300000,
"qty_limit": "1000000",
"delta_limit": "10.0",
"vega_limit": "5.0",
"nonce": 1,
"signature": "0x..."
}

字段:

  • wallet:钱包地址
  • currency:标的资产币种(例如 "BTC"、"ETH")
  • interval_ms:滚动窗口长度(毫秒)
  • frozen_time_ms:触发后的冻结时长(毫秒)
  • qty_limit:可选的数量限额(合约单位),以十进制字符串序列化
  • delta_limit:可选的 Delta 限额,以十进制字符串序列化
  • vega_limit:可选的 Vega 限额,以十进制字符串序列化
  • nonce:防重放 nonce,必须恰好比经认证读取返回的最新已提交 nonce 大 1
  • signature:覆盖所有请求字段的 EIP-712 SetMmpConfig 签名

响应:ApiResponse<MmpConfigData>

获取 MMP 配置​

端点:GET /mmp-config?wallet=...&currency=...

查询参数:

  • wallet(必填)
  • currency(可选过滤条件)

必需的请求头:

  • X-Hypercall-Expires-At-Ms:以毫秒表示的 Unix 过期时间,不得晚于当前时间 60 秒以上
  • X-Hypercall-Signature:覆盖 wallet、currency(省略时为空字符串)及请求头过期时间的 GetMmpConfig 签名

恢复出的签名者必须是钱包所有者。此读取操作不接受授权代理签名。

响应:MmpConfigResponse

{
"success": true,
"data": [
{
"wallet_address": "0x...",
"currency": "BTC",
"interval_ms": 60000,
"frozen_time_ms": 300000,
"qty_limit": "1000000",
"delta_limit": "10.0",
"vega_limit": "5.0",
"enabled": true,
"nonce": 1
}
]
}

删除 MMP 配置​

端点:DELETE /mmp-config

请求:DeleteMmpConfigRequest

{
"wallet": "0x...",
"currency": "BTC",
"nonce": 1,
"signature": "0x..."
}

响应:ApiResponse<String>。成功的命令会禁用该钱包/标的资产的数值权威状态。若携带请求头 X-Hypercall-Fence-Wait: 1,响应将包含用于投影读取的 X-Hypercall-Fence。

重置 MMP 状态​

端点:POST /mmp-config/reset

请求:ResetMmpRequest

{
"wallet": "0x...",
"currency": "BTC",
"nonce": 1,
"signature": "0x..."
}

响应:ApiResponse<String>。成功的命令会在可重放的权威状态中清除 MMP 成交窗口和冻结状态。若携带请求头 X-Hypercall-Fence-Wait: 1,响应将包含用于投影读取的 X-Hypercall-Fence。

MMP 行为(务必理解)​

哪些成交会被计入​

每笔成交都会计入订单设置了 mmp_enabled=true 的每一方的 MMP 窗口,无论该订单是挂在订单簿上的(Maker)还是新进入的(Taker):

  • 挂单报价: 当新进入的订单与您启用 MMP 的挂单成交时,该成交会被计入您的窗口。这正是 MMP 存在的意义:针对您报价的一连串成交会触发 MMP,并撤销您在该标的资产上剩余的启用 MMP 的报价。
  • 新进入订单: 启用 MMP 的吃单订单以同样方式计入其自身成交。
  • 组合订单与隐含订单: 组合包中每个受保护的参与方都会计入其成交的每一条腿,并按每个组合包评估一次。
  • RFQ 和 RPI 成交目前尚不计入 MMP。 MMP 冻结会阻止被冻结报价方的新 RFQ 执行。

每笔成交均从您自身的方向计量:卖出看涨期权的成交会为卖方窗口增加负 Delta,为买方窗口增加正 Delta。

如果订单设置了 mmp_enabled=true,但其钱包在该标的资产上没有 MMP 配置,MMP 将以失败关闭方式处理:第一笔成交即会触发,并撤销该钱包在该标的资产上所有启用 MMP 的订单。请在标记订单之前先配置 MMP。

成交处理顺序​

MMP 评估在成交之后进行:

  1. 引擎完成撮合并先接受成交
  2. 随后 MMP 针对成交中每个受保护的一方检查累计指标
  3. 如果某一方突破限额:
    • MMP 针对该方的钱包和标的资产触发
    • 引擎发出 MmpTriggered 事件
    • 引擎自动撤销该钱包+标的资产下所有启用 MMP 的未成交订单
    • 如果突破限额的一方是新进入订单,其剩余数量停止撮合,订单变为 CANCELED,原因为 "MMP triggered during fill processing"
    • 如果突破限额的一方是挂单 Maker,新进入订单将继续与其他流动性撮合;该 Maker 其他启用 MMP 的报价已被撤销

影响:在 MMP 触发之前,您可能会收到使您超出所配置阈值的成交。

触发条件​

只要任一已配置的限额被突破,MMP 即会触发:

  • 数量限额:cumulative_qty > qty_limit
  • Delta 限额:|cumulative_delta| > delta_limit
  • Vega 限额:|cumulative_vega| > vega_limit

累计指标在滚动窗口(interval_ms)内计算。

撤单行为​

MMP 触发时:

  1. 触发 MMP 的新进入订单:剩余数量停止撮合,订单变为 CANCELED,原因为 "MMP triggered during fill processing"
  2. 触发 MMP 的挂单:成交保持有效;订单的剩余部分(如有)将与其他启用 MMP 的订单一并撤销
  3. 其他订单:同一钱包+标的资产下所有启用 MMP 的未成交订单将被自动撤销,原因为 "Order canceled by MMP trigger"

注意:只有启用 MMP 的订单会被撤销。mmp_enabled=false 的订单不受影响。

冻结行为​

MMP 触发后:

  • 该钱包和标的资产将被冻结 frozen_time_ms 毫秒
  • 冻结期间,该钱包被排除在该标的资产的 RPI 拍卖和 RFQ 之外,会使其成交的组合或隐含执行将被拒绝
  • 冻结期间启用 MMP 的订单发生的直接成交仍然有效,随后会再次触发 MMP,并撤销该钱包在该标的资产上所有启用 MMP 的订单
  • POST /mmp-config/reset 可提前结束冻结

成交指标计算​

数量​

  • 来源:成交的 size(合约单位)
  • 累计:滚动窗口内所有成交之和

Delta​

  • 来源:根据成交合约代码和 GreeksCache 计算
  • 累计:滚动窗口内所有成交 Delta 之和

Vega​

  • 来源:根据成交合约代码和 GreeksCache 计算
  • 累计:滚动窗口内所有成交 Vega 之和

滚动窗口​

窗口淘汰​

早于 interval_ms 的成交会自动从窗口中淘汰:

  • 淘汰在处理下一笔成交时、新成交加入之前执行
  • 移除旧成交时相应递减累计指标

窗口重置​

通过 POST /mmp-config/reset 重置 MMP 状态:

  • 清除窗口内的所有成交
  • 将累计指标重置为零
  • 解除该币种的冻结

MMP 事件​

MmpTriggered 事件​

内部事件(目前不会转发给 WS 客户端):

MmpTriggeredMessage {
wallet: WalletAddress,
currency: String,
reason: String, // "MMP triggered during fill processing" | "MMP triggered by a resting order fill"
timestamp: u64,
}

最佳实践​

配置​

  1. 设置合适的限额:根据您的风险承受能力和典型成交规模设定
  2. 使用按币种的配置:按标的资产(BTC、ETH 等)分别配置
  3. 监控 MMP 触发:触发频率过高可能意味着限额配置不当或市场环境不利

订单管理​

  1. 有选择地启用 MMP:仅为需要保护的订单设置 mmp_enabled=true
  2. 使用一致的币种:确保同一标的资产的所有订单在 MMP 配置中使用相同的币种
  3. 处理 MMP 撤单:实现检测 MMP 触发撤单并调整报价的逻辑

监控​

  1. 跟踪 MMP 触发:监控原因为 "MMP triggered during fill processing" 和 "Order canceled by MMP trigger" 的事件
  2. 复核成交窗口:累计窗口指标目前尚未通过 API 公开;请自行按标的资产跟踪您的成交
  3. 调整限额:如果 MMP 触发过于频繁,请提高限额;如果触发过少,请降低限额

常见问题​

MMP 触发过于频繁​

原因:

  • 限额相对于典型成交规模过低
  • 市场环境不利
  • 快速报价导致大量成交

解决方案:

  • 提高 qty_limit、delta_limit 或 vega_limit
  • 增大 interval_ms,允许窗口内容纳更多成交
  • 降低报价频率

MMP 未触发​

原因:

  • 限额过高
  • 订单未启用 MMP(mmp_enabled=false)
  • 币种不匹配(MMP 配置币种 != 订单标的资产)

解决方案:

  • 降低限额
  • 确认订单已设置 mmp_enabled=true
  • 确认 MMP 配置币种与订单标的资产一致

意外撤单​

现象:订单以原因 "Order canceled by MMP trigger" 被撤销,但您并未预期到。

原因:同一钱包+标的资产下的另一笔订单触发了 MMP。

解决方案:当某笔订单触发 MMP 时,复核同一标的资产下所有启用 MMP 的订单。