Market Maker Protection (MMP)
Fill-window limits and auto-cancel behavior for market makers.
Overview
MMP protects market makers from rapid adverse fills by:
- Tracking cumulative fill metrics within a rolling time window
- Canceling orders when limits are breached
- Auto-canceling all other MMP-enabled orders for the same wallet+underlying
Configuration
Set MMP Config
Endpoint: POST /mmp-config
Request: SetMmpConfigRequest
{
"wallet": "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,
"signature": "0x..."
}
Fields:
wallet: Wallet addresscurrency: Underlying currency (e.g.,"BTC","ETH")interval_ms: Rolling window length in millisecondsfrozen_time_ms: Freeze duration after trigger (milliseconds)qty_limit: Optional quantity limit (contract units)delta_limit: Optional delta limitvega_limit: Optional vega limitenabled: Whether MMP is enabled for this wallet+currency
Response: ApiResponse<MmpConfigData>
Get MMP Config
Endpoint: GET /mmp-config?wallet=...¤cy=...
Query parameters:
wallet(required)currency(optional filter)
Response: 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
}
]
}
Delete MMP Config
Endpoint: DELETE /mmp-config
Request: DeleteMmpConfigRequest
{
"wallet": "0x...",
"currency": "BTC",
"nonce": 1,
"signature": "0x..."
}
Response: ApiResponse<String>
Reset MMP State
Endpoint: POST /mmp-config/reset
Request: ResetMmpRequest
{
"wallet": "0x...",
"currency": "BTC",
"nonce": 1,
"signature": "0x..."
}
Response: ApiResponse<String>
Notes: Resets MMP fill-window state (clears cumulative metrics, unfreezes currency).
MMP Behavior (Critical to Understand)
Fill Processing Order
MMP evaluation is POST-FILL:
- Engine matches and accepts the fill first
- Then MMP checks cumulative metrics
- If limits are breached:
- MMP triggers
- Remaining quantity on active order stops processing
- Order becomes
CANCELEDwith reason:"MMP triggered during fill processing" - Engine emits
MmpTriggeredevent - Engine auto-cancels all other MMP-enabled open orders for the same wallet+underlying
Implication: You can receive fills that push you beyond your configured thresholds before MMP triggers.
Trigger Conditions
MMP triggers if any configured limit is breached:
- Quantity limit:
cumulative_qty > qty_limit - Delta limit:
|cumulative_delta| > delta_limit - Vega limit:
|cumulative_vega| > vega_limit
Cumulative metrics are computed over the rolling window (interval_ms).
Cancel Behavior
When MMP triggers:
- Active order: Remaining quantity stops, order becomes
CANCELEDwith reason"MMP triggered during fill processing" - Other orders: All other MMP-enabled open orders for the same wallet+underlying are auto-canceled with reason
"Order canceled by MMP trigger"
Note: Only MMP-enabled orders are canceled. Orders with mmp_enabled=false are not affected.
Freeze Behavior
After MMP triggers:
- Currency is frozen for
frozen_time_msmilliseconds - While frozen, new fills may be rejected (implementation-dependent)
Fill Metrics Calculation
Quantity
- Source: Fill
size(contract units) - Cumulative: Sum of all fills in the rolling window
Delta
- Source: Calculated from fill symbol and GreeksCache
- Cumulative: Sum of all fill deltas in the rolling window
Vega
- Source: Calculated from fill symbol and GreeksCache
- Cumulative: Sum of all fill vegas in the rolling window
Rolling Window
Window Eviction
Fills older than interval_ms are automatically evicted from the window:
- Eviction runs periodically (background task)
- Cumulative metrics are decremented as old fills are removed
Window Reset
Reset MMP state via POST /mmp-config/reset:
- Clears all fills in the window
- Resets cumulative metrics to zero
- Unfreezes currency
MMP Events
MmpTriggered Event
Internal event (not currently forwarded to WS clients):
MmpTriggeredMessage {
wallet: WalletAddress,
currency: String,
reason: String, // "qty_limit" | "delta_limit" | "vega_limit"
}
Best Practices
Configuration
- Set appropriate limits: Based on your risk tolerance and typical fill sizes
- Use currency-specific configs: Configure per underlying (BTC, ETH, etc.)
- Monitor MMP triggers: High trigger rate may indicate misconfigured limits or adverse market conditions
Order Management
- Enable MMP selectively: Set
mmp_enabled=trueonly for orders you want protected - Use consistent currency: Ensure all orders for the same underlying use the same currency in MMP config
- Handle MMP cancels: Implement logic to detect MMP-triggered cancels and adjust quoting
Monitoring
- Track MMP triggers: Monitor for
"MMP triggered during fill processing"and"Order canceled by MMP trigger"reasons - Review fill windows: Check cumulative metrics via MMP config (not exposed via API currently)
- Adjust limits: If MMP triggers too frequently, increase limits; if too infrequently, decrease limits
Common Issues
MMP Triggers Too Frequently
Causes:
- Limits too low for typical fill sizes
- Adverse market conditions
- Rapid quoting causing many fills
Solutions:
- Increase
qty_limit,delta_limit, orvega_limit - Increase
interval_msto allow more fills in window - Reduce quoting frequency
MMP Doesn't Trigger
Causes:
- Limits too high
- MMP not enabled on orders (
mmp_enabled=false) - Currency mismatch (MMP config currency != order underlying)
Solutions:
- Decrease limits
- Verify
mmp_enabled=trueon orders - Verify MMP config currency matches order underlying
Unexpected Cancels
Symptom: Orders canceled with reason "Order canceled by MMP trigger" but you didn't expect it.
Cause: Another order for the same wallet+underlying triggered MMP.
Solution: Review all MMP-enabled orders for the same underlying when one triggers.