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

# Self-Trade Prevention

> Choose what happens when an incoming order reaches your own resting order.

export const LearnStyles = () => {
  useEffect(() => {
    const revealReference = () => {
      let id;
      try {
        id = decodeURIComponent(window.location.hash.slice(1));
      } catch {
        return;
      }
      if (!id) return;
      const target = document.getElementById(id);
      if (!target) return;
      let opened = false;
      for (let parent = target.parentElement; parent; parent = parent.parentElement) {
        if (parent.tagName === "DETAILS" && !parent.open) {
          parent.open = true;
          opened = true;
        }
      }
      if (opened) target.scrollIntoView({
        block: "start"
      });
    };
    const frame = requestAnimationFrame(revealReference);
    window.addEventListener("hashchange", revealReference);
    return () => {
      cancelAnimationFrame(frame);
      window.removeEventListener("hashchange", revealReference);
    };
  }, []);
  return <style>{`
.monaco-learn {
  --bg:#fff;
  --fg:#18261e;
  --body:#465149;
  --muted:#69756d;
  --line:#dce3dd;
  --accent:#233329;
  --callout:#f0f5ef;
  --amber:#9a6418;
}
.dark .monaco-learn {
  --bg:#0e1410;
  --fg:#edf3ed;
  --body:#c3cdc5;
  --muted:#9daa9f;
  --line:#344239;
  --accent:#c4dfc8;
  --callout:#1c2b20;
  --amber:#edc680;
}
.monaco-learn [data-as=p] {
  display: block;
  margin: 1.25em 0;
}
.monaco-learn .small-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}
.monaco-learn .example,
.monaco-learn .formula {
  margin: 24px 0;
  padding: 20px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--callout);
}
.monaco-learn .example strong {
  display: block;
  font-size: 19px;
  color: var(--fg);
}
.monaco-learn .example p {
  margin: 10px 0 0;
}
.monaco-learn .formula {
  font-family: monospace;
  overflow-x: auto;
}
.monaco-learn .callout {
  margin: 24px 0;
  padding: 18px 20px;
  border-left: 3px solid var(--accent);
  background: var(--callout);
  border-radius: 0 8px 8px 0;
}
.monaco-learn .callout.warning {
  border-color: var(--amber);
}
.monaco-learn .primary-link {
  display: inline-block;
  padding: 10px 18px;
  border-radius: 8px;
  background: #233329;
  color: white;
  text-decoration: none;
}
.monaco-learn .account-cards,
.monaco-learn .referral-levels {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin: 24px 0;
}
.monaco-learn .account-cards > div,
.monaco-learn .referral-levels > div {
  padding: 18px;
  border: 1px solid var(--line);
  border-radius: 10px;
}
.monaco-learn .account-cards h3 {
  margin: 0 0 8px;
  font-size: 16px;
}
.monaco-learn .account-cards p {
  margin: 0;
  font-size: 14px;
}
.monaco-learn .referral-levels {
  text-align: center;
}
.monaco-learn .referral-levels strong {
  display: block;
  font-size: 32px;
  color: var(--accent);
}
.monaco-learn .referral-levels span {
  display: block;
  font-size: 12px;
}
.monaco-learn .flow {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 24px 0;
}
.monaco-learn .flow > div {
  flex: 1;
  min-width: 0;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: 10px;
}
.monaco-learn .flow b {
  display: block;
  color: var(--muted);
}
.monaco-learn .flow p {
  font-size: 13px;
  margin: 8px 0 0;
}
.monaco-learn .learn-reference {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 20px;
  margin-top: 36px;
}
.monaco-learn .learn-reference > summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--accent);
}
.monaco-learn .fee-controls {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}
.monaco-learn .fee-tabs {
  display: flex;
  gap: 8px;
}
.monaco-learn .fee-controls button {
  cursor: pointer;
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 8px 12px;
  font-size: 13px;
  color: var(--fg);
}
.monaco-learn .fee-tabs button[aria-selected=true] {
  background: var(--callout);
  font-weight: 600;
}
.monaco-learn .fee-panel {
  overflow-x: auto;
}
.monaco-learn .fees-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.monaco-learn .fees-table th,
.monaco-learn .fees-table td {
  padding: 12px;
  text-align: right;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.monaco-learn .fees-table th:first-child,
.monaco-learn .fees-table th:nth-child(2),
.monaco-learn .fees-table td:first-child,
.monaco-learn .fees-table td:nth-child(2) {
  text-align: left;
}
.monaco-learn .fees-table caption {
  text-align: left;
  font-weight: 600;
  margin-bottom: 10px;
}
.monaco-learn button:focus-visible,
.monaco-learn input:focus-visible,
.monaco-learn summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}
@media (max-width: 600px) {
  .monaco-learn .account-cards {
    grid-template-columns: 1fr;
  }
  .monaco-learn .flow {
    flex-direction: column;
    align-items: stretch;
  }
  .monaco-learn .flow > span {
    display: none;
  }
  .monaco-learn .referral-levels > div {
    padding: 14px 6px;
  }
  .monaco-learn .referral-levels span {
    font-size: 10px;
  }
}
@media print {
  .monaco-learn .fee-controls {
    display: none;
  }
  .monaco-learn .fee-panel[hidden] {
    display: block;
    margin-top: 20px;
  }
}
.monaco-learn .referral-calculator {
  margin: 30px 0;
  border: 1px solid var(--line);
  border-radius: 13px;
  padding: 25px;
  background: var(--bg);
}
.monaco-learn .calculator-heading {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}
.monaco-learn .calculator-heading h3 {
  font-size: 19px;
  margin: 0;
  letter-spacing: -.025em;
}
.monaco-learn .calculator-heading .small-label {
  margin-bottom: 5px;
}
.monaco-learn .unlimited-flag {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--line);
  border-radius: 30px;
  background: var(--callout);
  padding: 4px 9px;
  font-size: 10px;
  color: var(--accent);
  white-space: nowrap;
}
.monaco-learn .calculator-intro {
  font-size: 13px;
  line-height: 1.7;
  margin: 13px 0 25px;
}
.monaco-learn .calculator-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 26px;
  align-items: start;
}
.monaco-learn .referral-control {
  margin: 0 0 20px;
}
.monaco-learn .slider-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
}
.monaco-learn .slider-label label {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--fg);
}
.monaco-learn .slider-label label span {
  display: block;
  font-weight: 400;
  font-size: 10px;
  color: var(--muted);
  margin-top: 2px;
}
.monaco-learn .slider-label output {
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  flex: none;
}
.monaco-learn .referral-calculator input[type=range] {
  display: block;
  appearance: none;
  -webkit-appearance: none;
  width: 100%;
  height: 24px;
  margin: 0;
  background: transparent;
  cursor: pointer;
  --range-fill:0%;
}
.monaco-learn .referral-calculator input[type=range]::-webkit-slider-runnable-track {
  height: 5px;
  border-radius: 5px;
  background:
    linear-gradient(
      to right,
      var(--accent) var(--range-fill),
      var(--line) var(--range-fill));
}
.monaco-learn .referral-calculator input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--bg);
  box-shadow: 0 0 0 1px var(--accent);
  margin-top: -6px;
}
.monaco-learn .referral-calculator input[type=range]::-moz-range-track {
  height: 5px;
  border-radius: 5px;
  background: var(--line);
}
.monaco-learn .referral-calculator input[type=range]::-moz-range-progress {
  height: 5px;
  border-radius: 5px;
  background: var(--accent);
}
.monaco-learn .referral-calculator input[type=range]::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  border: 3px solid var(--bg);
  box-shadow: 0 0 0 1px var(--accent);
}
.monaco-learn .slider-scale {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  line-height: 1.5;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.monaco-learn .referral-calculator .calculator-help {
  font-size: 10px;
  line-height: 1.7;
  color: var(--muted);
  margin: 6px 0 0;
}
.monaco-learn .calculator-inputs > .calculator-help {
  margin: -7px 0 20px;
}
.monaco-learn .volume-control {
  border-top: 1px solid var(--line);
  padding-top: 18px;
  margin-bottom: 0;
}
.monaco-learn .volume-control .slider-label {
  flex-wrap: wrap;
  gap: 4px;
}
.monaco-learn .volume-control label {
  font-size: 12px;
}
.monaco-learn .volume-control output {
  font-size: 17px;
}
.monaco-learn .earn-estimate {
  background: var(--callout);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 23px 20px;
  color: var(--accent);
  min-width: 0;
}
.monaco-learn .estimate-kicker {
  font-size: 10px;
  letter-spacing: .07em;
  text-transform: uppercase;
  font-weight: 600;
}
.monaco-learn .estimate-total,
.monaco-learn .estimate-annual {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  line-height: 1.25;
}
.monaco-learn .estimate-total {
  margin: 14px 0 15px;
}
.monaco-learn .estimate-total output {
  font-size: clamp(24px, 2.3vw, 34px);
  font-weight: 600;
  letter-spacing: -.045em;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.monaco-learn .estimate-total span,
.monaco-learn .estimate-annual span {
  font-size: 11px;
  color: var(--muted);
}
.monaco-learn .estimate-annual output {
  font-size: 23px;
  font-weight: 500;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.monaco-learn .estimate-breakdown {
  border-top: 1px solid var(--line);
  padding-top: 17px;
  margin-top: 23px;
}
.monaco-learn .breakdown-title {
  display: block;
  font-size: 10px;
  font-weight: 600;
  margin-bottom: 10px;
  color: var(--accent);
}
.monaco-learn .estimate-breakdown > div {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 11px;
  margin: 9px 0;
  line-height: 1.5;
}
.monaco-learn .estimate-breakdown > div > span {
  color: var(--body);
}
.monaco-learn .estimate-breakdown output {
  font-variant-numeric: tabular-nums;
  text-align: right;
  overflow-wrap: anywhere;
  min-width: 0;
}
.monaco-learn .earn-estimate p {
  font-size: 10px;
  line-height: 1.7;
  color: var(--muted);
  margin: 20px 0 0;
}
.monaco-learn .calculator-assumptions {
  border-top: 1px solid var(--line);
  margin-top: 24px;
  padding-top: 16px;
  font-size: 12px;
}
.monaco-learn .calculator-assumptions summary {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  list-style: none;
  cursor: pointer;
  color: var(--fg);
  font-weight: 500;
}
.monaco-learn .calculator-assumptions summary > span {
  color: var(--muted);
  font-size: 11px;
  font-weight: 400;
}
.monaco-learn .calculator-assumptions summary::-webkit-details-marker {
  display: none;
}
.monaco-learn .calculator-assumptions p {
  font-size: 11px;
  line-height: 1.8;
  margin: 12px 0 0;
}
.monaco-learn .referral-calculator .calculator-footnote {
  font-size: 10px;
  line-height: 1.8;
  color: var(--muted);
  margin: 13px 0 0;
}
@media (max-width: 600px) {
  .monaco-learn .referral-calculator {
    padding: 20px;
  }
  .monaco-learn .calculator-grid {
    grid-template-columns: 1fr;
    gap: 24px;
  }
  .monaco-learn .calculator-heading {
    gap: 10px;
  }
  .monaco-learn .calculator-heading h3 {
    font-size: 18px;
  }
  .monaco-learn .calculator-intro {
    font-size: 12px;
  }
  .monaco-learn .calculator-heading .small-label {
    font-size: 9px;
  }
  .monaco-learn .slider-label label {
    font-size: 13px;
  }
  .monaco-learn .slider-label output {
    font-size: 18px;
  }
  .monaco-learn .volume-control .slider-label {
    display: block;
  }
  .monaco-learn .volume-control output {
    display: block;
    font-size: 21px;
    margin: 6px 0;
  }
  .monaco-learn .earn-estimate {
    padding: 22px;
  }
  .monaco-learn .estimate-total output {
    font-size: 36px;
  }
  .monaco-learn .estimate-annual output {
    font-size: 27px;
  }
  .monaco-learn .estimate-breakdown > div {
    font-size: 12px;
  }
  .monaco-learn .calculator-assumptions summary {
    flex-wrap: wrap;
    gap: 4px;
  }
}
@media print {
  .monaco-learn .calculator-grid {
    grid-template-columns: 1.2fr 1fr;
  }
  .monaco-learn .referral-calculator {
    break-inside: avoid;
  }
  .monaco-learn .calculator-assumptions > * {
    display: block !important;
  }
  .monaco-learn .calculator-assumptions summary {
    display: flex !important;
  }
}
`}</style>;
};

