Skip to main content

Margin modes

This page describes the three margin modes of a position and how the chain computes margin in each.

tip

Stable.

Two different things are called a "mode"

This page is about the position setting: where the collateral of one position comes from. The account mode (unified, standard, portfolio) is a separate axis. See account modes.

Overview​

Each asset has one of three modes: Cross, Isolated and Strict-Iso. Cross pools collateral across all your positions. Isolated puts a wall around the margin of each asset. Strict-Iso also excludes that asset from any portfolio-margin netting.

Comparison​

ModeCollateral sourceLoss can drainPM eligibleLiquidation isolation
CrossFree balance, account-wideOther positionsYesWhole-account ladder
IsolatedPre-allocated bucket per assetOnly that bucketNoPer-asset ladder; max loss = bucket
Strict-IsoPre-allocated bucket per assetOnly that bucketNo (excluded even when master is PM-enrolled)Per-asset ladder

In Cross, profitable positions can carry less healthy ones, because your free balance is fungible across the account. In Isolated, a loss on one asset stays inside that asset's bucket.

Margin computation​

All amounts are on the whole-USDC Decimal plane (notional, collateral, margin), not the 1e8 book plane. See mark prices: two price planes.

Initial margin (pre-trade gate)​

An order that opens new exposure must post initial margin:

notional = |px × size| # whole USDC, fractions kept
effective_lev = your leverage for the asset, capped # see the ladder below
required_init = ceil( notional / effective_lev ) + cushion # ceil = conservative
free collateral = cross_account_value
− Σ held_initial_margin # cross perp positions
− Σ spot-margin initial margin # see below
− funding accrued against you # debits only, never credits
reject iff required_init > free collateral

The comparison always runs. An order that grows a position is charged the increase in the whole-USDC figure, and a small increase can round to zero. A zero charge is not a free pass: an account whose free collateral is negative is refused with MARGIN_INSUFFICIENT on every order that opens or extends, however small. Orders that reduce exposure stay admissible.

notional is a whole-USDC amount, and it keeps its fraction. It is not an integer. A price of 61750.25 and a size of 0.001 give a notional of 61.75025.

cushion is a flat 1 USDC, added once for each open cross position. An isolated position adds none. The cushion is a fixed unit, not a rate, so it does not scale with the notional. It covers the whole-USDC rounding that the liquidation engine applies to the same position. So a new position cannot open already inside the engine's reach. A position that you grow later pays the cushion once, at the open. A hedged account holds two positions on one asset, so it pays two.

So each cross position adds ceil(notional / effective_lev) + 1 to the account's held initial margin (perp.init_margin, or total_margin_used on detail: "margin").

Free collateral here is the raw signed gate value. It goes negative when open profit funds the held margin. The account read publishes it clamped, as withdrawable = max(0, free collateral). So an account that reads withdrawable: "0" can still have an order rejected. See account value.

effective_lev resolves in this order, and it is never below 1:

  1. Your own leverage preference for the asset, set with update_leverage.
  2. The market's dynamic-risk override tightens it, when governance has set one. With a margin-tier ladder, the rung that your notional falls into sets the cap, so a larger position gets less leverage.
  3. The market's own maximum bounds it.

update_leverage rejects any request above 100×. A market listed through MIP-3 has a separate cap of 50× when it is deployed, so most markets are well under the 100× ceiling. Read the current value from a market's fields on markets_meta. Do not assume either number.

Rounding is up, so a remainder always tightens the gate. reduce_only orders skip the gate, because they only reduce exposure.

held_initial_margin sums ceil(|entry_notional| / effective_lev(asset)) + 1 over every cross open position. This is the same per-position term, with the cushion. Isolated positions are not in the sum, because their collateral is the separately posted bucket.

This gate applies to every active order path that can open new exposure: submit_order / batch_order (limit, IOC, ALO), scale_order, chase_order, twap_order and an accepted RFQ quote (rfq_accept). Frequent batch auctions (FBA) are not an active exposure path today, because no market has FBA armed.

Maintenance margin and health​

health = account_value − cross_maintenance_margin_used # USDC, signed
tier = the band of account_value / cross_maintenance_margin_used

