> ## Documentation Index
> Fetch the complete documentation index at: https://docs.d1.exchange/llms.txt
> Use this file to discover all available pages before exploring further.

# Trading Rules

> When you can place orders, sell-to-close, funds and order limits.

Every new order is checked in the same transaction that places it. A refused order creates nothing, and D1 never changes the quantity you asked for to make an order fit.

## Trading availability

Having a key with `mm:trade` does not by itself mean you can place orders. A new order is accepted only when **all** of these hold:

* the key is active, carries `mm:trade`, and was issued by D1 as a trading key;
* your account is active, not suspended;
* D1 has enabled trading for your account;
* trading through the Market Maker API is switched on at D1.

D1 enables trading for an account during onboarding. Enabling it requires, among other checks, an available USDC balance of at least a minimum set by D1. Ask D1 for the current figure.

### What you see when trading is unavailable

`GET /mm/v1/status` tells you whether a new order would be accepted right now:

```json theme={null}
{
  "capabilities": { "read": true, "trade": false, "writeOptions": false },
  "trading": { "available": false, "reason": "TRADING_DISABLED", "sellPolicy": "CLOSE_ONLY" }
}
```

A placement in that state is refused:

| Cause | Response to `POST /mm/v1/orders` |
| - | - |
| Trading not enabled for your account, or switched off at D1 | `403 TRADING_DISABLED` |
| Account suspended | `403 DEALER_SUSPENDED` |
| Key without `mm:trade`, or not issued as a trading key | `403 INSUFFICIENT_SCOPE` |

```json theme={null}
{ "error": "TRADING_DISABLED", "message": "Trading is not enabled for this dealer." }
```

Even while trading is unavailable you can still:

* read everything with `mm:read`, unless your account is suspended;
* [cancel and cancel-all](https://docs.d1.exchange/market-makers/orders.md#cancellation-stays-available);
* retry an earlier placement with the same `clientOrderId` and get the existing order back.

Availability can change at any time, so treat `TRADING_DISABLED` as a normal state. Stop placing, cancel your resting orders if your strategy needs that, keep reconciling, and poll `GET /mm/v1/status` until `trading.available` is `true` again.

## Sell-to-close

External MM V1 does **not** support option writing. You can never create or increase a net short position through this API.

* **`BUY`** acquires a long position. It is limited only by your funds and [order limits](#order-limits).
* **`SELL`** is sell-to-close. You can sell only contracts you hold long and have not already committed to another resting `SELL`.

When you place a `SELL`, D1 sets aside that quantity of your long position for the order. That quantity cannot back a second `SELL` until the order fills or is cancelled.

```text theme={null}
Long position: 10 contracts, no resting SELL orders

SELL 6   → accepted. 6 contracts are set aside for this order.
           Unreserved long: 4

SELL 5   → refused: 422 INSUFFICIENT_POSITION
           (5 is more than the 4 unreserved contracts)

SELL 4   → accepted. Unreserved long: 0

cancel the SELL 6  → the 6 contracts are released. Unreserved long: 6
```

The refusal looks like this:

```json theme={null}
{ "error": "INSUFFICIENT_POSITION", "message": "The order exceeds the unreserved long position. Option writing is not available." }
```

D1 checks this when the order is placed **and again on every fill**, in the transaction that executes it. A fill can never take your position in a market below zero.

To calculate how much you can still sell in a market, take your long `quantity` from `GET /mm/v1/positions` and subtract the `remainingQuantity` of your resting `SELL` orders in that market.

`GET /mm/v1/status` reports this rule as `trading.sellPolicy: "CLOSE_ONLY"` and `capabilities.writeOptions: false`.

## Funds

A `BUY` sets aside its full premium at the limit price from your available USDC: `price × quantity`, or `price × quantity × contractSize` for markets quoted per underlying unit. If your available balance does not cover it, the order is refused with `422 INSUFFICIENT_FUNDS`.

The amount set aside appears in `reserved` in `GET /mm/v1/balances`. It is paid out as the order fills, and whatever is left is released when the order is filled or cancelled. A `SELL` does not set aside USDC.

## Order limits

Each account has three limits on its resting orders. `GET /mm/v1/status` returns the values that apply to you under `limits`:

```json theme={null}
{
  "limits": {
    "maxOpenExposure": { "units": "…", "decimals": 6 },
    "maxRestingOrders": 128,
    "maxRestingOrdersPerInstrument": 8
  }
}
```

| Limit | `limit` value in the error | Rule |
| - | - | - |
| Resting orders | `MAX_RESTING_ORDERS` | At most `maxRestingOrders` resting orders across all markets. Currently 128. |
| Resting orders per market | `MAX_RESTING_ORDERS_PER_INSTRUMENT` | At most `maxRestingOrdersPerInstrument` resting orders in any one market. Currently 8. |
| Open-order exposure | `MAX_OPEN_EXPOSURE` | The total notional of your resting orders cannot exceed `maxOpenExposure` (USDC, `decimals: 6`). Set by D1 and may differ between environments. |

An order that would break a limit is refused, and the body names the limit:

```json theme={null}
{ "error": "RISK_LIMIT", "message": "The order would exceed an External MM limit.", "limit": "MAX_OPEN_EXPOSURE" }
```

Read the limits from `GET /mm/v1/status` instead of hard-coding them. D1 may change them, and `maxOpenExposure` is `null` if no exposure limit is configured, in which case new orders are refused with `TRADING_DISABLED`.

### What open-order exposure means

Open-order exposure is the premium your resting orders would trade if they all filled at their own limit prices. It counts **both sides** and **every market**:

```text theme={null}
exposure = Σ over your resting orders of  price × remainingQuantity
           (× contractSize for markets quoted per underlying unit)
```

For example, with `QUOTE_PER_CONTRACT` markets:

```text theme={null}
resting BUY  3 @ 100   →  300 USDC
resting SELL 2 @ 110   →  220 USDC
                            ───
exposure                   520 USDC
```

When you place an order, D1 adds the new order's **full** quantity at its limit price, before any matching, and refuses it if the total would exceed `maxOpenExposure`. This applies even if the order would fill immediately. The same before-matching rule applies to the order counts: a new order needs room to rest, even if it would fill at once.

Exposure goes down when orders fill or are cancelled. It is based only on your order prices. It is not a measure of your position value, margin or P\&L.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.