<LearnStyles />

<div className="monaco-learn">
  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

  | Mode | Your resting order | Your incoming order |
  | - | - | - |
  | Cancel maker · default | Each of your resting orders reached by the incoming order is cancelled in full. | Continues against other liquidity. |
  | Cancel taker | Remains untouched. | Any earlier third-party fills stand; the remainder cancels at the first self-touch. |
  | Cancel both | Every resting order it would have reached is cancelled. | Its remaining quantity is cancelled. |
  | Skip | Remains untouched and is never matched. | Trades around your orders. A remainder that would rest crossing your surviving order is cancelled. |

  <div className="example"><span className="small-label">Default behavior</span><strong>Your incoming buy reaches your own resting sell</strong><p>The resting sell is cancelled. The buy continues looking for other liquidity. The two orders do not trade with one another.</p></div>

  ## 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.

  <Accordion title="STP Reference And Edge Cases" id="full-reference" className="learn-reference">
    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:

    | Mode | What happens at a self-cross |
    | - | - |
    | `CANCEL_MAKER` | Every resting order of yours the incoming order reaches cancels in full; the incoming order keeps matching against other liquidity. **The platform default.** |
    | `CANCEL_TAKER` | The incoming order fills third-party liquidity ahead of your order, then its remainder cancels at the first touch of your own order — liquidity behind it is never reached. Your resting order is untouched. |
    | `CANCEL_BOTH` | The incoming order's remainder cancels **and** every one of your resting orders it would have reached cancels. |
    | `SKIP` | The incoming order trades *around* your resting orders — they are never matched and never cancelled. A remainder that would rest crossing one of your own surviving orders cancels instead of resting. |

    `SKIP` in particular is rare among venues: it lets a market maker's incoming flow coexist with its own quotes instead of destroying them.

    <h2 id="how-it-resolves">How it resolves</h2>

    * **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.

    <h2 id="setting-it">Setting it</h2>

    * **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`](/api-reference/accounts/get-self-trade-prevention-default)/[`PUT /api/v1/accounts/self-trade-prevention`](/api-reference/accounts/set-self-trade-prevention-default) reads and sets your wallet's default (applies to every order from your wallet family that names no per-order mode).

    <h2 id="edge-semantics-worth-knowing">Edge semantics worth knowing</h2>

    * **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`.)
  </Accordion>
</div>


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