Market Maker Protections (MMP)
Market Maker Protections (MMP)
Market Maker Protections (MMP) is currently available for a set of whitelisted users.
Overview
MMP protects market makers from excessive fills during fast markets by automatically freezing protected orders once configured limits are exceeded.
MMP is available for perps and dated options and is configured per account (L2 address) and underlying (base asset). For example, one BTC configuration applies across all BTC perps and dated options for that account.
Only order book orders explicitly flagged for MMP are protected. Orders without the MMP flag are unaffected. RFQ and block trade fills count toward MMP limits only if the account opts in. See RFQ and block trades.
How MMP works
MMP tracks protected fills over a single sliding time window. Size, delta and vega are measured over the same window and compared independently against their configured limits.
Only MMP flagged fills count toward the window, and on the order book only the fill where your order was the resting maker. A flagged order that crosses the book is not counted. RFQ and block trade legs follow their own rules.
Because flagged orders that cross the book are not counted, they do not offset your maker fills in the window. Delta and vega limits trip on your gross maker exposure, so hedging with flagged aggressive orders does not keep the window’s net delta or vega down.
MMP is enforced by the matching engine, so concurrent fills across markets share the same state. At most one fill can take exposure beyond a configured limit before protection activates.
MMP relies on up to date Greeks. If Greeks become stale or unavailable for any market on an underlying, all MMP orders on that underlying are canceled with reason MMP_GREEKS_UNAVAILABLE, including orders on perps. This check applies to MMP orders that can rest, so an MMP IOC order is not canceled for stale Greeks.
RFQ and block trades
RFQ and block trade fills are protected only for accounts that opt in. Set protect_block_trades to true in the configuration for a base asset to protect your maker legs on that base asset. RFQ executions are included, because an RFQ settles as a block trade. The option is off by default.
You cannot set the MMP flag on a block trade leg yourself. Paradex applies it based on your protect_block_trades setting, to the legs described in Which legs above.
Before accepting a block trade request, Paradex checks the MMP settings of the accounts involved. If those settings cannot be read, the request is refused with HTTP 503 rather than proceeding without protection. This can happen even for accounts that have no MMP configuration. Retry the request later. The accounts checked depend on the request:
- Creating a block: every account with a maker leg, except the account that requested the quotes on a block built from offers.
- Creating an offer: the offering account.
Portfolio Margin
MMP can reduce the initial margin charged for protected resting orders under Portfolio Margin.
Without MMP, portfolio margin assumes all resting orders may fill. With MMP, Paradex instead considers the worst fills that can occur before protection activates: fills up to the size limit, plus one full triggering fill.
Only the size limit is used for margin relief. Delta and vega limits provide execution protection but do not reduce margin. Orders without the MMP flag are unaffected.
Calculation
For each portfolio margin stress scenario:
- Select the most damaging protected fills up to the size limit, allowing the last fill before the trigger to be partial, plus one full triggering fill.
- Add their loss to the position loss and the loss from orders without the MMP flag.
- The scenario with the largest combined loss sets the requirement.
The selected protected fills may differ across scenarios.
Example
Assume an account has a short BTC straddle and protected resting BTC call quotes with:
- MMP size limit: 2 BTC
- Quote size: 0.5 BTC
- 10 bids, each losing $4,000 in the BTC −14% scenario
- 6 asks, each losing $1,000 in the BTC +14% scenario
The position itself loses:
- $6,000 at BTC −14%
- $10,000 at BTC +14%
MMP can allow four 0.5 BTC fills up to the 2 BTC limit, plus one additional 0.5 BTC fill that triggers protection.
Portfolio margin therefore considers at most 2.5 BTC of protected fills per scenario, selecting whichever five quotes are most damaging.
Note that the position alone loses more in the +14% scenario. The protected bids move the binding scenario to −14%.
Without MMP, all 10 bids would count in the −14% scenario:
$6,000 + 10 × $4,000 = $46,000
MMP therefore reduces the scenario loss driving the requirement from $46,000 to $26,000.
Notes
- If the size limit is at or above the total protected resting size, the requirement is the same as without MMP.
- Maintenance margin is unchanged because it does not include open orders.
API
All endpoints are private. GET /v1/account/mmp also accepts a read only token, so you can always check which configurations are still enforced. All other endpoints require a regular (trading) JWT.
Sizes are in base units such as BTC or ETH. Times are in milliseconds.
Configuration changes can return HTTP 503 when market data is temporarily unavailable, and resets can return HTTP 503 while the matching engine is unavailable. Retry the request later.
Configuration
POST /v1/account/mmp/{base_asset} is a full create or replace: it overwrites any existing configuration. Omitted limits are set to 0. The exception is protect_block_trades: if you omit it, the stored value is kept. Only sending false turns block trade protection off. Each limit is optional, but at least one of size_limit, delta_limit or vega_limit must be non zero.
Invalid configurations, including values outside the allowed ranges and unsupported base assets, are rejected with MMP_CONFIG_INVALID (HTTP 400).
Request:
A successful POST or DELETE means the configuration has been persisted. The matching engine applies the change shortly afterward. Until it does, live fields in GET /v1/account/mmp, including is_frozen and the window totals, may be absent.
Example GET /v1/account/mmp response once the configuration is live:
account is the account the configurations belong to, and enabled indicates whether the account is enabled for MMP. A configuration listed while enabled is false is still enforced until it is deleted.
window_size, window_delta and window_vega are the current values accumulated over the same interval_ms window.
frozen_until is:
- the freeze expiry timestamp when
frozen_time_ms > 0; 0when frozen until manual reset;0when not frozen.
Use is_frozen to distinguish the last two cases.
Changing the configuration clears the trading window for that underlying. Posting an identical configuration again does not.
A freeze survives disabling MMP. Deleting and adding the configuration again does not clear an active freeze.
Disabling MMP cancels all resting MMP orders for that underlying with reason MMP_DISABLED, so no order remains resting without protection.
Reset
A reset keeps the configuration but clears the freeze and trading window. A successful reset takes effect immediately.
Send POST /v1/account/mmp/reset with a base_asset to reset one underlying, or with an empty body to reset all underlying assets:
A successful reset returns the underlying assets that were reset:
A reset of all underlying assets is applied underlying by underlying, and underlying assets without a configuration are skipped. If any underlying is still inside its 1 second lockout, the call returns HTTP 400 even though others may already have been reset. The error data lists which underlying assets were reset (data.reset) and which were refused (data.refused).
Canceled quotes are not restored automatically. The maker must place new quotes.
Orders
Add "MMP" to flags on a LIMIT order on a perp or dated option market.
The flag is supported on REST, batch and WebSocket order entry. The MMP flag is fixed when the order is placed and is kept when the order is modified. To remove it, cancel and replace the order. You cannot set the flag on block trade legs. Paradex sets it on eligible legs when protect_block_trades is on. See RFQ and block trades.
MMP related cancellation reasons:
WebSocket
Private channel mmp pushes state changes through the standard private subscription envelope.
Every event includes:
TRIGGERED events also include:
CONFIG_UPDATED events also include:
frozen_until on non TRIGGERED events does not indicate whether an underlying is frozen. Track the frozen state from TRIGGERED, UNFROZEN and RESET events, or read is_frozen from GET /v1/account/mmp.
Error codes
Configuration changes return HTTP 503 when market data is temporarily unavailable, and resets return HTTP 503 while the matching engine is unavailable.
Resets are limited to 60 per minute per account, with an additional short burst limit. Exceeding a limit returns HTTP 429.
SDK support
paradex-py 0.7.1 is the first version that supports the MMP order flag. Earlier versions cannot parse MMP flagged orders or protected block trade legs, including your own. Upgrade to 0.7.1 or later before placing MMP orders or opting in to block trade protection.