# TopOne OpenAPI 代理商跟单交易接口(v1) ## 更新日誌 ### 2024-11-21 - 增加代理商跟單接口 - 開倉 `POST /gateway/v1/openapi/agent/copy-trading/order` - 平倉 `POST /gateway/v1/openapi/agent/copy-trading/order/close` - 倉位清單 `GET /gateway/v1/openapi/future/copy-trading/position` - 账户余额接口 `GET /gateway/v1/openapi/wallet/copy-trading/balance` ## 基本信息 ### 服务器BASE URL #### 联调环境 - https://pre.top.one #### 生产环境 - https://top.one ### 接口访问规则 - 需要提前准备APIKEY和APISECRET(申请通过后,TOPONE通过邮件形式发送给代理商) - 接口请求频率限制为每秒钟10次(单用户下所有APIKEY) - 每个接口均需使用APIKEY和APISECRET计算签名signature ### 接口签名实现说明 - signature根据每个请求的timestamp, method, path, body计算sha256而来 - 时间戳为当前时间,超过1分钟的请求签名会被拒绝,不建议使用未来时间签名 - 如果是get请求需要忽略body - path需要包含query字段 #### example-golang ```go import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "fmt" ) func GenerateSignature(method, path, body string, timestamp int64, secret string) (string, error) { // 组合签名原文 var message string if method == "GET" { message = fmt.Sprintf("%d%s%s", timestamp, method, path) } else { message = fmt.Sprintf("%d%s%s%s", timestamp, method, path, body) } // 使用 HMAC-SHA256 算法进行签名 h := hmac.New(sha256.New, []byte(secret)) if _, err := h.Write([]byte(message)); err != nil { return "", err } // 返回签名结果 signature := hex.EncodeToString(h.Sum(nil)) return signature, nil } ``` #### example-python ```python import hmac import hashlib import time def generate_signature(method, path, body, timestamp, secret): """ 生成 HMAC-SHA256 签名 Args: method: HTTP 方法 path: 请求路径 body: 请求体 timestamp: 时间戳 Returns: str: 签名结果 """ # 组合签名原文 message = f"{timestamp}{method}{path}" if method != "GET": message += body # 使用 HMAC-SHA256 算法进行签名 signature = hmac.new(secret.encode('utf-8'), message.encode('utf-8'), hashlib.sha256).hexdigest() return signature ``` #### example-java ```java import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; public class HmacSha256 { public static String generateSignature(String method, String path, String body, long timestamp, String secret) throws Exception { // 组合签名原文 StringBuilder messageBuilder = new StringBuilder(); messageBuilder.append(timestamp).append(method).append(path); if (!method.equals("GET")) { messageBuilder.append(body); } String message = messageBuilder.toString(); // 使用 HMAC-SHA256 算法进行签名 SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8),"HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(signingKey); byte[] rawHmac = mac.doFinal(message.getBytes(StandardCharsets.UTF_8)); return bytesToHex(rawHmac); } private static String bytesToHex(byte[] bytes) { StringBuilder hexString = new StringBuilder(); for (byte b : bytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString(); } } ``` ### 通用返回接口示例 ```json { "status": { "code": 102000, "error": {}, "messages": "success" }, "data": { } } ``` - code = 102000表示请求成功,否则为请求失败 - 接口返回的数据在data字段中 ## 代理商跟單-下委託單 ### HTTP请求 **Path:** /gateway/v1/openapi/agent/copy-trading/order **Method:** POST ### 请求参数 #### Headers | 参数名称 | 参数值 | 是否必须 | 备注 | | ------------ | ------------ | ------------ | ------------ | | Content-Type | application/json | 是 | | |signature|8bde81ceaff50e7fe2a...|是| 簽名| | X-MBX-APIKEY | ee9aedd6a1b2a3a610fa2b1dab333d46 | 是 | ApiKey | | timestamp | 1732003370 | 是 | 請求時間戳 | #### Query 无 #### Body ```json! { "pair": "BTCUSDT", // 填入支持带单的币对 "side": "sell", // 目前只支持单向买多卖空,即buy+long,或者sell+short "position_side": "long", // 参考side字段配置 "margin": 5.0, // 1.0 <= margin <= 1000 "leverage": 1, // 1 <= 杠杆倍数 <= 1000 "take_profit_price": 0.0, // long必须大于市价,short必须小于市价,填0则不触发 "stop_loss_price": 0.0, // long必须小于市价,short必须大于市价,填0则不触发 "price": 0.0, // price=0则为市价单,否则为限价单(需谨慎检查对应价格) "is_simulate": false // 是否为模拟盘交易 } ``` ### 响应示例 ```json! { "status": { "code": 102000, "error": {}, "messages": "success" }, "data": { "order_id": "e0bf978a-b383-4e85-ba71-7684f81abcc7", "position_order_id": "", "pair": "BTCUSDT", "contract_type": 1, "uid": "00000034", "side": "sell", "position_side": "long", "quantity": "0.01682", "order_quantity": "0.01682", "leverage": 10, "price_type": "market", "price": "59307", "open_fee": "0", "pre_close_fee": "0", "take_profit_price": "0", "stop_loss_price": "0", "pay_margin": "100", "status": 1, "is_simulate": 0, "close_time": "", "create_time": "2024-01-01T12:23:34Z", "update_time": "2024-01-01T12:23:45Z", "copy_trade": { "success": [ { "order_id": "e0bf978a-b383-4e85-ba71-7684f81abcc7", "position_order_id": "", "pair": "BTCUSDT", "contract_type": 1, "uid": "00000034", "side": "sell", "position_side": "long", "quantity": "0.01682", "order_quantity": "0.01682", "leverage": 10, "price_type": "market", "price": "59307", "open_fee": "0", "pre_close_fee": "0", "take_profit_price": "0", "stop_loss_price": "0", "pay_margin": "100", "status": 1, "is_simulate": 0, "close_time": "", "create_time": "2024-01-01T12:23:34Z", "update_time": "2024-01-01T12:23:45Z" } ], "fail": [ "00001", "00002" ] } } } ``` #### 接口描述 - ~~quantity(數量下單)與margin(保證金下單) 只能擇一選擇~~ - 普通合約才有止盈止損價,得勁沒有 - position_side 多單 止盈>成交價>止損 空單 止盈<成交價<止損 - 會根據leverage自動判斷是普通/得勁合約 <h5>Error</h5> <table> <thead> <tr> <th>Error Code</th> <th>Message</th> </tr> </thead> <tbody> <tr> <td>836004</td> <td>保證金不足(餘額不足)</td> </tr> <tr> <td>837000</td> <td>目前合約無法開倉</td> </tr> <tr> <td>837004</td> <td>用戶持倉數已滿</td> </tr> <tr> <td>837005</td> <td>平台持倉數量已達上限</td> </tr> <tr> <td>837006</td> <td>標記價格於最新價格差價過大</td> </tr> <tr> <td>837007</td> <td>價格有問題(精度,限價止盈止損價格有問題)</td> </tr> <tr> <td>837010</td> <td>系統造市正在運作,不可下單</td> </tr> <tr> <td>837011</td> <td>用戶觸發風控,暫時停止交易</td> </tr> <tr> <td>837002</td> <td>止盈倍數有問題(超過上限)</td> </tr> <tr> <td>904059</td> <td>開倉功能被關閉</td> </tr> </tbody> </table> <h5>contract_type</h5> <table> <thead> <tr> <th>type</th> <th>comment</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>普通合約</td> </tr> <tr> <td>2</td> <td>閃電合約</td> </tr> </tbody> </table> <h5>position_side</h5> <table> <thead> <tr> <th>code</th> <th>comment</th> </tr> </thead> <tbody> <tr> <td>long</td> <td>多</td> </tr> <tr> <td>short</td> <td>空</td> </tr> </tbody> </table> <h5>side</h5> <table> <thead> <tr> <th>code</th> <th>comment</th> </tr> </thead> <tbody> <tr> <td>buy</td> <td>買</td> </tr> <tr> <td>sell</td> <td>賣</td> </tr> </tbody> </table> <h5>price_type</h5> <table> <thead> <tr> <th>type</th> <th>comment</th> </tr> </thead> <tbody> <tr> <td>market</td> <td>市價</td> </tr> <tr> <td>limit</td> <td>限價</td> </tr> </tbody> </table> <h5>status</h5> <table> <thead> <tr> <th>status</th> <th>comment</th> </tr> </thead> <tbody> <tr> <td>0</td> <td>未成交</td> </tr> <tr> <td>1</td> <td>成交</td> </tr> <tr> <td>2</td> <td>取消</td> </tr> <tr> <td>3</td> <td>異常</td> </tr> </tbody> </table> <h5>組合關係</h5> <table> <thead> <tr> <th>side</th> <th>position_side</th> <th>price</th> <th>comment</th> </tr> </thead> <tbody> <tr> <td>buy</td> <td>long</td> <td>100</td> <td>買限價多單</td> </tr> <tr> <td>buy</td> <td>long</td> <td>0</td> <td>買市價多單</td> </tr> <tr> <td>sell</td> <td>long</td> <td>100</td> <td>平倉限價多單</td> </tr> <tr> <td>sell</td> <td>long</td> <td>0</td> <td>平倉市價多單</td> </tr> <tr> <td>buy</td> <td>short</td> <td>100</td> <td>平倉限價空單</td> </tr> <tr> <td>buy</td> <td>short</td> <td>0</td> <td>平倉市價空單</td> </tr> <tr> <td>sell</td> <td>short</td> <td>100</td> <td>買限價空單</td> </tr> <tr> <td>sell</td> <td>short</td> <td>0</td> <td>買市價空單</td> </tr> </tbody> </table> ## 代理商跟單-平倉 ### HTTP请求 **Path:** /gateway/v1/openapi/agent/copy-trading/order/close **Method:** POST ### 请求参数 #### Headers | 参数名称 | 参数值 | 是否必须 | 备注 | | ------------ | ------------ | ------------ | ------------ | | Content-Type | application/json | 是 | | |signature|8bde81ceaff50e7fe2ad69e...|是| 簽名| | X-MBX-APIKEY | ee9aedd6a1b2a3a610fa2b1dab333d46 | 是 | ApiKey | | timestamp | 1732003370 | 是 | 請求時間戳 | #### Query 无 #### Body ```json! { "order_id": "TX0000001" //required } ``` ### 响应示例 ```json! { "status": { "code": 102000, "error": {}, "messages": "success" }, "data": { } } ``` ## 代理商跟單-倉位清單 ### HTTP请求 **Path:** /gateway/v1/openapi/future/copy-trading/position **Method:** GET ### 请求参数 #### Headers | 参数名称 | 参数值 | 是否必须 | 备注 | | ------------ | ------------ | ------------ | ------------ | | Content-Type | application/json | 是 | | |signature|8bde81ceaff50e7fe2ad69e...|是| 簽名| | X-MBX-APIKEY | ee9aedd6a1b2a3a610fa2b1dab333d46 | 是 | ApiKey | | timestamp | 1732003370 | 是 | 請求時間戳 | #### Query | 参数名称 | 是否必须 | 类型 | 备注 | | ------------ | ------------ | ------------ | ------------ | | page_index | 是 | int | 第幾頁(默認1) | | page_size | 是 | int | 每頁多少筆 | | status | 否 | int | 倉位狀態 | | start_time | 否 | int | 建倉開始時間 | | end_time | 否 | int | 建倉結束時間 | | pair | 否 | string | 交易對 | | side | 否 | string | 多/空 | | is_simulate | 否 | int | 是否為模擬單 默認為(不是) 1:是 2:不是 | | create_platform | 否 | string | "agent"=帶單, "copy-trade"=跟單 | | position_id | 否 | string | 倉位ID | #### Body 無 ### 响应示例 ```json! { "status": { "code": 102000, "error": {}, "messages": "success" }, "data": { "list": [ { "order_id": "TX000000001", "uid": "00001", "pair": "BTCUSDT", "crypto": "BTC", "crypto_price_unit": "USDT", "side": "long", "contract_type": 1, "leverage": 10, "quantity": "100.1", "number": 123466, "price": "529.01", "price_type": "market", "take_profit_price": "600.01", "stop_loss_price": "450.01", "total_funding_fee": "100", "init_margin": "100", "margin": "20.01", "pay_margin": "120", "status": 1, "create_platform": "copy-trade", "create_time": "2024-05-06T19:23:36Z", "close_time": "2024-05-06T19:23:36Z" } ], "page": { "total": 1, "index": 1, "size": 20 } } } ``` ### 响应說明 | 名称 | 類型 | 備註 | 示例 | | ------------ | ------------ | ------------ | ------------ | | order_id | string | 訂單ID | | | uid | string | 用戶ID | | | pair | string | 幣對 | BTCUSDT | | crypto | string | 交易幣 | BTC | | crypto_price_unit | string | 計價幣 | USDT | | side | string | 方向 | | | contract_type | number | 合約類型 | | | leverage | number | 槓桿倍數 | | | quantity | string | 數量(幣量) | | | number | number |總張數=數量/每張多少單位 | | | price | string | 開倉價 | | | price_type | string | 下單價格類型(市價/限價) | | | close_price | string | 平倉價 | | | take_profit_price | string | 止盈價 | | | stop_loss_price | string | 止損價 | | | total_funding_fee | string | 資金費 | | | margin | string | 倉位保證金 | | | init_margin | string | 倉位佔用保證金 | | | pay_margin | string | 開倉成本(開倉保證金) | | | status | number | 倉位狀態 | 1=開倉中, 2=已平倉 | | create_platform | string | 開單平台 | "agent"=帶單, "copy-trade"=跟單 | | create_time | string | 撮合/建立時間 | | | close_time | string | 平倉時間 | | ## 代理商跟單-账户余额 ### HTTP请求 **Path:** /gateway/v1/openapi/wallet/copy-trading/balance **Method:** GET ### 请求示例 #### Headers | 参数名称 | 参数值 | 是否必须 | 备注 | | ------------ | ------------ | ------------ | ------------ | | Content-Type | application/json | 是 | | |signature|8bde81ceaff50e7fe2ad69e...|是| 簽名| | X-MBX-APIKEY | ee9aedd6a1b2a3a610fa2b1dab333d46 | 是 | ApiKey | | timestamp | 1732003370 | 是 | 請求時間戳 | #### Query 無 #### Body 無 ### 响应示例 ```json! { "status": { "code": 102000, "error": {}, "messages": "success" }, "data": { "list": [ { "uid": "OOOOOTRU", "trading_available": "999016.0075683", // 合約帳戶可用金額 "trading_freeze": "0", // 合約帳戶凍結保證金 "realized_profit_and_loss": "0" // 已實現盈虧金額 }, { "uid": "OOOOJOKT", "trading_available": "0", "trading_freeze": "0", "realized_profit_and_loss": "0" }, { "uid": "OOOOOEDV", "trading_available": "99000000", "trading_freeze": "0", "realized_profit_and_loss": "0" }, { "uid": "OOOOOEJV", "trading_available": "0", "trading_freeze": "0", "realized_profit_and_loss": "0" } ] } } ```