自成交预防(STP)简介

2023-08-29 07:03

什么是自成交预防(STP)?

自成交预防(STP)是交易平台采用的一种机制,旨在防止用户无意中与自己进行交易。当同一用户的两笔订单在订单簿上相互撮合时,就会发生自成交情况。STP机制对于维护公平透明的交易环境尤为重要,有助于防止市场价格操纵,确保交易活动准确反映真实的市场利益。

币安通过自成交预防(STP)机制来防止来自同一用户或“tradeGroupId”的订单彼此撮合。

什么是自成交?

在以下情况下,可能发生自成交:

  • 来自同一账户的订单彼此交易。
  • 来自同一“tradeGroupId”的订单彼此交易。

触发STP时会如何?

订单触发自成交预防机制后,系统可能会执行以下四种模式之一:

  • NONE模式:订单不受自成交预防机制的影响。系统不会对账户或“tradeGroupId”进行对比,也不会使订单失效,交易将正常执行。
  • EXPIRE_TAKER模式:吃单订单的剩余数量将立即失效以防止交易执行。
  • EXPIRE_MAKER模式:潜在挂单订单的剩余数量将立即失效以防止交易执行。
  • EXPIRE_BOTH模式:吃单订单和潜在挂单订单的剩余数量均将立即失效以防止交易执行。

STP的执行情况取决于吃单订单的STP模式。因此,订单簿上现有订单的STP模式将不再适用,并且在所有未来的订单处理中将被忽略。

如何设置订单的STP模式?

STP可通过以下API端点的“selfTradePreventionMode”字段设置:

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

什么是“tradeGroupId”?

具有相同“tradeGroupId”的账户被视为属于同一“交易组”。同一交易组的成员提交的订单可能会触发STP,具体取决于吃单订单的STP模式。

用户可以通过API端点GET fapi/v2/account (REST API)确定账户是否属于同一个“tradeGroupId”。

如果相应的值为-1,则表示账户未设置“tradeGroupId”,因此只有同一账户的不同订单之间会触发STP。

哪些币对支持STP?

GET fapi/v1/exchangeInfo中的所有币对都支持STP。

哪些订单类型支持STP?

当“生效时间”(timeInForce)设置为GTC/IOC/GTD时,以下订单类型支持STP:

  • 限价单
  • 市价单
  • 止盈单
  • 市价止盈止损单
  • 市价止盈单
  • 市价追踪止盈止损单

请注意,当“生效时间”(timeInForce)设置为FOK或GTX时,STP无效。

改单是否支持STP?

不,改单暂不支持STP。

如何判断订单是否因触发STP而失效?

请确认订单状态是否显示为“EXPIRED_IN_MATCH”。在用户数据流推送事件“ORDER_TRADE_UPDATE”中,如果订单因触发STP而失效,字段X将显示为“EXPIRED_IN_MATCH”。

