Skip to main content

FAQ

Frequently asked questions about the USDⓈ-Margined Futures API.

What is Self Trade Prevention (STP)?

Self Trade Prevention prevents orders from trading against orders from the same account or accounts with the same tradeGroupId.

What is a self-trade?

A self-trade can occur in either of the following situations:

  • Orders from the same account trade against each other.
  • Orders from accounts with the same tradeGroupId trade against each other.

What happens when STP is triggered?

If an order would cause a self-trade, the system will execute one of three possible modes:

  • EXPIRE_TAKER - Prevents the trade by immediately expiring the remaining quantity of the taker order.
  • EXPIRE_MAKER - Prevents the trade by immediately expiring the remaining quantity of the potential maker order.
  • EXPIRE_BOTH - Prevents the trade by immediately expiring the remaining quantity of both the taker and maker orders.

STP is determined by the STP mode of the Taker order. Therefore, the STP mode of orders already on the order book no longer has effect and will be ignored in all future order processing.

How to set Self Trade Prevention on an order?

Self Trade Prevention can be set via the selfTradePreventionMode parameter on the order placement endpoint. Related endpoints:

  • POST /fapi/v1/order
  • POST /fapi/v1/batchOrders

What is Trade Group Id?

Accounts belonging to the same tradeGroupId are considered part of the same trading group. Orders submitted by members of the same trading group are eligible for STP.

Each account can confirm whether it belongs to a tradeGroupId via GET /fapi/v1/accountConfig (REST API).

tradeGroupId also appears in the response of GET /api/v3/preventedMatches (REST API) or myPreventedMatches (WebSocket API).

If the value is -1, it means the account has no tradeGroupId set, so STP can only occur between orders from the same account.

We will provide the ability to set sub-accounts to the same tradeGroupId in a future update.

How to know which symbols support STP?

All symbols in GET fapi/v1/exchangeInfo support selfTradePreventionMode.

Which order types support STP?

LIMIT / MARKET / STOP / TAKE_PROFIT / STOP_MARKET / TAKE_PROFIT_MARKET / TRAILING_STOP_MARKET support STP when Time in Force (timeInForce) is set to GTC / IOC / GTD.

When Time in Force (timeInForce) is FOK or GTX, the STP setting on the order will not take effect.

Does order modification support STP?

Currently not supported. Order modification will reset the order's selfTradePreventionMode to NONE.

How to know if an order expired due to STP?

The order status will be EXPIRED_IN_MATCH.

In the user data stream push ORDER_TRADE_UPDATE, if an order expires due to STP, the field X will show EXPIRED_IN_MATCH:

{
"e": "ORDER_TRADE_UPDATE",
"E": 1568879465651,
"T": 1568879465650,
"o": {
"s": "BTCUSDT",
"c": "TEST",
"S": "SELL",
"o": "TRAILING_STOP_MARKET",
"f": "GTC",
"q": "0.001",
"p": "0",
"ap": "0",
"sp": "7103.04",
"x": "EXPIRED",
"X": "EXPIRED_IN_MATCH",
"i": 8886774,
"l": "0",
"z": "0",
"L": "0",
"N": "USDT",
"n": "0",
"T": 1568879465650,
"t": 0,
"b": "0",
"a": "9.91",
"m": false,
"R": false,
"wt": "CONTRACT_PRICE",
"ot": "TRAILING_STOP_MARKET",
"ps": "LONG",
"cp": false,
"AP": "7476.89",
"cr": "5.0",
"pP": false,
"si": 0,
"ss": 0,
"rp": "0",
"V": "EXPIRE_MAKER",
"pm": "QUEUE",
"gtd": 1768879465650
}
}

STP Examples

Assume all orders in the following examples are sent from the same account.

Case A - EXPIRE_MAKER mode

User sends an order with EXPIRE_MAKER that would match against existing orders on the order book.

Maker Order 1: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=20002 selfTradePreventionMode=EXPIRE_MAKER
Maker Order 2: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=20001 selfTradePreventionMode=EXPIRE_MAKER
Taker Order 1: symbol=BTCUSDT side=SELL type=LIMIT quantity=1 price=20000 selfTradePreventionMode=EXPIRE_MAKER

Result: Due to STP, the orders on the order book will expire, and the taker order will remain on the order book.

Maker Order 1:

