Files
DisneyandGitHub d6399b92aa Feat/support binance (#22)
* add docs

* Add Binance exchange support

- Updated the environment configuration to include Binance as a selectable exchange option.
- Enhanced the README documentation to reflect the addition of Binance.
- Implemented the Binance exchange adapter and integrated it into the existing exchange framework.
- Modified the basis arbitrage strategy to support Binance alongside existing exchanges.
- Added tests to ensure proper functionality and integration of Binance within the trading system.

* Enhance README with detailed Binance exchange configuration

- Added comprehensive instructions for setting up Binance as an exchange option.
- Included environment variable specifications for API keys, market types, and trading symbols.
- Provided examples for both perpetual and spot trading strategies.
- Clarified the use of WebSocket and REST for the Binance adapter.

* Enhance exchange support and testing framework

- Added a new test suite for exchange contracts to ensure consistency and functionality across supported exchanges.
- Refactored exchange ID handling to utilize a centralized list of supported exchanges, improving maintainability.
- Updated CLI argument parsing and help documentation to reflect the new exchange structure.
- Introduced utility functions for validating supported exchanges and their display names.
- Enhanced the BasisApp and strategy runner to leverage the new exchange validation logic.
- Added a new test command for running exchange-related tests.

* Refactor exchange contract tests and update CLI commands

- Removed the trailing supported exchanges set and simplified the logic for trailing stop support in the exchange contract tests.
- Updated the test command for exchange contracts to exclude unnecessary tests, streamlining the testing process.
- Enhanced test descriptions for clarity and improved understanding of the functionality being tested.
2026-02-27 11:37:44 +08:00

370 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "STP FAQ | Binance Open Platform"
source: "https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq"
fetched_at: "2026-02-26T10:38:08.165Z"
---
# Self Trade Prevention (STP) FAQ
**Disclaimer:**
- The commissions and prices used here are fictional and do not imply anything about the actual setup on the live exchange.
### What is Self Trade Prevention?[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
Self Trade Prevention (or STP) prevents orders of users, or the user's `tradeGroupId` to match against their own.
### What defines a self-trade?[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
A self-trade can occur in either scenario:
- The order traded against the same account.
- The order traded against an account with the same `tradeGroupId`.
### What happens when STP is triggered?[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
There are five possible modes for what the system does when an order would create a self-trade.
`NONE` - This mode exempts the order from self-trade prevention. Accounts or Trade group IDs will not be compared, no orders will be expired, and the trade will occur.
`EXPIRE_TAKER` - This mode prevents a trade by immediately expiring the taker order's remaining quantity.
`EXPIRE_MAKER` - This mode prevents a trade by immediately expiring the potential maker order's remaining quantity.
`EXPIRE_BOTH` - This mode prevents a trade by immediately expiring both the taker and the potential maker orders' remaining quantities.
`DECREMENT` - This mode increases the `prevented quantity` of _both_ orders by the amount of the prevented match. The smaller of the two orders will expire, or both if they have the same quantity.
`TRANSFER` - If orders are from the same account, then the behavior is the same as `DECREMENT`. If orders are from different accounts with the same `tradeGroupId`, then in addition to the behavior of `DECREMENT`, the `last prevented quantity` and its notional are transferred between the two accounts.
STP behavior is typically determined by the STP mode of the **taker order** only. The exception is that for STP `TRANSFER` to occur, both the maker and taker orders must specify STP mode `TRANSFER`. If the taker order specifies STP mode `TRANSFER`, but the maker order specifies a different STP mode, then the STP behavior is `DECREMENT`.
In summary:
Taker Order STP Mode
Maker Order STP Mode
Effective STP Mode
`TRANSFER`
`TRANSFER`
`TRANSFER`
`TRANSFER`
`EXPIRE_MAKER`, `EXPIRE_TAKER`, `EXPIRE_BOTH`, `NONE`, `DECREMENT`
`DECREMENT`
`EXPIRE_MAKER`, `EXPIRE_TAKER`, `EXPIRE_BOTH`, `NONE`, `DECREMENT`
ANY STP MODE
STP mode of the Taker Order
### What is a Trade Group Id?[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
Different accounts with the same `tradeGroupId` are considered part of the same "trade group". Orders submitted by members of a trade group are eligible for STP according to the taker-order's STP mode.
A user can confirm if their accounts are under the same `tradeGroupId` from the API either from `GET /api/v3/account` (REST API) or `account.status` (WebSocket API) for each account.
The field is also present in the response for `GET /api/v3/preventedMatches` (REST API) or `myPreventedMatches` (WebSocket API).
If the value is `-1`, then the `tradeGroupId` has not been set for that account, so the STP may only take place between orders of the same account.
### What is a Prevented Match?[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
When a self-trade is prevented, a prevented match is created. The orders in the prevented match have their prevented quantities increased and one or more orders expire.
This is not to be confused with a trade, as no orders will match.
This is a record of what orders could have self-traded.
This can be queried through the endpoint `GET /api/v3/preventedMatches` on the REST API or `myPreventedMatches` on the WebSocket API.
This is a sample of the output request for reference:
```
[ { "symbol": "BTCDUSDT", // Symbol of the orders "preventedMatchId": 8, // Identifies the prevented match of the expired order(s) for the symbol. "takerOrderId": 12, // Order Id of the Taker Order "makerOrderId": 10, // Order Id of the Maker Order "tradeGroupId": 1, // Identifies the Trade Group Id. (If the account is not part of a trade group, this will be -1.) "selfTradePreventionMode": "EXPIRE_BOTH", // STP mode that expired the order(s). "price": "50.00000000", // Price at which the match occurred. "takerPreventedQuantity": "1.00000000", // Taker's remaining quantity before the STP. Only appears if the STP mode is EXPIRE_TAKER, EXPIRE_BOTH or DECREMENT. "makerPreventedQuantity": "10.00000000", // Maker's remaining quantity before the STP. Only appears if the STP mode is EXPIRE_MAKER, EXPIRE_BOTH, or DECREMENT. "transactTime": 1663190634060 // Time the order(s) expired due to STP. }]
```
### What is "prevented quantity?"[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
STP events expire quantity from open orders. The STP modes `EXPIRE_TAKER`, `EXPIRE_MAKER`, and `EXPIRE_BOTH` expire all remaining quantity on the affected orders, resulting in the entire open order being expired.
Prevented quantity is the amount of quantity that is expired due to STP events for a particular order. User stream execution reports for orders involved in STP may have these fields:
```
{ "A": "3.000000", // Prevented Quantity "B": "3.000000" // Last Prevented Quantity}
```
`B` is present for execution type `TRADE_PREVENTION`, and is the quantity expired due to that individual STP event.
`A` is the cumulative quantity expired due to STP over the lifetime of the order. For `EXPIRE_TAKER`, `EXPIRE_MAKER`, and `EXPIRE_BOTH` modes this will always be the same value as `B`.
API responses for orders which expired due to STP will also have a `preventedQuantity` field, indicating the cumulative quantity expired due to STP over the lifetime of the order.
While an order is open, the following equation holds true:
```
original order quantity - executed quantity - prevented quantity = quantity available for further execution
```
When an order's available quantity goes to zero, the order will be removed from the order book and the status will be one of `EXPIRED_IN_MATCH`, `FILLED`, or `EXPIRED`.
### How do I know which symbol uses STP?[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
Symbols may be configured to allow different sets of STP modes and take different default STP modes.
`defaultSelfTradePreventionMode` - Orders will use this STP mode if the user does not provide one on order placement.
`allowedSelfTradePreventionModes` - Defines the allowed set of STP modes for order placement on that symbol.
For example, if a symbol has the following configuration:
```
{ "defaultSelfTradePreventionMode": "NONE", "allowedSelfTradePreventionModes": ["NONE", "EXPIRE_TAKER", "EXPIRE_BOTH"]}
```
Then that means if a user sends an order with no `selfTradePreventionMode` provided, then the order sent will have the value of `NONE`.
If a user wants to explicitly specify the mode they can pass the enum `NONE`, `EXPIRE_TAKER`, or `EXPIRE_BOTH`.
If a user tries to specify `EXPIRE_MAKER` for orders on this symbol, they will receive an error:
```
{ "code": -1013, "msg": "This symbol does not allow the specified self-trade prevention mode."}
```
### How do I know if an order expired due to STP?[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
The order will have the status `EXPIRED_IN_MATCH`.
### STP Examples[](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
For all these cases, assume that all orders for these examples are made on the same account.
**Scenario A- A user sends a new order with selfTradePreventionMode:`NONE` that will match with another order of theirs that is already on the book.**
```
Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=1 selfTradePreventionMode=NONETaker Order: symbol=BTCUSDT side=SELL type=LIMIT quantity=1 price=1 selfTradePreventionMode=NONE
```
**Result**: No STP is triggered and the orders will match.
Order Status of the Maker Order
```
{ "symbol": "BTCUSDT", "orderId": 2, "orderListId": -1, "clientOrderId": "FaDk4LPRxastaICEFE9YTf", "price": "1.000000", "origQty": "1.000000", "executedQty": "1.000000", "cummulativeQuoteQty": "1.000000", "status": "FILLED", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670217090310, "updateTime": 1670217090330, "isWorking": true, "workingTime": 1670217090310, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE"}
```
Order Status of the Taker Order
```
{ "symbol": "BTCUSDT", "orderId": 3, "orderListId": -1, "clientOrderId": "Ay48Vtpghnsvy6w8RPQEde", "transactTime": 1670207731263, "price": "1.000000", "origQty": "1.000000", "executedQty": "1.000000", "cummulativeQuoteQty": "1.000000", "status": "FILLED", "timeInForce": "GTC", "type": "LIMIT", "side": "SELL", "workingTime": 1670207731263, "fills": [ { "price": "1.000000", "qty": "1.000000", "commission": "0.000000", "commissionAsset": "USDT", "tradeId": 1 } ], "selfTradePreventionMode": "NONE"}
```
**Scenario B- A user sends an order with `EXPIRE_MAKER` that would match with their orders that are already on the book.**
```
Maker Order 1: symbol=BTCUSDT side=BUY type=LIMIT quantity=1.2 price=1.2 selfTradePreventionMode=NONEMaker Order 2: symbol=BTCUSDT side=BUY type=LIMIT quantity=1.3 price=1.1 selfTradePreventionMode=NONEMaker Order 3: symbol=BTCUSDT side=BUY type=LIMIT quantity=8.1 price=1 selfTradePreventionMode=NONETaker Order 1: symbol=BTCUSDT side=SELL type=LIMIT quantity=3 price=1 selfTradePreventionMode=EXPIRE_MAKER
```
**Result**: The orders that were on the book will expire due to STP, and the taker order will go on the book.
Maker Order 1
```
{ "symbol": "BTCUSDT", "orderId": 2, "orderListId": -1, "clientOrderId": "wpNzhSclc16pV8g5THIOR3", "price": "1.200000", "origQty": "1.200000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670217957437, "updateTime": 1670217957498, "isWorking": true, "workingTime": 1670217957437, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE", "preventedMatchId": 0, "preventedQuantity": "1.200000"}
```
Maker Order 2
```
{ "symbol": "BTCUSDT", "orderId": 3, "orderListId": -1, "clientOrderId": "ZT9emqia99V7x8B6FW0pFF", "price": "1.100000", "origQty": "1.300000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670217957458, "updateTime": 1670217957498, "isWorking": true, "workingTime": 1670217957458, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE", "preventedMatchId": 1, "preventedQuantity": "1.300000"}
```
Maker Order 3
```
{ "symbol": "BTCUSDT", "orderId": 4, "orderListId": -1, "clientOrderId": "8QZ3taGcU4gND59TxHAcR0", "price": "1.000000", "origQty": "8.100000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670217957478, "updateTime": 1670217957498, "isWorking": true, "workingTime": 1670217957478, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE", "preventedMatchId": 2, "preventedQuantity": "8.100000"}
```
Output of the Taker Order
```
{ "symbol": "BTCUSDT", "orderId": 5, "orderListId": -1, "clientOrderId": "WRzbhp257NhZsIJW4y2Nri", "transactTime": 1670217957498, "price": "1.000000", "origQty": "3.000000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", "side": "SELL", "workingTime": 1670217957498, "fills": [], "preventedMatches": [ { "preventedMatchId": 0, "makerOrderId": 2, "price": "1.200000", "makerPreventedQuantity": "1.200000" }, { "preventedMatchId": 1, "makerOrderId": 3, "price": "1.100000", "makerPreventedQuantity": "1.300000" }, { "preventedMatchId": 2, "makerOrderId": 4, "price": "1.000000", "makerPreventedQuantity": "8.100000" } ], "selfTradePreventionMode": "EXPIRE_MAKER"}
```
**Scenario C - A user sends an order with `EXPIRE_TAKER` that would match with their orders already on the book.**
```
Maker Order 1: symbol=BTCUSDT side=BUY type=LIMIT quantity=1.2 price=1.2 selfTradePreventionMode=NONEMaker Order 2: symbol=BTCUSDT side=BUY type=LIMIT quantity=1.3 price=1.1 selfTradePreventionMode=NONEMaker Order 3: symbol=BTCUSDT side=BUY type=LIMIT quantity=8.1 price=1 selfTradePreventionMode=NONETaker Order 1: symbol=BTCUSDT side=SELL type=LIMIT quantity=3 price=1 selfTradePreventionMode=EXPIRE_TAKER
```
**Result**: The orders already on the book will remain, while the taker order will expire.
Maker Order 1
```
{ "symbol": "BTCUSDT", "orderId": 2, "orderListId": -1, "clientOrderId": "NpwW2t0L4AGQnCDeNjHIga", "price": "1.200000", "origQty": "1.200000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670219811986, "updateTime": 1670219811986, "isWorking": true, "workingTime": 1670219811986, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE"}
```
Maker Order 2
```
{ "symbol": "BTCUSDT", "orderId": 3, "orderListId": -1, "clientOrderId": "TSAmJqGWk4YTB2yA9p04UO", "price": "1.100000", "origQty": "1.300000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670219812007, "updateTime": 1670219812007, "isWorking": true, "workingTime": 1670219812007, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE"}
```
Maker Order 3
```
{ "symbol": "BTCUSDT", "orderId": 4, "orderListId": -1, "clientOrderId": "L6FmpCJJP6q4hCNv4MuZDG", "price": "1.000000", "origQty": "8.100000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670219812026, "updateTime": 1670219812026, "isWorking": true, "workingTime": 1670219812026, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE"}
```
Output of the Taker order
```
{ "symbol": "BTCUSDT", "orderId": 5, "orderListId": -1, "clientOrderId": "kocvDAi4GNN2y1l1Ojg1Ri", "price": "1.000000", "origQty": "3.000000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "SELL", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670219812046, "updateTime": 1670219812046, "isWorking": true, "workingTime": 1670219812046, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "EXPIRE_TAKER", "preventedMatchId": 0, "preventedQuantity": "3.000000"}
```
**Scenario D- A user has an order on the book, and then sends an order with `EXPIRE_BOTH` that would match with the existing order.**
```
Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=1 selfTradePreventionMode=NONETaker Order: symbol=BTCUSDT side=SELL type=LIMIT quantity=3 price=1 selfTradePreventionMode=EXPIRE_BOTH
```
**Result:** Both orders will expire.
Maker Order
```
{ "symbol": "BTCUSDT", "orderId": 2, "orderListId": -1, "clientOrderId": "2JPC8xjpLq6Q0665uYWAcs", "price": "1.000000", "origQty": "1.000000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1673842412831, "updateTime": 1673842413170, "isWorking": true, "workingTime": 1673842412831, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE", "preventedMatchId": 0, "preventedQuantity": "1.000000"}
```
Taker Order
```
{ "symbol": "BTCUSDT", "orderId": 5, "orderListId": -1, "clientOrderId": "qMaz8yrOXk2iUIz74cFkiZ", "transactTime": 1673842413170, "price": "1.000000", "origQty": "3.000000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "SELL", "workingTime": 1673842413170, "fills": [], "preventedMatches": [ { "preventedMatchId": 0, "makerOrderId": 2, "price": "1.000000", "takerPreventedQuantity": "3.000000", "makerPreventedQuantity": "1.000000" } ], "selfTradePreventionMode": "EXPIRE_BOTH", "tradeGroupId": 1, "preventedQuantity": "3.000000"}
```
**Scenario E - A user has an order on the book with `EXPIRE_MAKER`, and then sends a new order with `EXPIRE_TAKER` which would match with the existing order.**
```
Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=1 selfTradePreventionMode=EXPIRE_MAKERTaker Order: symbol=BTCUSDT side=SELL type=LIMIT quantity=1 price=1 selfTradePreventionMode=EXPIRE_TAKER
```
**Result**: The taker order's STP mode will be used, so the taker order will be expired.
Maker Order
```
{ "symbol": "BTCUSDT", "orderId": 0, "orderListId": -1, "clientOrderId": "jFUap8iFwwgqIpOfAL60GS", "price": "1.000000", "origQty": "1.000000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670220769261, "updateTime": 1670220769261, "isWorking": true, "workingTime": 1670220769261, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "EXPIRE_MAKER"}
```
Taker Order
```
{ "symbol": "BTCUSDT", "orderId": 1, "orderListId": -1, "clientOrderId": "zxrvnNNm1RXC3rkPLUPrc1", "transactTime": 1670220800315, "price": "1.000000", "origQty": "1.000000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "SELL", "workingTime": 1670220800315, "fills": [], "preventedMatches": [ { "preventedMatchId": 0, "makerOrderId": 0, "price": "1.000000", "takerPreventedQuantity": "1.000000" } ], "selfTradePreventionMode": "EXPIRE_TAKER", "preventedQuantity": "1.000000"}
```
**Scenario F - A user sends a market order with `EXPIRE_MAKER` which would match with an existing order.**
```
Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=1 selfTradePreventionMode=NONETaker Order: symbol=BTCUSDT side=SELL type=MARKET quantity=1 selfTradePreventionMode=EXPIRE_MAKER
```
**Result**: The existing order expires with the status `EXPIRED_IN_MATCH`, due to STP. The new order also expires but with status `EXPIRED`, due to low liquidity on the order book.
Maker Order
```
{ "symbol": "BTCUSDT", "orderId": 2, "orderListId": -1, "clientOrderId": "7sgrQQInL69XDMQpiqMaG2", "price": "1.000000", "origQty": "1.000000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.000000", "icebergQty": "0.000000", "time": 1670222557456, "updateTime": 1670222557478, "isWorking": true, "workingTime": 1670222557456, "origQuoteOrderQty": "0.000000", "selfTradePreventionMode": "NONE", "preventedMatchId": 0, "preventedQuantity": "1.000000"}
```
Taker Order
```
{ "symbol": "BTCUSDT", "orderId": 3, "orderListId": -1, "clientOrderId": "zqhsgGDEcdhxy2oza2Ljxd", "transactTime": 1670222557478, "price": "0.000000", "origQty": "1.000000", "executedQty": "0.000000", "cummulativeQuoteQty": "0.000000", "status": "EXPIRED", "timeInForce": "GTC", "type": "MARKET", "side": "SELL", "workingTime": 1670222557478, "fills": [], "preventedMatches": [ { "preventedMatchId": 0, "makerOrderId": 2, "price": "1.000000", "makerPreventedQuantity": "1.000000" } ], "selfTradePreventionMode": "EXPIRE_MAKER"}
```
**Scenario G- A user sends a limit order with `DECREMENT` which would match with an existing order.**
```
Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=6 price=2 selfTradePreventionMode=NONETaker Order: symbol=BTCUSDT side=SELL type=LIMIT quantity=2 price=2 selfTradePreventionMode=DECREMENT
```
**Result**: Both orders have a preventedQuantity of 2. Since this is the taker orders full quantity, it expires due to STP.
Maker Order
```
{ "symbol": "BTCUSDT", "orderId": 23, "orderListId": -1, "clientOrderId": "Kxb4RpsBhfQrkK2r2YO2Z9", "price": "2.00000000", "origQty": "6.00000000", "executedQty": "0.00000000", "cummulativeQuoteQty": "0.00000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.00000000", "icebergQty": "0.00000000", "time": 1741682807892, "updateTime": 1741682816376, "isWorking": true, "workingTime": 1741682807892, "origQuoteOrderQty": "0.00000000", "selfTradePreventionMode": "DECREMENT", "preventedMatchId": 4, "preventedQuantity": "2.00000000"}
```
Taker Order
```
{ "symbol": "BTCUSDT", "orderId": 24, "orderListId": -1, "clientOrderId": "dwf3qOzD7GM9ysDn9XG9AS", "price": "2.00000000", "origQty": "2.00000000", "executedQty": "0.00000000", "cummulativeQuoteQty": "0.00000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "SELL", "stopPrice": "0.00000000", "icebergQty": "0.00000000", "time": 1741682816376, "updateTime": 1741682816376, "isWorking": true, "workingTime": 1741682816376, "origQuoteOrderQty": "0.00000000", "selfTradePreventionMode": "DECREMENT", "preventedMatchId": 4, "preventedQuantity": "2.00000000"}
```
**Scenario H- A user sends a limit order with `TRANSFER` which would match with an existing order under the same tradeGroupId.**
Balances before order placement
Maker's Balances
```
{ "balances": [ { "asset": "BTC", "free": "20000.00000000", "locked": "0.00000000" }, { "asset": "USDT", "free": "20000.00000000", "locked": "0.00000000" } ]}
```
Taker's Balances
```
{ "balances": [ { "asset": "BTC", "free": "20000.00000000", "locked": "0.00000000" }, { "asset": "USDT", "free": "20000.00000000", "locked": "0.00000000" } ]}
```
```
Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=0.6 price=0.2 selfTradePreventionMode=TRANSFER tradeGroupId=1Taker Order: symbol=BTCUSDT side=SELL type=LIMIT quantity=0.2 price=0.2 selfTradePreventionMode=TRANSFER tradeGroupId=1
```
**Result:** Both orders have a preventedQuantity of 0.2. Since this is the takers full quantity, it expires due to STP.
Maker Order
```
{ "symbol": "BTCUSDT", "orderId": 12, "orderListId": -1, "clientOrderId": "zEyu9HGqiT5YUaXXhKr1MR", "price": "0.20000000", "origQty": "0.60000000", "executedQty": "0.00000000", "cummulativeQuoteQty": "0.00000000", "status": "NEW", "timeInForce": "GTC", "type": "LIMIT", "side": "BUY", "stopPrice": "0.00000000", "icebergQty": "0.00000000", "time": 1762852466582, "updateTime": 1762852522145, "isWorking": true, "workingTime": 1762852466582, "origQuoteOrderQty": "0.00000000", "selfTradePreventionMode": "TRANSFER", "preventedMatchId": 3, "preventedQuantity": "0.20000000"}
```
Taker Order
```
{ "symbol": "BTCUSDT", "orderId": 13, "orderListId": -1, "clientOrderId": "6T06cph3Et2yFNnGpHdejh", "transactTime": 1762852522145, "price": "0.20000000", "origQty": "0.20000000", "executedQty": "0.00000000", "origQuoteOrderQty": "0.00000000", "cummulativeQuoteQty": "0.00000000", "status": "EXPIRED_IN_MATCH", "timeInForce": "GTC", "type": "LIMIT", "side": "SELL", "workingTime": 1762852522145, "fills": [], "preventedMatches": [ { "preventedMatchId": 3, "makerSymbol": "BTCUSDT", "makerOrderId": 12, "price": "0.20000000", "takerPreventedQuantity": "0.20000000", "makerPreventedQuantity": "0.20000000" } ], "selfTradePreventionMode": "TRANSFER", "tradeGroupId": 1, "preventedQuantity": "0.20000000"}
```
Balances after self-trade prevention:
Maker Balances
```
{ "balances": [ { "asset": "BTC", "free": "20000.20000000", "locked": "0.00000000" }, { "asset": "USDT", "free": "19999.88000000", "locked": "0.08000000" } ]}
```
Taker's Balances
```
{ "balances": [ { "asset": "BTC", "free": "19999.80000000", "locked": "0.00000000" }, { "asset": "USDT", "free": "20000.04000000", "locked": "0.00000000" } ]}
```
- [What is Self Trade Prevention?](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
- [What defines a self-trade?](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
- [What happens when STP is triggered?](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
- [What is a Trade Group Id?](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
- [What is a Prevented Match?](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
- [What is "prevented quantity?"](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
- [How do I know which symbol uses STP?](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
- [How do I know if an order expired due to STP?](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)
- [STP Examples](https://developers.binance.com/docs/binance-spot-api-docs/faqs/stp_faq)