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

# Futures market

> Trade the cash-settled cNGN future: discovery, order entry, the fill band, margin, variation margin and settlement

The cNGN future is a dated, cash-settled future on the naira rate. It is quoted the other way round
from [spot](/spot): every price is **cNGN per USDC** (about `1380`) and every size is **USDC of
notional**. A **long** (`buy`) gains when cNGN weakens against the dollar, so more cNGN buys a USDC.
A **short** (`sell`) gains when cNGN strengthens. Read this before integrating against the future.

## What the market is

Each series is a `FutureAsset` series on Base under the **MarginEngine**, the risk manager that
holds margin, settles variation margin and liquidates. Orders are signed for the same TradeModule
as spot, and a wallet has **one trading account** under the MarginEngine for both markets. Spot
balances and futures margin share that account, so cNGN bought on spot counts toward futures margin
at its factor. Your first [deposit](/api-reference/endpoint/deposits) opens the account.

A series is listed as `USDC-cNGN-<DDMONYY>`, named for its expiry date. The series listed now is
`USDC-cNGN-30NOV26`:

* `market = "USDC-cNGN-30NOV26"`: the identifier you pass as `symbol` on REST endpoints and
  `market` on websocket streams
* `contract_type = "future"`, `settlement_type = "cash_settled_future"`
* `base_asset_symbol = "USDC"`, `quote_asset_symbol = "cNGN"`, `display_label = "cNGN per USDC"`
* `expiry_timestamp = 1796047200` (2026-11-30 14:00 UTC), which is also the series' `sub_id`
* `contract_multiplier = "1000"`: one contract is 1,000 USDC of notional
* `ui_size_unit = "USDC of notional (1,000 a contract)"`, `min_size = "1"`, `amount_step = "1"`
* `taker_fee_bps = 25`, `maker_fee_bps = 0`

Discover series from `GET /v1/markets` rather than hard-coding one. A new series gets a new
identifier, a new `sub_id` and its own expiry.

## Discover the market

```bash theme={null}
curl "https://api.numofx.com/v1/markets"
```

A future's entry carries the `ui_*` and `engine_*` contract fields, with
`engine_side_policy = "same_as_ui"`, plus these:

| Field | What it is |
| - | - |
| `asset_address`, `sub_id` | The `FutureAsset` and the series' expiry. Sign them into `action_json.data`. |
| `trade_module_address` | The TradeModule an order's `action_json.module` must name. Spot uses the same one. |
| `quote_asset_address` | The USDC CashAsset. Fees, and any variation margin your cNGN does not cover, are paid from it. |
| `margin_manager_address` | The MarginEngine. Only an account under it can hold the future. |
| `amount_scale` | `1000000000000000` (1e15): what one USDC of size is signed as. |
| `fill_band_enforced` | Always `true`. See [The fill band](#the-fill-band). |
| `fill_band_low`, `fill_band_high` | The band's edges now, in cNGN per USDC. Omitted while the band cannot be read. |

The `future` object is the series as the chain has it. Prices are cNGN per USDC, up to 18 decimals.
An absent optional field could not be read, so treat it as unknown, not as zero.

| Field | Meaning |
| - | - |
| `expiry_timestamp` | Unix seconds the series expires and settles. |
| `last_trade_time` | Unix seconds after which no order is accepted and nothing fills: one hour before expiry. |
| `listed`, `settled` | The series' state on its `FutureAsset`. |
| `trading_open` | Whether the matcher crosses orders. While it is `false`, orders are accepted and rest. |
| `trading_closed_reason` | Why `trading_open` is `false`, for example that the MarginEngine is paused. |
| `mark_price` | The mark that variation margin is settled against. |
| `index_price` | The index the fill band is centred on: the inverse of the on-chain USDC-per-cNGN index. |
| `band_width` | The band's half-width as a fraction of the index: `0.1` is the index ∓ 10%. |
| `band_status` | `ok`, `index_stale` (the index feed is past its heartbeat, so nothing can fill) or `unreadable`. |
| `contract_size_usdc` | `1000`. |
| `updated_at` | When the state was read. |

## Place an order

Futures take raw engine values only. `order_entry_spec` and `ui_intent` are refused on a future.
In the body, `limit_price` is in cNGN per USDC and `desired_amount` in whole USDC of notional, both
human decimals. A long of one contract (1,000 USDC) at 1,380 cNGN per USDC:

```json theme={null}
{
  "side": "buy",
  "asset_address": "0xDCFa4Ee0772647aBd24E8592596b5fe4F001Bc19",
  "sub_id": "1796047200",
  "limit_price": "1380",
  "desired_amount": "1000",
  "worst_fee": "3000000000000000000"
}
```

Sign the same order into `action_json.data`, with two different scales:

* `limitPrice` is the price × 1e18: `1380000000000000000000`.
* `desiredAmount` is the size × `amount_scale` (1e15): `1000000000000000000`, one contract.
* `worstFee` caps the fee **per contract filled**, in USDC × 1e18. The fee is 25 bps of the
  notional, so 2.5 USDC a contract at any price. Sign at least `2500000000000000000`; the example
  signs 30 bps (`3000000000000000000`) to leave headroom.
* `action_json.module` is the market's `trade_module_address`.

A fill carries its price to the chain and moves no quote leg. The account receives the position,
and variation margin settles the gap between the fill price and the mark at once. See
[Variation margin](#variation-margin).

`reduce_only: true` lets an order only shrink the account's position in the series. It is refused
when the account has no position, or when the order is on the same side as the position. The
matcher clamps each fill so it never crosses through zero. It is refused on spot.

See [Authentication and signing](/signing) for building the signed payload, and
[Create order](/api-reference/endpoint/create) for the full request body.

### Orders the venue refuses

The venue refuses a futures order the chain could not settle, rather than resting it as depth no
fill can take:

| Status | When |
| - | - |
| `422` | The signed limit is outside the fill band now. The error starts with `fill_band:` and states the band. |
| `422` | The account is not under the MarginEngine. |
| `422` | `reduce_only` has no position to reduce, or would increase it. |
| `409` | The series is settled or past its last trade time. |
| `503` | The index is stale, or the band, the series or the account's manager could not be read. Retry shortly. |

## The fill band

The chain refuses a fill priced too far from the index. A fill must sit within `band_width` of
`index_price`, so between `fill_band_low` and `fill_band_high`. The band is 10% either side of the
index, and narrows linearly to 1% over the last 14 days before expiry.

The venue applies the same test with the chain's own arithmetic:

* On submission, an order whose signed limit is outside the band now is refused.
* Before each fill, the matcher re-checks the fill price against a band read at most two seconds
  earlier. A resting order the index has moved away from is held back, not cancelled. It fills again
  once the index comes back within reach.
* While the index is stale (`band_status = "index_stale"`), the chain refuses every fill. The venue
  refuses new orders until the index updates.

Liquidations and the close-out at expiry move positions at the mark and are not bounded.

## Margin

Margin is held under the MarginEngine in USDC cash and cNGN. USDC counts at par. cNGN counts at its
base margin factor (`0.5`), valued at the index. Futures margin is charged on the **USDC notional**,
gross, with no offset between series or against other positions:

| Requirement | Rate | What it means |
| - | - | - |
| Initial margin | 25% | What a new or larger position must leave in surplus. Caps leverage at 4x. |
| Maintenance margin | 15% | What an open position must keep. Below it, the account is liquidated through the auction. |

While cNGN trades below its depeg threshold, the MarginEngine adds a penalty to initial margin.

A trade that only reduces a futures position is held to maintenance margin, not initial, so you can
always deleverage. Open interest in each series is capped on chain.

Before submitting a fill, the matcher estimates each account's initial-margin surplus after it.
If an account comes up short, its order is held back for 30 seconds. After three refusals, at least a
minute apart from the first, the order is cancelled with `cancel_reason: "insufficient_margin"`. The
estimate is deliberately generous, so the MarginEngine on chain remains the authority.

## Variation margin

Variation margin (VM) settles in **cNGN**: a move of the mark by `Δmark` cNGN per USDC is
`Δmark × 1,000` cNGN per contract. A long receives it when the mark rises, and a short pays it.

* **At the fill.** A fill is marked to the mark at once. A buy above the mark, or a sell below it,
  pays the gap. [`GET /v1/fills`](/api-reference/endpoint/fills) reports the mark as `mark_price`
  and the VM as `vm_cngn`.
* **At each mark.** The mark is pulled from a signed forward feed at most once an hour. Each update
  may move at most 5%, and must sit inside the band around the index. The MarginEngine settles VM
  before every risk check, and anyone can trigger it for an account.
* **Who pays what.** A payer pays from its cNGN first, then the rest from USDC at the index. A
  winner is paid in cNGN while the engine's pool holds it, then in USDC.

## Settlement

Trading stops at `last_trade_time`, one hour before expiry. From then on only the MarginEngine moves
positions, through liquidations and the close-out.

The settlement price is the time-weighted average of the index over the fixing window, the last
hour before expiry. Each open position is closed out at it, and the final variation margin is paid
as above. If the fixing is incomplete, a fallback price may be set after 24 hours, within 2% of the
samples' average.

## Read a position

The Numo API does not serve futures positions. Read them on chain, where they are public:

* **Position**: `SubAccounts.getBalance(subaccountId, future, subId)` on SubAccounts
  `0x7019244E25FA416e6Ca2ed2F3cA25277aef72843`, where `future` is the market's `asset_address` and
  `subId` its `sub_id`. The result is signed contracts at 18 decimals; positive is a long.
* **Margin**: `MarginEngine.getMargin(subaccountId, true)` for the initial-margin surplus, or `false`
  for maintenance, in USD at 18 decimals, on `margin_manager_address`.

Your fills, with their `mark_price` and `vm_cngn`, are on
[`GET /v1/fills`](/api-reference/endpoint/fills).

## Market data

The book, trades and candles work for a future as for spot: pass the series' `market` as `symbol`
on REST endpoints, or as `market` on the [websocket stream](/api-reference/websocket). Prices are
cNGN per USDC and sizes USDC of notional. The `/v1/integrations/*` endpoints serve spot only and
refuse a future's `ticker_id`.


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