> For the complete documentation index, see [llms.txt](https://docs.nexus.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nexus.xyz/trading/trading/perpetuals/liquidations.md).

# Liquidations

When a position is liquidated, how to compute your own liquidation price, the order the engine sends, and the waterfall that absorbs a shortfall.

Liquidation protects the venue from insolvency. When an account can no longer support its open positions, the risk engine closes them and, if the close leaves a shortfall, absorbs that shortfall through a fixed waterfall: insurance fund first, then profitable counterparties, then a market halt.

The exchange engine enforces everything on this page. The formal derivation, with numbered formulas, is in the [Math Engine's liquidation chapter](https://docs.nexus.xyz/math-engine/liquidation-engine). The formula labels below, such as (L.1), (L.4) and (L.7), refer to it.

### The trigger

An account liquidates when its equity falls to **or below** its total maintenance margin:

```
liquidate  ⟺  equity ≤ Σ maintenance_margin                            (L.4)
```

**The threshold is inclusive.** Equity exactly equal to maintenance liquidates. An account with no open positions never liquidates.

Both sides are recomputed from the current mark on every evaluation:

```
equity             = collateral + Σ size × (mark − entry) × direction   (L.1, L.2)
maintenance_margin = size × mark × maintenance_margin_rate              (L.3)
```

Three details change the answer in practice:

* **Equity is funding-aware.** Accrued funding you are owed counts toward equity, and funding you owe counts against it. An account that looks underwater before funding may be healthy after it, and the reverse.
* **Maintenance margin moves with the mark.** It is a fraction of notional at the *current* mark, not at entry. A falling mark therefore reduces the requirement on a long at the same time as it reduces equity. Both sides move, and only the gap matters.
* **A mark of zero or below is treated as absent** and the entry price is substituted, making that position's unrealized PnL exactly zero. This is the stateless-boot sentinel for "no oracle push yet". Without it, a long would show a catastrophic phantom loss against a zero mark.

### When liquidation pauses

Liquidation depends on a trustworthy mark, so the venue stops liquidating when it does not have one.

If no accepted price update arrives for a market within `oracle_staleness_seconds`, which is **30 seconds on every listed market**, that market's stale policy takes effect. The default, and the policy every listed market runs, **fails closed**:

| While the mark is stale              |                                                                |
| ------------------------------------ | -------------------------------------------------------------- |
| Liquidations                         | **Paused**                                                     |
| Risk-increasing orders               | **Rejected**                                                   |
| Risk-reducing and reduce-only orders | Still accepted                                                 |
| Liquidation orders already in flight | Still accepted                                                 |
| Recovery                             | **Automatic** on the next fresh price, with no operator action |

Two things follow for a trader. You **cannot be liquidated on a frozen mark**. A stale feed must not liquidate anyone against a price that may no longer be real. You also **cannot add exposure** in that market while it is stale, because an account that cannot be liquidated must not be allowed to grow.

This is distinct from a halt. A stale market recovers by itself when prices resume; a halted market requires an operator to resume it.

### Computing your own liquidation price

The venue does not always give you this number, so it helps to compute it yourself. See [Why the API may not give you a liquidation price](#why-the-api-may-not-give-you-a-liquidation-price).

Start from the **bankruptcy price**, the mark at which the position's loss exactly exhausts the collateral backing it:

```
p_bankruptcy = entry − direction × collateral / size                    (L.7)
```

`direction` is `+1` for a long and `−1` for a short. Solving (L.4) at equality for the mark gives the **liquidation price**, the mark at which the trigger fires:

```
p_liquidation = p_bankruptcy / (1 − direction × maintenance_margin_rate)
```

For a long the liquidation price sits **above** the bankruptcy price: you are liquidated while collateral remains, and the gap between the two prices is the cushion the maintenance margin rate buys. For a short the order reverses. The Math Engine states this as an invariant: `p_bankruptcy < p_liquidation < mark` for a healthy long.

> **This closed form is exact for a single position.** For a cross-margin account holding several positions, no per-position liquidation price exists: equity depends on every market's mark at once, so a position can be liquidated by a move in a market you are not even looking at. Only the account-level condition (L.4) is well defined. Use `POST /orders/preview` for a multi-position projection rather than applying the formula per position.

**Leverage does not appear in the formula.** The liquidation price is set by the *maintenance* margin rate and your collateral, and leverage touches neither. Raising leverage lets you open a larger position with the same collateral, and that *larger* position has its own liquidation price. Leverage never moves the liquidation price of a position you already hold. See [Margining](/trading/trading/perpetuals/margining.md).

### Worked example

This example uses a `BTC-USDX-PERP` position and that market's parameters: `initial_margin_rate = 0.02`, `maintenance_margin_rate = 0.01`, `tick_size = 0.5`, `liquidation_sweep_depth_bps = 500`.

> **Margin rates are per-market configuration and are tuned between releases.** Read the ones that apply to you from `GET /markets/{market_id}/risk-params` rather than from this example. The arithmetic below is the method, not a quote.

You deposit **2,000 USDX** and open **1 BTC long at 60,000**.

| Step                          | Value                                 |
| ----------------------------- | ------------------------------------- |
| Initial margin required       | `1 × 60,000 × 0.02` = **1,200.00**    |
| Free collateral after opening | `2,000 − 1,200` = **800.00**          |
| Bankruptcy price (L.7)        | `60,000 − 2,000 / 1` = **58,000.00**  |
| Liquidation price             | `58,000 / (1 − 0.01)` = **58,585.86** |

Checking the trigger at that mark: unrealized PnL is `1 × (58,585.86 − 60,000)` = **−1,414.14**, so equity is `2,000 − 1,414.14` = **585.86**, and maintenance margin is `1 × 58,585.86 × 0.01` = **585.86**. Equity equals maintenance exactly, and the threshold is inclusive, so the position liquidates at that mark, not one tick lower.

The bankruptcy price does **not** depend on the maintenance margin rate. Your collateral alone sets it. The rate only decides how far above it the liquidation fires. A higher maintenance rate moves the liquidation price further from the bankruptcy price, and therefore further into your position.

All **2,000 USDX** of collateral backs the position, not only the 1,200 of initial margin. That is what cross margin means. The free 800 is cushion for this position, which is why the bankruptcy price is 58,000 rather than 58,800.

### The order the engine sends

Liquidation closes the position against the order book, in two bounded attempts.

1. **Primary order.** A **reduce-only limit IOC** at the bankruptcy price, tick-aligned toward executability (a sell rounds down, conceding at most one tick). Because it is a limit order, it fills **at bankruptcy-or-better only**. A fill better than the bound produces spread profit, which accrues to the insurance fund.
2. **Backstop sweep.** If the primary order expires with quantity unfilled, the engine sends **exactly one** follow-up limit IOC at `mark × (1 ∓ liquidation_sweep_depth_bps / 10,000)`. On every listed market that depth is **500 bps**, so the sweep reaches 5% through the mark and no further. This caps the liquidation's realized slippage at the per-market policy depth.

Continuing the example, with the mark at 58,585.86:

| Attempt | Side | Quantity  | Limit price                                                       |
| ------- | ---- | --------- | ----------------------------------------------------------------- |
| Primary | Sell | 1 BTC     | **58,000.0** (the bankruptcy price, already tick-aligned)         |
| Sweep   | Sell | remainder | `58,585.86 × 0.95` = 55,656.57, tick-aligned down to **55,656.5** |

Fills worse than the bankruptcy price can only come from the sweep. They become **bad debt** and enter the waterfall below. The sweep is suppressed entirely when the depth is non-positive, nothing remains to close, or the market has no usable mark.

**Sizing.** Every listed market runs in **Full** mode today: the liquidation closes the entire position. The engine also implements **Partial** mode, which closes only the excess above the largest size the collateral supports at 1.5× the initial margin rate, leaving a healthy remainder ((L.10), (L.11)). No listed market is configured for it.

### What absorbs a shortfall

If the close leaves the account with a cash deficit, the waterfall runs in a fixed order.

| Rung | Absorbs                                                                                                                                                                              | Exhausted or unavailable →                                                            |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| 1    | Spread profit from better-than-bankruptcy fills                                                                                                                                      | credited to the insurance fund                                                        |
| 2    | **Insurance fund**. See the [Math Engine's insurance-fund chapter](https://docs.nexus.xyz/math-engine/insurance-fund)                                                                | next rung                                                                             |
| 3    | **Auto-deleveraging** against profitable counterparties                                                                                                                              | next rung                                                                             |
| 4    | **Market halt**: `adl_exhausted` when the counterparty pool cannot cover the residual position; `uncovered_system_loss` when the deficit is cash with no position left to deleverage | recorded as an explicit ledger liability, never minted or discarded; resume is manual |

A halted market stops trading until an operator resumes it. `uncovered_system_loss` also requires the outstanding loss to be cleared before resumption. These are 2 of the **7** reasons a market can halt; the others are operator action, a mid-fill position-apply failure, the [max-move circuit breaker](/trading/trading/perpetuals/discovery-bounds.md), a risk-actor restart the supervisor could not prove current, and a market-parameter divergence after commit.

### Auto-deleveraging

When the insurance fund cannot absorb the deficit, the residual position is closed against profitable counterparties on the other side. This is live on every listed market.

**To be selected you must hold a position that is** in the same market, on the opposite side to the bankrupt position, and **profitable at the mark**. A position at a loss is never deleveraged. Reserved system accounts are never selected, and the search is bounded to accounts with live exposure in that market.

Ranking is by a priority score, descending, with exact ties broken on ascending account identifier so the ordering is deterministic under replay:

```
priority_score = pnl_percent × leverage                                 (L.12)

pnl_percent = unrealized_pnl / (size × entry)
leverage    = size × mark / backing_equity
```

**Leverage is your own, measured against the equity that backs the position.** For a cross-margin position, that is your account equity (L.1, L.2): collateral plus every cross position at its own mark, funding included. A loss in another market therefore moves you up the queue, but auto-deleveraging still closes only the position in the failing market. For an isolated position, it is the position's allocated margin plus its own unrealized PnL, funding included. A position whose backing equity is zero or negative ranks first.

**Position size does not determine your place in the queue.** Percentage profit does, multiplied by leverage. Take two cross-margin shorts at a mark of 58,585.86 on `BTC-USDX-PERP`, each the only position on its account:

| Counterparty | Size    | Entry  | Collateral | Unrealized PnL | PnL % | Leverage | Score      |
| ------------ | ------- | ------ | ---------- | -------------- | ----- | -------- | ---------- |
| **A**        | 0.5 BTC | 61,000 | 10,000     | 1,207.07       | 3.96% | 2.61×    | 0.1034     |
| **B**        | 2 BTC   | 59,000 | 3,000      | 828.28         | 0.70% | 30.61×   | **0.2148** |

A's percentage return is more than five times B's, but B is deleveraged **first**. B backs four times A's notional with about a third of A's equity, so it is nearly twelve times as levered.

Both are shorts, and both must be **profitable at the mark** to be admissible at all. A short with an entry *below* 58,585.86 is at a loss here and is never selected, however large or however levered.

**What you give up is capped at your unrealized profit** on the deleveraged portion. That profit covers the bad debt. A counterparty is also screened against the price it will be closed at, not only the mark it was scored on, so a candidate whose position would settle at a loss is excluded rather than deleveraged into one.

Query it: `GET /markets/{market_id}/adl-events` for a market's history, `GET /account/{address}/adl-history` for your own.

### Why the API may not give you a liquidation price

The `Position` object carries a `liquidationPrice` field, and it is frequently `null`. When it is, a sibling field says why.

* **`GET /positions` is served by the indexer**, which does not mirror margin-module state. On that read `liquidationPrice` is `null` and `liquidationPrice_error` is **always** `margin_state_not_mirrored`. The same applies to `leverage`, which is currently always `null`.
* **`GET /account` is relayed from the engine**, which does hold margin state, and does not carry the error sibling at all.
* **`POST /orders/preview`** returns `projected_post_trade_liquidation_price` alongside `required_initial_margin` and `projected_post_trade_equity`, projected for an order before you submit it.

Design your client around two consequences. A `null` liquidation price means *not computed*, never *cannot be liquidated*, so do not treat it as safety. And **a zero is a real price**. A position whose liquidation price is zero effectively cannot be liquidated. The field no longer overloads `"0"` to mean absence, so the two cases are now distinguishable.

Do not derive leverage from `initialMargin`. That collapses to `1 / initial_margin_rate`, a per-market constant, not your actual leverage.

### Position takeover

The engine implements an alternative model in which a liquidated position transfers atomically, in whole, to a reserved per-market liquidation account rather than being closed against the book inside the liquidation call. It is gated per risk class by `TAKEOVER_ENABLED_CLASSES`.

**No environment enables it.** All 32 configured markets are risk class `core`, the variable is set in no deployment manifest, and unset means no class is enabled. Every liquidation today therefore runs the book-close path described above. This page will change when takeover is armed.

> **The liquidation account is an internal engine account,** one per market, derived under a reserved identifier prefix. It is part of the exchange engine, not an external address, and it is never selected as an [auto-deleveraging](#auto-deleveraging) counterparty. See [Architecture](/overview/architecture.md).

### Reducing your risk of liquidation

* **Add collateral.** Every unit of free collateral moves the bankruptcy price, and therefore the liquidation price, further away.
* **Reduce size.** Closing part of a position lowers the maintenance requirement proportionally.
* **Watch the mark, not the last trade.** Liquidation is evaluated against the [mark price](/trading/trading/perpetuals/price-oracles.md), which is 95% index by construction. A thin-book print does not liquidate you; a move in the index does.
* **Preview before submitting.** `POST /orders/preview` reports the projected liquidation price and post-trade equity for an order without placing it.
* **Remember that cross margin is shared.** One collateral pool backs every position. A loss in one market consumes the cushion under all of them.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.nexus.xyz/trading/trading/perpetuals/liquidations.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