{
"orderId": 292864710,
"symbol": "BTCUSDT",
"status": "FILLED",
"clientOrderId": "testMaker1",
"price": "20002",
"avgPrice": "20002",
"origQty": "1",
"executedQty": "1",
"cumQuote": "20002",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "BUY",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Maker Order 2:

{
"orderId": 292864711,
"symbol": "BTCUSDT",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testMaker2",
"price": "20001",
"avgPrice": "0.0000",
"origQty": "1",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "BUY",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Taker Order response:

{
"orderId": 292864712,
"symbol": "BTCUSDT",
"status": "PARTIALLY_FILLED",
"clientOrderId": "testTaker1",
"price": "20000",
"avgPrice": "20002",
"origQty": "2",
"executedQty": "1",
"cumQuote": "20002",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "SELL",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Case B - EXPIRE_TAKER mode

User sends an order with EXPIRE_TAKER that would match against existing orders on the order book.

Maker Order 1: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=20002 selfTradePreventionMode=EXPIRE_MAKER
Maker Order 2: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=20001 selfTradePreventionMode=EXPIRE_MAKER
Taker Order 1: symbol=BTCUSDT side=SELL type=LIMIT quantity=2 price=3 selfTradePreventionMode=EXPIRE_TAKER

Result: The orders already on the order book will be preserved, and the taker order will expire.

Maker Order 1:

{
"orderId": 292864710,
"symbol": "BTCUSDT",
"status": "FILLED",
"clientOrderId": "testMaker1",
"price": "20002",
"avgPrice": "0.0000",
"origQty": "1",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "BUY",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Maker Order 2:

{
"orderId": 292864711,
"symbol": "BTCUSDT",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testMaker2",
"price": "20001",
"avgPrice": "0.0000",
"origQty": "1",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "BUY",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Taker Order status:

{
"orderId": 292864712,
"symbol": "BTCUSDT",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testTaker1",
"price": "20000",
"avgPrice": "0.0000",
"origQty": "3",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "SELL",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_TAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Case C - EXPIRE_BOTH mode

User sends an order with EXPIRE_BOTH that would match against an existing order on the order book.

Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=20002 selfTradePreventionMode=EXPIRE_MAKER
Taker Order: symbol=BTCUSDT side=SELL type=LIMIT quantity=3 price=20000 selfTradePreventionMode=EXPIRE_BOTH

Result: Both orders will expire.

Maker Order:

{
"orderId": 292864710,
"symbol": "BTCUSDT",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testMaker1",
"price": "20002",
"avgPrice": "0.0000",
"origQty": "1",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "BUY",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Taker Order:

{
"orderId": 292864712,
"symbol": "BTCUSDT",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testTaker1",
"price": "20000",
"avgPrice": "0.0000",
"origQty": "3",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "SELL",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_BOTH",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Case D - Taker with EXPIRE_TAKER, Maker with EXPIRE_MAKER

User has an order with EXPIRE_MAKER on the order book, then sends a new order with EXPIRE_TAKER that would match.

Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=1 selfTradePreventionMode=EXPIRE_MAKER
Taker 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 expire.

Maker Order:

{
"orderId": 292864710,
"symbol": "BTCUSDT",
"status": "NEW",
"clientOrderId": "testMaker1",
"price": "20002",
"avgPrice": "0.0000",
"origQty": "1",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "BUY",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Taker Order:

{
"orderId": 292864712,
"symbol": "BTCUSDT",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testTaker1",
"price": "20000",
"avgPrice": "0.0000",
"origQty": "3",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "SELL",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_TAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Case E - Market order with EXPIRE_MAKER

User sends a market order with EXPIRE_MAKER that would match against an existing order on the order book.

Maker Order: symbol=ABCDEF side=BUY type=LIMIT quantity=1 price=1 selfTradePreventionMode=EXPIRE_MAKER
Taker Order: symbol=ABCDEF side=SELL type=MARKET quantity=3 selfTradePreventionMode=EXPIRE_MAKER

Result: Due to STP, the order on the order book expires with status EXPIRED_IN_MATCH. Due to low liquidity on the order book, the new order also expires but with status EXPIRED.

Maker Order:

{
"orderId": 292864710,
"symbol": "BTCUSDT",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testMaker1",
"price": "20002",
"avgPrice": "0.0000",
"origQty": "1",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "BUY",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}

Taker Order:

{
"orderId": 292864712,
"symbol": "BTCUSDT",
"status": "EXPIRED",
"clientOrderId": "testTaker1",
"price": "20000",
"avgPrice": "0.0000",
"origQty": "3",
"executedQty": "0",
"cumQuote": "0",
"timeInForce": "GTC",
"type": "LIMIT",
"reduceOnly": false,
"closePosition": false,
"side": "SELL",
"positionSide": "BOTH",
"stopPrice": "0",
"workingType": "CONTRACT_PRICE",
"priceMatch": "NONE",
"selfTradePreventionMode": "EXPIRE_MAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}