Market Maker Protection (MMP)
Limites por janela de execuções e comportamento de cancelamento automático para market makers.
Todo endpoint de MMP com escopo de carteira exige autenticação EIP-712. Escritas de configuração aceitam o dono da carteira ou um agente autorizado para essa carteira. Leituras são exclusivas do dono e rejeitam assinaturas de agentes autorizados.
O MMP se aplica à conta de trading que detém as execuções. Para um gestor de
portfolio margin, leituras e escritas assinadas pela carteira do gestor resolvem para sua
conta de trading Account.sol, a mesma conta usada no envio de ordens.
As respostas reportam essa conta em wallet_address, e a sequência de nonces do MMP
pertence a essa conta.
Para consistência de leitura após escrita, envie X-Hypercall-Fence-Wait: 1 em qualquer
mutação de MMP. Uma resposta bem-sucedida então inclui X-Hypercall-Fence; repasse esse
valor como X-Hypercall-Fence no GET autenticado. Mutações sem o
header de espera opcional intencionalmente não retornam um fence.
Visão geral
O MMP protege market makers contra execuções adversas rápidas ao:
- Acompanhar métricas cumulativas de execução dentro de uma janela de tempo móvel
- Cancelar ordens quando os limites são violados
- Cancelar automaticamente todas as outras ordens com MMP habilitado para a mesma carteira+ativo subjacente
Configuração
Definir configuração de MMP
Endpoint: POST /mmp-config
Requisição: 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..."
}
Campos:
wallet: Endereço da carteiracurrency: Moeda do ativo subjacente (por exemplo,"BTC","ETH")interval_ms: Duração da janela móvel em milissegundosfrozen_time_ms: Duração do congelamento após o gatilho (milissegundos)qty_limit: Limite de quantidade opcional (unidades de contrato), serializado como string decimaldelta_limit: Limite de delta opcional, serializado como string decimalvega_limit: Limite de vega opcional, serializado como string decimalnonce: Nonce de proteção contra replay, exatamente um a mais que o último nonce confirmado retornado pela leitura autenticadasignature: Assinatura EIP-712SetMmpConfigsobre todos os campos da requisição
Resposta: ApiResponse<MmpConfigData>
Obter configuração de MMP
Endpoint: GET /mmp-config?wallet=...¤cy=...
Parâmetros de query:
wallet(obrigatório)currency(filtro opcional)
Headers obrigatórios:
X-Hypercall-Expires-At-Ms: Expiração Unix em milissegundos, no máximo 60 segundos no futuroX-Hypercall-Signature: AssinaturaGetMmpConfigsobrewallet,currency(string vazia quando omitido) e a expiração do header
O signatário recuperado deve ser o dono da carteira. Assinaturas de agentes autorizados não são aceitas para esta leitura.
Resposta: 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
}
]
}
Excluir configuração de MMP
Endpoint: DELETE /mmp-config
Requisição: DeleteMmpConfigRequest
{
"wallet": "0x...",
"currency": "BTC",
"nonce": 1,
"signature": "0x..."
}
Resposta: ApiResponse<String>. Um comando bem-sucedido desabilita o estado
numérico de autoridade da carteira/ativo subjacente. Com o header de requisição
X-Hypercall-Fence-Wait: 1, a resposta inclui X-Hypercall-Fence para a
leitura baseada em projeção.
Resetar estado do MMP
Endpoint: POST /mmp-config/reset
Requisição: ResetMmpRequest
{
"wallet": "0x...",
"currency": "BTC",
"nonce": 1,
"signature": "0x..."
}
Resposta: ApiResponse<String>. Um comando bem-sucedido limpa a janela de execuções
do MMP e o estado de congelamento na autoridade reproduzível. Com o header de requisição
X-Hypercall-Fence-Wait: 1, a resposta inclui X-Hypercall-Fence para a
leitura baseada em projeção.
Comportamento do MMP (essencial entender)
Quais execuções contam
Toda execução conta para a janela de MMP de cada lado cuja ordem tem
mmp_enabled=true, seja essa ordem repousando no livro (maker) ou
chegando (taker):
- Cotações em repouso: quando uma ordem recebida negocia contra sua ordem em repouso com MMP habilitado, essa execução é adicionada à sua janela. Este é o caso para o qual o MMP existe: uma rajada de execuções contra suas cotações dispara o MMP e cancela suas cotações restantes com MMP habilitado naquele ativo subjacente.
- Ordens recebidas: uma ordem com MMP habilitado que consome liquidez conta suas próprias execuções da mesma forma.
- Combos e ordens implícitas: cada participante protegido de um pacote conta todas as pernas que negocia, avaliadas uma vez por pacote.
- Execuções de RFQ e RPI ainda não contam para o MMP. Um congelamento de MMP bloqueia novas execuções de RFQ para o provedor de cotações congelado.
Cada execução é medida a partir do seu próprio lado: uma execução que vende uma call adiciona delta negativo à janela do vendedor e delta positivo à do comprador.
Se uma ordem tem mmp_enabled=true, mas sua carteira não tem configuração de MMP
para aquele ativo subjacente, o MMP falha de forma fechada: a primeira execução dispara e cancela as
ordens com MMP habilitado daquela carteira no ativo subjacente. Configure o MMP antes de marcar
ordens.
Ordem de processamento das execuções
A avaliação do MMP é PÓS-EXECUÇÃO:
- O engine casa e aceita a execução primeiro
- Em seguida, o MMP verifica as métricas cumulativas para cada lado protegido da execução
- Se os limites de um lado forem violados:
- O MMP dispara para a carteira e o ativo subjacente daquele lado
- O engine emite o evento
MmpTriggered - O engine cancela automaticamente todas as ordens abertas com MMP habilitado para aquela carteira+ativo subjacente
- Se o lado que violou era a ordem recebida, sua quantidade restante
é interrompida e ela passa a
CANCELEDcom o motivo"MMP triggered during fill processing" - Se o lado que violou era um maker em repouso, a ordem recebida continua casando contra outra liquidez; as outras cotações com MMP habilitado do maker já foram canceladas
Implicação: Você pode receber execuções que o levam além dos limites configurados antes de o MMP disparar.
Condições de disparo
O MMP dispara se qualquer limite configurado for violado:
- Limite de quantidade:
cumulative_qty > qty_limit - Limite de delta:
|cumulative_delta| > delta_limit - Limite de vega:
|cumulative_vega| > vega_limit
Métricas cumulativas são calculadas sobre a janela móvel (interval_ms).
Comportamento de cancelamento
Quando o MMP dispara:
- Ordem recebida que disparou: a quantidade restante é interrompida e a ordem passa a
CANCELEDcom o motivo"MMP triggered during fill processing" - Ordem em repouso que disparou: a execução permanece válida; o restante da ordem, se houver, é cancelado junto com as outras ordens com MMP habilitado
- Outras ordens: Todas as ordens abertas com MMP habilitado para a mesma carteira+ativo subjacente são canceladas automaticamente com o motivo
"Order canceled by MMP trigger"
Nota: Apenas ordens com MMP habilitado são canceladas. Ordens com mmp_enabled=false não são afetadas.
Comportamento de congelamento
Após o MMP disparar:
- A carteira e o ativo subjacente ficam congelados por
frozen_time_msmilissegundos - Enquanto congelada, a carteira é excluída de leilões RPI e RFQs naquele ativo subjacente, e execuções de combos ou implícitas que a executariam são rejeitadas
- Uma execução simples em uma ordem com MMP habilitado durante o congelamento continua válida, mas dispara o MMP novamente e cancela as ordens com MMP habilitado daquela carteira no ativo subjacente
POST /mmp-config/resetencerra o congelamento antecipadamente
Cálculo das métricas de execução
Quantidade
- Fonte:
sizeda execução (unidades de contrato) - Cumulativo: Soma de todas as execuções na janela móvel
Delta
- Fonte: Calculado a partir do símbolo da execução e do GreeksCache
- Cumulativo: Soma dos deltas de todas as execuções na janela móvel
Vega
- Fonte: Calculado a partir do símbolo da execução e do GreeksCache
- Cumulativo: Soma dos vegas de todas as execuções na janela móvel
Janela móvel
Remoção da janela
Execuções mais antigas que interval_ms são removidas automaticamente da janela:
- A remoção ocorre quando a próxima execução é processada, antes de a nova execução ser adicionada
- As métricas cumulativas são decrementadas conforme as execuções antigas são removidas
Reset da janela
Resete o estado do MMP via POST /mmp-config/reset:
- Limpa todas as execuções da janela
- Zera as métricas cumulativas
- Descongela a moeda
Eventos de MMP
Evento MmpTriggered
Evento interno (atualmente não repassado aos clientes WS):
MmpTriggeredMessage {
wallet: WalletAddress,
currency: String,
reason: String, // "MMP triggered during fill processing" | "MMP triggered by a resting order fill"
timestamp: u64,
}
Boas práticas
Configuração
- Defina limites adequados: Com base na sua tolerância a risco e nos tamanhos típicos de execução
- Use configurações específicas por moeda: Configure por ativo subjacente (BTC, ETH etc.)
- Monitore os disparos de MMP: Uma taxa alta de disparos pode indicar limites mal configurados ou condições de mercado adversas
Gestão de ordens
- Habilite o MMP seletivamente: Defina
mmp_enabled=trueapenas para as ordens que você quer proteger - Use moeda consistente: Garanta que todas as ordens do mesmo ativo subjacente usem a mesma moeda na configuração de MMP
- Trate os cancelamentos do MMP: Implemente lógica para detectar cancelamentos disparados pelo MMP e ajustar as cotações
Monitoramento
- Acompanhe os disparos de MMP: Monitore os motivos
"MMP triggered during fill processing"e"Order canceled by MMP trigger" - Revise as janelas de execução: As métricas cumulativas da janela ainda não são expostas pela API; acompanhe suas próprias execuções por ativo subjacente
- Ajuste os limites: Se o MMP disparar com frequência demais, aumente os limites; se disparar raramente demais, reduza os limites
Problemas comuns
O MMP dispara com frequência demais
Causas:
- Limites baixos demais para os tamanhos típicos de execução
- Condições de mercado adversas
- Cotação rápida gerando muitas execuções
Soluções:
- Aumente
qty_limit,delta_limitouvega_limit - Aumente
interval_mspara permitir mais execuções na janela - Reduza a frequência de cotação
O MMP não dispara
Causas:
- Limites altos demais
- MMP não habilitado nas ordens (
mmp_enabled=false) - Divergência de moeda (moeda da configuração de MMP != ativo subjacente da ordem)
Soluções:
- Reduza os limites
- Verifique
mmp_enabled=truenas ordens - Verifique se a moeda da configuração de MMP corresponde ao ativo subjacente da ordem
Cancelamentos inesperados
Sintoma: Ordens canceladas com o motivo "Order canceled by MMP trigger" sem que você esperasse.
Causa: Outra ordem para a mesma carteira+ativo subjacente disparou o MMP.
Solução: Revise todas as ordens com MMP habilitado para o mesmo ativo subjacente quando uma delas disparar.