# Liquidation logic

#### Liquidation Trigger Condition

Accounts are liquidated when equity falls below maintenance:

```rust
fn is_liquidatable(account, markets) -> bool {
    let equity = calculate_equity(account, markets)
    let maintenance = calculate_maintenance_margin(account, markets)
    let reserved = account.reserved_margin.max(0)

    equity < maintenance + reserved
}
```

The inclusion of `reserved_margin` ensures pending orders don't create hidden risk.

#### Liquidation Detection Process

The `check_liquidations` function scans all accounts:

```rust
fn check_liquidations(state, mark_prices) -> Vec<Order> {
    let mut liquidation_orders = Vec::new()
    let mut liquidation_id = 1 << 63  // Bit 63 marks liquidation orders

    for (account_id, account) in state.margin_accounts {
        let equity = calculate_equity(account, markets)
        let maintenance = calculate_maintenance_margin(account, markets)

        if equity >= maintenance + reserved {
            continue  // Account is healthy
        }

        // Generate liquidation orders for all positions
        for (market_id, position) in account.positions {
            if position.base_position == 0 {
                continue
            }

            liquidation_orders.push(Order {
                order_id: OrderId(liquidation_id),
                market_id,
                account_id,
                side: if position.base_position > 0 { Sell } else { Buy },
                price: mark_price,
                quantity: abs(position.base_position),
                timestamp: mark_price_timestamp,
            })

            liquidation_id += 1
        }
    }

    liquidation_orders
}
```

#### Liquidation Order Properties

| Property  | Value                | Reason                                |
| --------- | -------------------- | ------------------------------------- |
| Order ID  | `≥ 1 << 63`          | Bit 63 set to identify as liquidation |
| Side      | Opposite to position | Closes the position                   |
| Price     | Current mark price   | Market order semantics                |
| Quantity  | Full position size   | Complete liquidation                  |
| Timestamp | Mark price timestamp | Deterministic ordering                |

#### Liquidation Execution Flow

```
1. Mark price update received
2. check_liquidations() scans all accounts
3. Liquidation orders generated for underwater accounts
4. Orders inserted into matching engine
5. Normal matching rules apply
6. Fills update position and collateral
7. If partially filled, position reduced proportionally
```

#### PnL Realization on Liquidation

When liquidation orders fill, PnL is realized:

```rust
// For a long being liquidated (selling)
pnl_per_unit = exit_price - entry_price
realized_pnl = pnl_per_unit × quantity

// For a short being liquidated (buying)
pnl_per_unit = entry_price - exit_price
realized_pnl = pnl_per_unit × quantity
```

The `collateral` balance is adjusted by `realized_pnl`, which may be negative.

#### Fill Classification

The system classifies each fill to determine accounting treatment:

```rust
enum PositionFillEffect {
    Opening,   // Increasing position or opening new
    Reducing,  // Partially closing position
    Flipping,  // Closing and reversing direction
}

fn classify_fill(base_position, side, quantity) -> PositionFillEffect {
    if base_position == 0 {
        return Opening
    }

    let direction = if side == Buy { 1 } else { -1 }

    if base_position.signum() == direction {
        return Opening  // Same direction = adding
    }

    if quantity > abs(base_position) {
        return Flipping  // Exceeds position = flip
    }

    return Reducing  // Partial close
}
```


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs-v2.fermilabs.xyz/trading/liquidation-logic.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
