Runbook: Delisting a Product

Last updated: 2026-06-09

Delisting is not a single command. It is a coordinated wind-down: communicate, discourage new risk, halt trading, run a final settlement, flatten remaining positions, and terminate the instrument in EP3. The instrument's historical data (trades, transactions, funding) is preserved; the Postgres instruments row is never deleted.

Note — tooling status: an instrument migrator (delist → re-create → position-transfer, with UAT probe and order-gateway audit tagging) is planned as the follow-up to the routing-key planner (PR #2085, A-3454). Until it lands, the position wind-down steps below are manual.

Phase 1 — Decision and communication

  1. Set the timeline. The business owner sets, at minimum: the announcement date, the last trading day/time, and the final settlement time. Customers with open positions need enough notice to wind down — for anything with real open interest, two weeks is a reasonable floor.

  2. Notify customers and MMs. Announce via the public changelog and direct outreach to every account holding an open position or active quoting obligation in the symbol. State explicitly what happens to positions still open at final settlement (cash settlement at the final settlement price).

Phase 2 — Wind-down period

  1. Discourage new risk. There is no automated close-only mode today. The available lever is margin: raise initial_margin_pct on the instrument (leave maintenance_margin_pct so existing positions aren't force-liquidated) to make new position-opening expensive while leaving closing unaffected in practice.

  2. Monitor open interest. Track open interest daily through the wind-down window. Chase down the long tail of position holders directly — the goal is zero open interest before final settlement, so forced cash settlement is the exception, not the mechanism.

Phase 3 — Last trading day

  1. Halt trading. At the announced last trading time, transition the instrument out of Open in EP3 (Halted or Closed). Resting orders are no longer matchable and new orders are rejected. Verify via the order gateway that order entry for the symbol fails cleanly.

  2. Run final settlement. Run the final settlement/funding cycle at the announced time and record the final settlement price. This is the price at which any residual positions are cash-settled.

  3. Flatten residual positions. For any account still holding a position after final settlement, book offsetting cash-settlement transactions at the final settlement price via admin tooling, bringing every account's position in the symbol to zero. Reconcile: total long = total short = 0 across all accounts before proceeding.

Phase 4 — Terminate and clean up

  1. Terminate the instrument in EP3. Transition the instrument to Expired or Terminated (both render as Delisted). Market data publication stops and the instrument leaves tradable listings.

  2. Remove from the instrument spec. Remove (or comment out) the product from instruments.yml in each environment's config repository so a future instruments sync doesn't attempt to recreate or reconcile it. Do not delete the Postgres instruments row — historical transactions and funding records reference it.

  3. Stop settlement-engine work for the symbol. Confirm the settlement engine no longer schedules funding runs for the symbol, and stop extending its cme_future_roll_schedule rows (existing rows can remain).

  4. Update documentation. Remove the contract from the public contract-specs page, note the delisting in the public changelog, and keep the instrument ID reserved in ax_sdk_internal::constants::INSTRUMENT_IDS — IDs are never reused.

Phase 5 — Post-delist verification

  1. Order entry for the symbol is rejected on all gateways.
  2. No funding or settlement runs execute for the symbol after termination.
  3. All accounts show zero position in the symbol; final cash settlements reconcile against the final settlement price.
  4. GUI shows the product as delisted; historical data (trades, funding history) remains queryable.