Skip to main content
Self-trade prevention (STP) applies across your wallet family: accounts sharing your wallet address, including across applications. Those accounts cannot trade with one another. A sub-account registered under a different wallet address belongs to a separate family.The incoming order’s mode governs the match. By default, Monaco cancels your resting order and continues matching the incoming order against other liquidity.

Choose A Mode

Default behaviorYour incoming buy reaches your own resting sell

The resting sell is cancelled. The buy continues looking for other liquidity. The two orders do not trade with one another.

Which Setting Applies?

The priority is:
  1. The mode specified on the incoming order.
  2. Your configured wallet default.
  3. The platform default: Cancel maker.
A replacement is a new order, so its mode must be specified again to retain a per-order setting. Wallet defaults apply to every order in the family that does not specify a mode.

Exceptions To Understand

  • FOK can still remove your quotes. Under Cancel maker, your own quotes are cancelled before the third-party depth check. If the FOK cannot fill, those cancellations can still stand.
  • Under Cancel taker or Skip, a self-cross in the fill path cancels the whole FOK. FOK with Cancel both and a self-cross is rejected at placement.
  • A zero-fill market order refused before sequencing does not commit a simulated maker cancellation. Do not infer a quote was removed solely from the incoming order’s failure.
  • Post-only orders reject if they would cross before STP is consulted, regardless of who owns the opposing liquidity.
  • Liquidations and auto-deleveraging do not apply STP. A liquidation slice fills against your own resting orders in other risk buckets and sub-accounts in price order, like anyone else’s, and never cancels them; ADL fills no resting orders and can close an opposing position in your other risk buckets. User settings cannot obstruct either.

Identifying A Prevented Trade

STP cancellations carry a self-trade-prevention reason and the counterparty order ID. They have cancelled status, which differs from accepted zero-fill IOC/FOK rejections for insufficient qualifying liquidity.The full reference preserves the exact status, event, movement-channel, and configuration fields for integrations.
Self-trade prevention (STP) decides what happens when your incoming order would match one of your own resting orders. Most venues fix a single behavior — typically cancelling the resting order — or offer a limited subset. Monaco exposes all four behaviors, selectable per order and configurable as a default per wallet:SKIP in particular is rare among venues: it lets a market maker’s incoming flow coexist with its own quotes instead of destroying them.

How it resolves

  • The incoming (taker) order’s mode governs the whole match. Modes carried by resting orders are never consulted — the same convention as every major venue.
  • “Your own” means your wallet family: every account under your wallet address, across applications, including every margin sub-account you open (they all belong to your user). Two accounts under the same wallet address cannot trade with each other. A master-account sub-account linked under a different wallet address is its own family.
  • Resolution order: the order’s own selfTradePreventionMode field if present → your wallet’s configured default → the platform default (CANCEL_MAKER).
  • Orders cancelled by STP are announced like any other cancellation, with terminalReason: SELF_TRADE_PREVENTION on the WebSocket event and on later order reads; the event also carries stpCounterpartyOrderId identifying the order on the other side, so the cause is always attributable.
  • An STP outcome is a CANCELLED order even when nothing filled — deliberately distinct from an accepted zero-fill IOC/FOK, which is REJECTED for want of qualifying liquidity — for a FOK that means depth that cannot cover the full quantity, whose candidate fills are then discarded, not necessarily an empty book. (A plain zero-fill MARKET submit never reaches either outcome: it is refused before acceptance and emits no order event.) Status alone separates “my own prevention ended this” from “there was not enough qualifying liquidity”, with no message parsing.
  • A swept spot maker also receives the movements-channel user_movement frame for its lock release, exactly as a user-initiated cancel produces. A swept margin maker receives none: its reserve release moves no user_balances leg — and a user cancel of a margin order emits none either, so the two stay consistent. Do not wait on a movements frame for a margin order.

Setting it

  • Per order: pass selfTradePreventionMode on create, replace, or batch items. A replacement is a new order — restate the field to keep it.
  • Per wallet: GET/PUT /api/v1/accounts/self-trade-prevention reads and sets your wallet’s default (applies to every order from your wallet family that names no per-order mode).

Edge semantics worth knowing

  • Fill-or-kill: under CANCEL_TAKER or SKIP, any self-cross in the fill path cancels the whole FOK; under CANCEL_MAKER, your makers cancel first and the order then fills or kills against the rest; a FOK + CANCEL_BOTH order with a self-cross in its fill path is rejected at placement with SELF_TRADE_NOT_ALLOWED — all-or-none contradicts the partial outcomes CANCEL_BOTH produces.
  • A killed FOK still cancels your makers. Under CANCEL_MAKER the sufficiency check runs on third-party depth only — your own orders are cancelled first and never counted as available liquidity. If that depth cannot fill the order the FOK is rejected and those cancellations stand: you lose the quotes and get nothing. (FOK is a LIMIT-only time in force — a MARKET order carrying any timeInForce is rejected outright.)
  • A rejected taker does not mean your quote was swept. The cancellation is decided during simulation and commits only if the order is sequenced. A zero-fill MARKET order whose only in-band depth was your own resting order is rejected for insufficient liquidity before the sequence is allocated, so the simulated cancellation is discarded and your resting order survives. Reconcile against the order stream rather than inferring from the taker’s result.
  • Post-only orders reject with POST_ONLY_WOULD_CROSS before STP is ever consulted, whoever owns the crossing liquidity.
  • Liquidations and auto-deleveraging apply no self-trade prevention at all, whatever your configured mode. A liquidation slice matches your own resting orders — from your other risk buckets and sub-accounts — in price order exactly as it matches anyone else’s, counts them as available depth, and never cancels them for crossing. ADL does not trade against the book: it closes opposing positions directly at the pinned price, and a position your other risk buckets hold is as eligible as anyone else’s. It never fills your resting orders, but when it fully closes a position, that risk bucket’s resting reduce-only orders on the pair are cancelled with terminal reason AUTO_DELEVERAGING. User configuration can never impede a forced close. (The liquidated risk bucket’s own resting orders are cancelled before it is liquidated, with terminal reason LIQUIDATION.)