{  "e":"ORDER_TRADE_UPDATE",      // Event Type  "E":1568879465651,             // Event Time  "T":1568879465650,             // Transaction Time  "o":{                                "s":"BTCUSDT",               // Symbol    "c":"TEST",                  // Client Order Id      // special client order id:      // starts with "autoclose-": liquidation order      // "adl_autoclose": ADL auto close order      // "settlement_autoclose-": settlement order for delisting or delivery    "S":"SELL",                  // Side    "o":"TRAILING_STOP_MARKET",  // Order Type    "f":"GTC",                   // Time in Force    "q":"0.001",                 // Original Quantity    "p":"0",                     // Original Price    "ap":"0",                    // Average Price    "sp":"7103.04",              // Stop Price. Please ignore with TRAILING_STOP_MARKET order    "x":"EXPIRED",               // Execution Type    "X":"EXPIRED_IN_MATCH",      // Order Status    "i":8886774,                 // Order Id    "l":"0",                     // Order Last Filled Quantity    "z":"0",                     // Order Filled Accumulated Quantity    "L":"0",                     // Last Filled Price    "N":"USDT",                  // Commission Asset, will not push if no commission    "n":"0",                     // Commission, will not push if no commission    "T":1568879465650,           // Order Trade Time    "t":0,                       // Trade Id    "b":"0",                     // Bids Notional    "a":"9.91",                  // Ask Notional    "m":false,                   // Is this trade the maker side?    "R":false,                   // Is this reduce only    "wt":"CONTRACT_PRICE",       // Stop Price Working Type    "ot":"TRAILING_STOP_MARKET", // Original Order Type    "ps":"LONG",                 // Position Side    "cp":false,                  // If Close-All, pushed with conditional order    "AP":"7476.89",              // Activation Price, only pushed with TRAILING_STOP_MARKET order    "cr":"5.0",                  // Callback Rate, only pushed with TRAILING_STOP_MARKET order    "pP": false,                 // ignore    "si": 0,                     // ignore    "ss": 0,                     // ignore    "rp":"0"                     // Realized Profit of the trade    "V": "NONE".                 // selfTradePreventionMode    "pm":"QUEUE"                 // price match type    "gtd":1768879465650          // good till date   }}

STP示例

假设以下示例中的所有订单均来自同一账户。

情景1:用户发送一个采用“selfTradePreventionMode:NONE”设置的新订单,该订单将与该用户在订单簿上已有的另一个订单撮合。

Maker Order: symbol=BTCUSDT side=BUY type=LIMIT quantity=1 price=20000 selfTradePreventionMode=NONE Taker Order: symbol=BTCUSDT side=SELL type=LIMIT quantity=1 price=20000 selfTradePreventionMode=NONE

结果:不会触发STP,订单将正常撮合。

挂单订单的状态:

{    "orderId": 292864713,    "symbol": "BTCUSDT",    "status": "FILLED",    "clientOrderId": "43N239GaUaqshfG7825184",    "price": "20000",    "avgPrice": "20000",    "origQty": "1",    "executedQty": "1",    "cumQty": "1",    "cumQuote": "20000",    "timeInForce": "GTC",    "type": "LIMIT",    "reduceOnly": false,    "closePosition": false,    "side": "BUY",    "positionSide": "BOTH",    "stopPrice": "0",    "workingType": "CONTRACT_PRICE",    "priceMatch": "NONE",    "selfTradePreventionMode": "NONE",    "goodTillDate": 0,    "priceProtect": false,    "origType": "LIMIT",    "updateTime": 1692849639460}

吃单订单的状态:

{    "orderId": 292864714,    "symbol": "BTCUSDT",    "status": "FILLED",    "clientOrderId": "43N239GaUaqshfG7825184",    "price": "20000",    "avgPrice": "20000",    "origQty": "1",    "executedQty": "1",    "cumQty": "1",    "cumQuote": "20000",    "timeInForce": "GTC",    "type": "LIMIT",    "reduceOnly": false,    "closePosition": false,    "side": "SELL",    "positionSide": "BOTH",    "stopPrice": "0",    "workingType": "CONTRACT_PRICE",    "priceMatch": "NONE",    "selfTradePreventionMode": "NONE",    "goodTillDate": 0,    "priceProtect": false,    "origType": "LIMIT",    "updateTime": 1692849639460}

情景2:用户发送一个采用“EXPIRE_MAKER”设置的订单,该订单本将与该用户在订单簿上已有的其他订单撮合。

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

结果:由于触发STP,订单簿上已有的订单会失效,吃单订单将继续保留在订单簿中。

挂单订单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": "NONE",    "goodTillDate": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

挂单订单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": "NONE",    "goodTillDate": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

吃单订单:

{    "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": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

情景3:用户发送一个采用“EXPIRE_TAKER”设置的订单,该订单本将与该用户在订单簿上已有的其他订单撮合。

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

结果:订单簿上的现有订单将保留,而吃单订单将失效。

挂单订单1:

{    "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": "NONE",    "goodTillDate": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

挂单订单2:

{    "orderId": 292864711,    "symbol": "BTCUSDT",    "status": "NEW",    "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": "NONE",    "goodTillDate": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

吃单订单:

{    "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": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

情景4:用户在订单簿上已有一个订单,然后发送一个采用“EXPIRE_BOTH”设置的新订单,该订单本将与订单簿上的现有订单撮合。

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

结果:两个订单均将失效。

挂单订单:

{    "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": "NONE",    "goodTillDate": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

吃单订单:

{    "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": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

情景5:用户在订单簿上已有一个采用“EXPIRE_MAKER”设置的订单,然后发送一个采用“EXPIRE_TAKER”设置的新订单,该订单本将与订单簿上的现有订单撮合。

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

结果:由于触发吃单订单的STP模式,吃单订单将失效。

挂单订单:

{    "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": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

吃单订单:

{    "orderId": 292864712,    "symbol": "BTCUSDT",    "status": "EXPIRED_IN_MATCH",    "clientOrderId": "testTaker1",    "price": "20000",    "avgPrice": "0.0000",    "origQty": "1",    "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": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

情景6:用户发送一个采用“EXPIRE_MAKER”设置的市价单,该订单本将与订单簿上的现有订单撮合。

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

结果:由于触发STP,订单簿上的现有订单将失效,状态显示为“EXPIRED_IN_MATCH”。由于订单簿的流动性较低,新订单也将失效,状态显示为“EXPIRED”。

挂单订单:

{    "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": 0,    "priceProtect": false,    "origType": "LIMIT",    "time": 1692849639460,    "updateTime": 1692849639460}

吃单订单:

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