health is a subtraction, not a ratio. The served health field is the cushion in USDC above the maintenance line. It is positive while the account is clear, and negative when the account is under the line. The ratio of the same two numbers is a separate quantity, and it picks the liquidation band. Do not read one as the other. An account that reads health: "9752" is not at a health of 9752x.

  • account_value = cross_account_value (free balance ± unrealized PnL), signed.
  • cross_maintenance_margin_used = the sum of |entry_notional| × maint_margin_ratio over every held cross position leg, derived from current positions. When portfolio margin is enrolled, it is the PM number (last_computed_pm_cents / 100). An isolated leg is judged against its own bucket and is not in this sum.
  • The chain rounds each leg's term down to whole USDC before the sum. So this account scalar is always a whole number. The per-position maint_margin field keeps its fraction, and the account scalar does not. Do not expect the two to agree to the cent.

The per-asset maintenance ratio is the market's dynamic-risk override, when governance has set one. Otherwise it is the protocol's baseline maintenance ratio, a governed parameter (set_risk_base_maint_ratio). Read the current value from a market's maint_margin_ratio field on markets_meta, and its risk_override when governance has set one. Never assume a fixed percentage. The derived forced-close slippage floor is half the effective ratio, unless an explicit override sets it.

Maintenance is below the initial requirement. So a position can open and then fall to the maintenance floor before liquidation. The ratio account_value / cross_maintenance_margin_used picks the band. At or above 1.1 the account is clear. Below that, the liquidation ladder applies at 1.1 / 1.0 / 0.8 / 0.667. Read those four numbers against the ratio, never against the health field. The 1.1, 0.8 and 0.667 edges are governed values, so read them at run time. Do not pin them.

The arithmetic is exact fixed-point throughout, with no floating point on this path. At extreme account values, the tier decision scales both operands down by the same factor before it divides. The health ratio does not change, so you land in the same tier.

Worked example​

This example takes one order through required_init and maintenance together. It names the account_state field that carries each figure.

A market with a margin-tier ladder bands both numbers from the same notional. Take the example ladder from markets_meta.margin_tiers:

max_open_interest (upper bound, whole USDC)max_leveragemaint_margin_ratio (bps string)
"100000"50×"100" (1.0%)
"500000"20×"250" (2.5%)
"2000000"10×"500" (5.0%)
null (unbounded)5×"1000" (10.0%)

A position's own notional picks the first row, in ascending order, whose max_open_interest is null or strictly greater than that notional. A notional exactly on a bound is not strictly greater, so it selects the next row. A position of exactly 100,000 notional gets the 20× / 2.5% row, not the 50× / 1.0% row.

Opening the position. BTC trades at 61,750.00. You set your own leverage preference for BTC to 20× with update_leverage, and you buy 3.4 BTC:

notional = px × size = 61750.00 × 3.4 = 209950.00
tier = the 500,000 row (209,950 < 500,000, and NOT < 100,000)
effective_lev = min(your 20x preference, the row's 20x cap) = 20
required_init = ceil(notional / effective_lev) + cushion
= ceil(209950.00 / 20) + 1
= ceil(10497.50) + 1
= 10499.00

Before the order, your account reads account_value: "15000" and has no open position. So free collateral is the full 15,000. 10499.00 <= 15000, so the chain admits the order.

After the fill, the leg's own row under clearinghouse_state reads:

FieldValueWhat it is
margin"10499"This leg's initial margin: the figure above, with the cushion
maint_margin"5248.75"209950.00 × 0.025: the same row's ratio, on the same notional. The leg field keeps the fraction
lev20The effective leverage that the fill used

The account-wide scalars read:

FieldValueDepth
perp.init_margin (total_margin_used on detail: "margin")"10499"Both, under two names. This is the account's only position
cross_maintenance_margin_used"5248"detail: "margin" only. 5248.75 rounded down to whole USDC
withdrawable"4501"Both. 15000 − 10499. Entry equals mark, so account_value has not moved
health"9752"account_value − cross_maintenance_margin_used = 15000 − 5248
tier"Safe"The ratio 15000 / 5248 is about 2.86, well clear of the 1.1 yellow-card threshold

The leg reads 5248.75, and the account reads 5248. That is the rounding above, not an error: the account scalar rounds each leg down to whole USDC before it adds them. Size a withdrawal on the account scalar, never on the sum of the leg fields.

Zero notional. An order whose price or size resolves to zero notional needs no initial margin. required_init is 0, and the chain does not test free collateral.

The isolated case. Fund the bucket first. update_isolated_margin with a positive delta moves USDC out of the cross balance into this asset's bucket. That transfer debits cross_account_value directly. So it has already left withdrawable before the order arrives. It never shows up as a held-initial-margin subtrahend, because held_initial_margin sums cross legs only. If you open the same 209,950 notional position isolated instead of cross, the account read differs on this leg only:

  • margin still reads the leg's own bucket balance, not a ceiling recomputed at run time. If you add to the bucket or let it drain, margin follows the balance.
  • maint_margin is the same "5248.75". The ratio and the notional it applies to do not depend on the margin mode.
  • The held initial margin and cross_maintenance_margin_used carry nothing for this leg. An account that holds only this isolated position reports perp.init_margin: "0" and cross_maintenance_margin_used: "0", and it can still be liquidated. Its own margin and maint_margin are the only fields that size it. See held initial margin and cross_maintenance_margin_used.

Cross​

Cross is the default mode.

cross_maintenance_margin_used is the sum of the per-position maintenance requirements across the cross bucket. If portfolio margin is enrolled, it is the PM number.

So a 10% adverse move on BTC reduces account-wide health, even if your ETH position is fine. You can support the BTC position by closing the ETH winner.

Spot margin in the cross account​

A spot-margin position is cross-margined against the same unified USDC account. The chain subtracts its initial-margin requirement from free collateral, as for a perpetual open. Its unrealized PnL and maintenance requirement enter the account-level health decision. Two consequences follow:

  • An open spot-margin position reduces your perpetual margin headroom.
  • A perpetual loss reduces the collateral that backs a spot-margin position. A spot-margin loss can draw on the same account collateral that your perpetual positions use.

There is no per-pair spot-margin collateral bucket and no separate deposit. The one unified USDC account is the collateral. See spot margin.

Isolated​

warning

Implementation gap. The model below is the target behaviour. The pre-trade margin gate implements only the cross, pooled-collateral path today, and the trading path opens every position cross. The chain already reads the position margin_mode field (0 = cross, 1 = isolated) to exclude isolated positions from the cross held-margin sum. A dedicated isolated-margin pre-trade gate, which would check the order's own posted isolated_margin against its notional, is not wired yet.

When you set is_isolated: true for an asset, the protocol moves isolated_amount USDC from the cross balance into a per-position bucket. That position's gain or loss settles into the bucket only:

If position_health falls into a liquidation tier, the per-position ladder fires. The rest of the account does not change.

The chain solves the liq field on an isolated position on this bucket alone. A large cross balance does not push it away, because cross never rescues an isolated bucket. See reading liq.

You can deposit to the bucket or withdraw from it while the position is open:

// add 500 USDC to the isolated bucket on asset 0
{ "type":"update_isolated_margin", "params": { "asset": 0, "delta": "500" } }

delta can be positive, which moves USDC from cross to the bucket. It can be negative, which withdraws USDC from the bucket to cross. The chain rejects a withdrawal that would push the position into a worse tier. To switch the position itself into isolated mode is a separate step: the is_isolated flag on update_leverage. See Transitions.

Strict-Iso​

Strict-Iso has the same wall as Isolated, plus an explicit opt-out from PM scenarios. Even if your master account is enrolled in portfolio margin, a Strict-Iso position:

  • does not contribute to the cross scenario engine
  • does not receive netting credit
  • is margined under the classical model (per-asset baseline)
warning

Not a user choice. Unlike Cross and Isolated, you never request Strict-Iso for your own position. Only the governance market-level flag below puts a position into Strict-Iso. No action moves a position from Isolated into Strict-Iso, or back, at the trader's request.

Market-level strict isolation​

Governance can impose strict isolation at the market level. This is a per-market risk flag that forces every participant in that market into Strict-Iso margin, whatever their own preference. It is not a user toggle. The only way a position becomes Strict-Iso is to open it on a market that already carries this flag.

When a market carries the governance strict-isolated flag:

  • New positions open isolated. At settlement, a fill on that market lands in isolated margin mode, not cross. So its loss stays inside its own bucket, and it earns no portfolio-margin netting credit.
  • Cross opens are rejected. The chain refuses an order that would open or grow a cross position on that market.
  • No switch to cross. The chain rejects a leverage or margin-mode change that targets cross on that market.

A stake-weighted validator vote sets the flag, as a per-market dynamic-risk parameter. The trading path does not set it. The flag lets the protocol ring-fence a market whose risk profile needs it, such as a new, thin or volatile listing. A loss there then cannot drain cross-collateralized positions on other markets. The per-market metadata from /info shows the constraint, so a client can show it before a user tries to open cross.

The onlyIsolated deploy-time flag is fixed once, when a MIP-3 market is created. The governance strict-isolated flag is different: a later vote can turn it on or off on a running market as its risk profile changes.

Choosing a mode​

GoalMode
Maximize capital efficiency on a coherent bookCross (+ PM)
Run multiple uncorrelated strategies under one accountIsolated per strategy, or sub-accounts
Keep one risky position from threatening the restIsolated (your own choice)
Hedge across assets, with netting creditCross + PM
Trade a long-tail listing that governance has flagged strict-isolatedStrict-Iso. Automatic, not requested

For multi-strategy isolation, sub-accounts usually fit better than Isolated. A sub-account isolates the entire account, including agent keys and order space, not only margin.

Transitions​

To switch between Cross and Isolated, use the is_isolated flag of the update_leverage action. There is no separate margin-mode action, and there is no way to request Strict-Iso (see above).

You can change the mode on an asset only while you are flat in it. If you hold any open position (long or short) on that asset, the chain rejects an update_leverage call whose is_isolated differs from the position's current mode. The position keeps its mode until it closes. A change of leverage only (same mode, different leverage) is not affected and is always allowed. When you are flat, a switch from Cross to Isolated takes effect on the next position you open on that asset. To fund its isolated bucket, send a separate update_isolated_margin call.

Liquidation behaviour​

The tiered liquidation ladder applies independently in each scope:

  • Cross: one ladder for the whole account
  • Isolated: one ladder for each isolated asset
  • Strict-Iso: one ladder for each strict-iso asset

A Cross-tier T1 closes positions on the cross book in proportion to their contribution to maintenance. An Isolated T1 closes only the isolated position. T3 backstop and T4 ADL are per-scope. A loss on an isolated position does not claw back from cross winners.

Switch from cross to isolated​

Edge cases​

Show edge cases
  • Auto-deposit on margin add. An isolated position takes a maintenance shortfall from its bucket only. When the bucket is empty, the position liquidates. Cross does not cover an Isolated bucket automatically. Add margin yourself with update_isolated_margin and a positive delta.
  • Closing an Isolated position. A full close releases the bucket back into the cross balance.
  • Mode of a new asset. New positions default to Cross. If governance has flagged the market strict-isolated, every position on it opens in Strict-Iso, whatever you prefer. The market metadata has no per-asset "isolated only" field. The flag lives on the market's governance risk parameters.
  • Isolated under a PM master. PM netting credit applies to Cross positions only. The chain sums Isolated positions classically. A PM-enrolled master with one very large Isolated position and a small Cross book gets almost no PM benefit.

See also​

FAQ​

Show FAQ

Q: Can one asset have both Isolated and Strict-Iso buckets? A: No. The mode is per asset and has one value. The read surface reports it as "cross", "isolated" or "strict_iso".

Q: Does a mode switch cost a trade? A: No. It has no fees and no fills. It is only a state transition.

Q: What happens if I deplete an Isolated bucket below maintenance? A: That asset's liquidation ladder fires. The rest of your account is not affected.

Q: Is auto-deleverage (ADL) cross-scope or per-scope? A: Per-scope. ADL on an Isolated position claws back only from counterparties of that asset. It does not claw back from your Cross book or from other Isolated positions.