Margin modes
This page describes the three margin modes of a position and how the chain computes margin in each.
Stable.
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
| Mode | Collateral source | Loss can drain | PM eligible | Liquidation isolation |
|---|---|---|---|---|
| Cross | Free balance, account-wide | Other positions | Yes | Whole-account ladder |
| Isolated | Pre-allocated bucket per asset | Only that bucket | No | Per-asset ladder; max loss = bucket |
| Strict-Iso | Pre-allocated bucket per asset | Only that bucket | No (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:
- Your own leverage preference for the asset, set with
update_leverage. - 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.
- 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_ratioover 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_marginfield 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_leverage | maint_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:
| Field | Value | What 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 |
lev | 20 | The effective leverage that the fill used |
The account-wide scalars read:
| Field | Value | Depth |
|---|---|---|
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:
marginstill reads the leg's own bucket balance, not a ceiling recomputed at run time. If you add to the bucket or let it drain,marginfollows the balance.maint_marginis 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_usedcarry nothing for this leg. An account that holds only this isolated position reportsperp.init_margin: "0"andcross_maintenance_margin_used: "0", and it can still be liquidated. Its ownmarginandmaint_marginare 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
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)
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
| Goal | Mode |
|---|---|
| Maximize capital efficiency on a coherent book | Cross (+ PM) |
| Run multiple uncorrelated strategies under one account | Isolated per strategy, or sub-accounts |
| Keep one risky position from threatening the rest | Isolated (your own choice) |
| Hedge across assets, with netting credit | Cross + PM |
| Trade a long-tail listing that governance has flagged strict-isolated | Strict-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_marginand a positivedelta. - 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
- Portfolio margin: PM and classical math compared
- Tiered liquidation: per-scope ladders
- Sub-accounts: full account-level isolation
update_leverage: the margin mode is theis_isolatedflag on this action. There is no separate margin-mode action
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.