自我交易预防 (Self Trade Prevention - STP) 常见问题
什么是 Self Trade Prevention - STP?
自我交易预防是指阻止订单与来自同一账户或者同一 tradeGroupId 账户的订单交易。
什么是自我交易(self-trade)?
在以下任一情况下都可能发生自我交易:
- 属于同一账户的订单之间交易。
- 属于相同
tradeGroupId的账户的订单之间交易。
STP 触发时会发生什么?
如果订单会触发自我交易,系统将执行三种可能的模式:
EXPIRE_TAKER - 此模式通过立即使吃单者(taker)的剩余数量过期来预防交易。
EXPIRE_MAKER - 此模式通过立即使潜在挂单者(maker)的剩余数量过期来预防交易。
EXPIRE_BOTH - 此模式通过立即同时使吃单和挂单者的剩余数量过期来预防交易。
STP 的发生取决于 Taker 订单 的 STP 模式。
因此,订单薄上的订单的 STP 模式不再有效果,并且将在所有未来的订单处理中被忽略。
如何在订单上设置自我交易预防 ?
自我交易预防可以通过下单接口的参数selfTradePreventionMode设置,相关接口如下:
- POST
/eapi/v1/order - POST
/eapi/v1/batchOrders
什么是交易组 Id(Trade Group Id)?
属于同一 tradeGroupId 的账户被视为同一交易组。相同交易组成员提交的订单有 STP 资格。
每个账户可以从 GET /eapi/v1/accountConfig(REST API)确认账户是否属于同一个 tradeGroupId。
如果该值为 -1,这表示账户未设置 tradeGroupId,因此 STP 只能发生在同一账户的订单之间。
用户可以通过子账户API管理页面将子账户分组到同一个tradeGroupId。
如何知道有那些交易对支持 STP?
所有GET /eapi/v1/exchangeInfo中的交易对都支持selfTradePreventionMode。
哪些订单类型支持 STP?
所有类型订单在Time in force(timeInForce)设置为GTC/ IOC/ GTD时支持STP。 当Time in force(timeInForce)为FOK 或 GTX时订单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":"BTC-260228-70000-C", // 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": "EXPIRE_MAKER", // selfTradePreventionMode
"pm":"QUEUE", // price match type
"gtd":1768879465650 // good till date
}
}
STP 的一些示例:
假设以下示例的所有订单都是在同一个账户下发送。
情况 A - 用户发送带有 EXPIRE_MAKER 的订单,该订单将与订单薄上已有的订单撮合。
Maker 订单 1: symbol=BTC-260228-70000-C side=BUY type=LIMIT quantity=1 price=51 selfTradePreventionMode=EXPIRE_MAKER
Taker 订单 1: symbol=BTC-260228-70000-C side=SELL type=LIMIT quantity=2 price=50 selfTradePreventionMode=EXPIRE_MAKER
结果 : 由于 STP,订单薄上的订单将会过期,taker 订单将继续在订单薄。
Maker 订单
{
"orderId":4611875134427365378,
"symbol": "BTC-260228-70000-C",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testMaker1",
"price": "51",
"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 订单的响应
{
"orderId":4611875134427365379,
"symbol": "BTC-260228-70000-C",
"status": "FILLED",
"clientOrderId": "testTaker1",
"price": "50",
"avgPrice": "50",
"origQty": "2",
"executedQty": "2",
"cumQuote": "50",
"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
}
情况 B - 用户发送带有 EXPIRE_TAKER 的订单,该订单将与订单薄上已有的订单撮合。
Maker 订单 1: symbol=BTC-260228-70000-C side=BUY type=LIMIT quantity=1 price=51 selfTradePreventionMode=EXPIRE_TAKER
Taker 订单 1: symbol=BTC-260228-70000-C side=SELL type=LIMIT quantity=2 price=50 selfTradePreventionMode=EXPIRE_TAKER
结果 : 已经在订单薄上的订单将保留,而taker订单将过期。
Maker 订单
{
"orderId":4611875134427365378,
"symbol": "BTC-260228-70000-C",
"status": "NEW",
"clientOrderId": "testMaker1",
"price": "51",
"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_TAKER",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}
Taker 订单的状态
{
"orderId":4611875134427365379,
"symbol": "BTC-260228-70000-C",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testTaker1",
"price": "50",
"avgPrice": "0.0000",
"origQty": "2",
"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
}
情况 C - 用户发送带有 EXPIRE_BOTH 的订单,该订单将与订单薄上已有的订单撮合。
Maker 订单: symbol=BTC-260228-70000-C side=BUY type=LIMIT quantity=1 price=51 selfTradePreventionMode=EXPIRE_BOTH
Taker 订单: symbol=BTC-260228-70000-C side=SELL type=LIMIT quantity=3 price=50 selfTradePreventionMode=EXPIRE_BOTH
结果 : 两个订单都将过期。
Maker 订单
{
"orderId":4611875134427365378,
"symbol": "BTC-260228-70000-C",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testMaker1",
"price": "51",
"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_BOTH",
"goodTillDate": "null",
"priceProtect": false,
"origType": "LIMIT",
"time": 1692849639460,
"updateTime": 1692849639460
}
Taker 订单
{
"orderId":4611875134427365379,
"symbol": "BTC-260228-70000-C",
"status": "EXPIRED_IN_MATCH",
"clientOrderId": "testTaker1",
"price": "50",
"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
}