Skip to main content
Self-Trade Prevention (STP) stops an account’s taker order from matching against its own resting maker order. It is a baseline market-integrity mechanism on every modern exchange: without STP, users could manufacture fake volume and liquidity by crossing their own orders, and algo traders would get accidental self-fills when their strategies happen to overlap. Intention enables STP by default for every user and every contract. No configuration is required.

How it works

When a taker order enters matching, the engine checks the account on each resting maker order it is about to fill. If both orders belong to the same user:
1

Cancel the maker

The resting maker is removed from the book. Its status becomes EXPIRED_BY_STP. No fill is recorded and no fee is charged.
2

Skip, do not fill

The taker is neither cancelled nor modified. It continues to the next resting order in the book.
3

Repeat

If the next resting maker is also from the same user, the same thing happens again. This loop continues until the taker either matches a different user’s maker, fills completely, or runs out of acceptable price levels.

Walked example

Suppose the ask side of the BTC book looks like this:
  • 101: 1 BTC (User A)
  • 102: 2 BTC (User B)
  • 103: 3 BTC (User C)
User A submits a market buy for 5 BTC.
  1. The taker meets 1 BTC @ 101 from User A. Same user → STP triggers. The 1 BTC @ 101 maker is cancelled with status EXPIRED_BY_STP. No fill.
  2. The taker continues with 5 BTC to buy and meets 2 BTC @ 102 from User B. Different user → normal fill. Taker has 3 BTC remaining.
  3. The taker meets 3 BTC @ 103 from User C. Different user → normal fill. Taker fully filled.
User A ends with 5 BTC bought at an average price of (2 × 102 + 3 × 103) / 5 = 102.6, and its own maker order is cleanly expired.

Scope

STP operates at the individual account level. In the current implementation, sub-accounts under the same master are treated as different users — a taker in a sub-account can match a maker in the parent account, for example. A future iteration may introduce user-configurable trade groups to extend STP across related accounts.

API surfaces

Every interface that exposes order status — REST, WebSocket, and historical queries — reflects the EXPIRED_BY_STP status so clients can distinguish STP cancellations from regular cancellations and from fills. Integrators should update any code that enumerates terminal order states to handle this new value.
STP is always on. There is no API flag to disable it. This matches the approach taken by several major perp venues and simplifies market-integrity audits.

Why Intention picked this design

Intention uses the simplest STP flavor (“cancel maker”) for the initial release, following the pattern that has worked well on other on-chain perps. It is easy to reason about, easy for algo traders to handle, and avoids edge cases where a large taker could be cancelled midway due to a small accidental overlap. More flexible STP modes — for example, cancel-taker or cancel-both, and cross-account trade groups — are planned as a later enhancement.