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: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.Skip, do not fill
The taker is neither cancelled nor modified. It continues to the next resting order in the book.
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)
- 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. - 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.
- The taker meets 3 BTC @ 103 from User C. Different user → normal fill. Taker fully filled.
(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 theEXPIRED_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.