使用 欧易 V5 API 的技巧和诀窍(2)
引言
欧易在推出统一账户交易系统的同时,亦把 API 由 V3 升级到了 V5,带来了更多和更完善的功能。在第 1 部分,我们讲解了 V5 API 相对于 V3 API 有什么改动和交易前设置账户时的技巧和诀窍。这次,我们会讲解在使用 V5 API 交易时有哪些技巧和诀窍。
交易
交易模式
欧易统一账户交易系统的全仓/逐仓设置更为弹性,我们可以同时以全仓和逐仓交易同一产品。因此,我们需要在下单时指定该订单的交易模式(tdMode 字段)。
各种情景下 tdMode 所需的值:
示例
假设我们有以下的设置和订单需求:
- 账户模式:跨币种保证金
- 持仓模式:单向持仓
- 产品:BTC-USDT-SWAP
- 保证金模式:全仓
- 订单方向:买入(开多)
- 订单类型:限价单
- 委托价格:50,912.4 USDT
- 委托数量:1 张
查找上表得知 tdMode 字段应填上“cross”。
我们建议下单时填上客户自定义订单 ID(clOrdId 字段),识别订单时会更为容易。客户自定义订单 ID 需由字母与数字或纯字母组成,必须以字母开头,区分大小写,最长 32 位。
此示例我们会在 clOrdId 字段填上 testBTC0123。
订阅订单频道
下单前,我们应先使用 WebSocket 订阅订单频道,这样我们才能够监察订单状态(如等待成交、完全成交)和作出相应的操作(如在完全成交后下新单)。
V5 API 的订单频道提供多种维度的订阅。要订阅以上 BTC-USDT-SWAP 订单的数据,我们可在连接到和登入私有 WebSocket 后,传送下表任一请求:
我们亦可以把 instType 参数填上 ANY,一次性订阅所有产品类型的订单更新。
注:订单频道不设首次订阅全量数据推送,只会在订单状态改变时(如由等待成交到撤单成功)推送该订单的更新。
换言之,我们无法在订阅订单频道时得知当时的订单数据。要获取订阅订单频道前未完成订单的数据,可通过以下的 REST API 查看:
GET /api/v5/trade/orders-pending |
下单
在订阅订单频道后,我们便可以准备 BTC-USDT-SWAP 订单的下单。
V5 API 提供 REST 和 WebSocket 两种协议去下单。
REST
我们可以通过以下的 REST API 下单,服务器收到请求后会返回订单 ID(ordId 字段)。
注:这只代表交易所已成功收取请求,把订单 ID 指派到该订单。这时候订单有可能还没在线,我们需要进一步检查订单状态去确认。
WebSocket
我们亦可以通过 WebSocket 下单,理论上比 REST 更有效率和节约资源。
由于 WebSocket 操作为异步通信,我们需要提供信息 ID(id 字段)以便识别其返回。
于私有 WebSocket 登陆后,传送以下 WebSocket 信息:
服务器收到请求后,会连同信息 ID(即 NEWtestBTC012)返回结果,并附上交易所指派的订单 ID(ordId 字段):
注:这只代表交易所已成功收取请求,把订单 ID 指派到该订单。这时候订单有可能还没在线,我们需要进一步检查订单状态去确认。
检查订单状态
下单后,我们会预期在 WebSocket 订单频道收到该订单状态为“live”的信息。
信息示例(以产品类型 + 标的指数维度订阅订单频道):
订单完全成交后,我们会收到以下的推送信息示例,订单状态变更为“filled”,并填上其他有关成交的字段。
信息还会附上最新成交 ID (tradeId 字段)。这字段可用于与持仓对账,会在稍后的章节讲解。
改单
V5 API 已支持所有产品类型的改单,让您修改订单的价格(newPx 字段)和/或数量(newSz 字段)。另外 API 也提供 cxlOnFail 参数,设置修改失败时自动撤单。
REST:
POST /api/v5/trade/amend-order |
WebSocket 业务操作请求参数:
“op”: “amend-order” |
与下单相似,我们应会收到服务器相应 REST / WebSocket 的成功返回,然后于 WebSocket 订单频道收到已填上“amendResult”字段的订单推送更新。
注:订单完全成交或撤单已成功时不能改单。
撤单
我们可以以类似的方式,通过 REST 或 WebSocket 撤单。
REST:
POST /api/v5/trade/cancel-order |
WebSocket 业务操作请求参数:
“op”: “cancel-order” |
同样,我们应会收到服务器相应 REST / WebSocket 的成功返回。当我们从 WebSocket 订单频道收到订单状态为“canceled”的推送更新时,才代表订单撤单成功。
注:订单完全成交或撤单已成功时不能撤单。
批量操作
下单、改单、撤单均支持批量操作,每次最多 20 张订单。受惠于统一 API,同一批量操作的订单可包括不同的产品类型。
REST:
下单 | POST /api/v5/trade/batch-orders |
改单 | POST /api/v5/trade/amend-batch-orders |
撤单 | POST /api/v5/trade/cancel-batch-orders |
WebSocket 业务操作请求参数:
下单 | “op”: “batch-orders” |
改单 | “op”: “batch-amend-orders” |
撤单 | “op”: “batch-cancel-orders” |
批量操作容许部分订单操作成功。在收到返回后,我们应检查返回结果内每个订单的 sCode 和 sMsg 字段来判段订单的执行结果。
账户和持仓
统一账户
欧易统一账户交易系统下只有一个所有产品类型共用的统一账户。因此,使用 V5 API 交易时不再会有币币、币币杠杆、交割、永续、期权的独立账户。
WebSocket 订阅
我们建议使用 WebSocket 订阅账户频道收取账户更新。账户频道设有可选参数 ccy,让我们可以仅收取指定账户币种的信息。
连接到私有 WebScoket 和登入后的请求和返回示例:
首次订阅全量数据
与订单频道不同,账户频道首次订阅会推送全量数据,推送币种层面资产不为 0 的账户信息。币种层面资产不为 0 指币种总权益(eq 字段)、可用保证金(availEq 字段)、可用余额(availBal 字段)任一字段不为 0。
假设账户的 BTC 和 USDT 币种层面资产不为 0,而账户模式为跨币种保证金模式,我们应收到账户频道以下的信息示例:
后续推送
之后,我们会根据以下情况收到账户数据推送:
事件触发推送 | 下单、撤单等事件会触发推送。多项事件(如同时间有多个订单成交)有可能会聚合成单个账户信息推送。 仅推送受事件变更的币种,包括币种资产变为 0。 |
定时推送 | 定时推送,目前为每 10 秒推送一次。 与首次订阅一样,推送全量数据,即推送所有币种(或于 ccy 参数指定的币种)层面资产不为 0 的账户信息。 |
REST
我们亦可以通过 REST API 查看币种层面资产不为 0 的账户余额:
GET /api/v5/account/balance |
REST API 亦提供可选参数 ccy,支持单个币种(如 BTC)或多个以逗号分隔的币种(如 BTC,USDT,ETH)查询,最多 20 个。
示例:
GET /api/v5/account/balance?ccy=BTC,USDT,ETH |
值得一提的是,当我们于 ccy 参数指定币种时,无论该币种层面资产是否为 0,REST API 均会返回该币种的数据,与 WebSocket 账户频道不同。这只适用于曾经持有的币种。
最大可用数量
跨币种保证金模式下,启用自动借币能让您从 欧易 借币,以多于币种余额的数量买入/卖出产品。
在这种情况下,我们便会想知道该产品最大的买入/卖出数量为多少。我们可以轮询以下的 REST API 得知最大可用数量(包括可用余额和交易所的最大可借):
GET /api/v5/account/max-avail-size |
跨币种保证金模式下,BTC-USDT 全仓的请求和返回示例:
币币的 availBuy 为计价货币,availSell 为交易货币。
以上的返回结果表示 BTC-USDT 最大买入可用数量为 213,800.42 USDT,最大卖出可用数量为 1.35394052 BTC。这应与网页上交易时显示的数量一样。
持仓
V5 API 下所有产品也共用统一的持仓 API。我们建议您使用 WebSocket 获取持仓信息更新。
WebSocket 订阅
与订单频道类似,V5 API 的持仓频道提供多种维度的订阅。
要订阅以上 BTC-USDT-SWAP 持仓的数据,我们可在连接到和登入私有 WebSocket 后,传送下表任一请求:
我们亦可以把 instType 参数填上 ANY,一次性订阅所有产品类型的持仓更新。
首次订阅全量数据
持仓频道首次订阅会推送全量数据,推送持仓数量不为 0 的持仓信息。持仓数量不为 0 指 pos 字段大于或小于 0。
我们继续沿用先前章节的 BTC-USDT-SWAP 全仓订单(单向持仓模式)例子。在订阅持仓频道(产品类型 + 标的指数维度)后,我们应收到以下的推送信息示例:
后续推送
之后,与账户频道相似,我们会根据以下情况收到持仓数据推送:
事件触发推送 | 开仓、平仓等事件会触发推送。多项事件(如同时间有多个订单成交)有可能会聚合成单个持仓信息推送。 仅推送受事件变更的持仓,包括平仓(即持仓数量变为 0)。 |
定时推送 | 定时推送,目前为每 10 秒推送一次。 与首次订阅一样,推送全量数据,即推送订阅维度上指定的所有不为 0 的持仓。 |
持仓 ID
您可能会发现每项持仓数据均设有持仓 ID 字段(posId)。这字段可以用作填写 REST API 可选查询参数,会在下一章节讲解。
持仓 ID 由 mgnMode + posSide + instId + ccy 这几个字段所产生,可让您唯一地识别同一个账户内的持仓。持仓 ID 不会因平仓及再开仓而变动。
REST
我们亦可以通过 REST API 查看持仓数量不为 0 的持仓信息:
GET /api/v5/account/positions |
REST API 提供以下维度查询:
维度 | 示例 |
产品类型 | GET /api/v5/account/positions?instType=SWAP |
产品 ID | GET /api/v5/account/positions?instId=BTC-USDT-SWAP |
持仓 ID(单个) | GET /api/v5/account/positions?posId=287999792370819074 |
持仓 ID(多个,最多 20 个) | GET /api/v5/account/positions?posId=287999792370819074,289098391880081414 |
值得一提的是,当我们于 posId 参数指定持仓时,无论持仓是否已平仓,REST API 均会返回该持仓的数据,与 WebSocket 持仓频道不同。这只适用于曾经开仓的持仓。
订单成交推送与持仓的对账
运用持仓频道新增的最新成交 ID (tradeId 字段),我们可以进行订单频道成交推送与持仓的对账。这样做法其中一个案例就是我们想从订单成交推算出现有的持仓数量。
新的订单成交均会指派较新的成交 ID。利用这一特性,我们可用成交 ID 匹配相应的持仓/订单成交,并以成交 ID 的数字比较哪项数据较新。
不过,我们需要注意下列事项:
- 多个持仓变化有可能会聚合成单个持仓信息推送,即持仓信息只有最新的成交 ID,并非每一个订单成交更新均能与持仓信息匹配
- 强平/强减或 ADL 不会推送订单更新(因订单为系统所拥有)
- 因强平/强减或 ADL 而触发的持仓更新不会更新 tradeId
要准确地进行订单成交推送与持仓的对账,我们必需考虑以上的注意事项,除比较 tradeId 外还需比较持仓数量(或比较持仓更新时间 uTime 字段)。
我们来看看以下的推送序列示例。假设下列都是同样产品及同样保证金模式的数据,持仓模式为单向持仓。
序列 | 频道 | 数据 | 对账后的持仓 |
1 | order (订单) | fillSz=20, side=buy, tradeId=150 | 20 |
2 | positions (持仓) | pos=20, tradeId=150, uTime=1614859751636 | 20 |
3 | positions (持仓) | pos=18, tradeId=151, uTime=1614859752637 | 18 |
4 | order (订单) | fillSz=2, side=sell, tradeId=151 | 18 |
5 | order (订单) | fillSz=3, side=sell, tradeId=156 | 15 |
6 | order (订单) | fillSz=1, side=sell, tradeId=158 | 14 |
7 | positions (持仓) | pos=10, tradeId=163, uTime=1614859755037 | 10 |
8 | order (订单) | fillSz=1, side=sell, tradeId=159 | 10 |
9 | order (订单) | fillSz=3, side=sell, tradeId=163 | 10 |
10 | positions (持仓) | pos=10, tradeId=163, uTime=1614859755037 | 10 |
11 | positions (持仓) | pos=6, tradeId=163, uTime=1614866547430 | 6 |
从中观察,我们得知:
- 收到 tradeId=163 的单个持仓推送 #7,即代表与持仓对账时,可忽略 tradeId<=163 的订单推送。换言之,我们可忽略订单推送 #8 和 #9
- 持仓推送 #10 与 #7 的 tradeId 和 pos(和 uTime)一样,这表示我们可以认为 #10 为持仓每 10 秒的定时推送
- 持仓推送 #11 具同样的 tradeId=163 但持仓数量有变化(uTime 也较新),我们可推断这推送是由强减或 ADL 触发
总结
在这篇文章中我们学习了如何使用 V5 API 交易,在订阅订单频道后通过 REST 或 WebSocket 进行订单操作。
我们亦从本文理解了如何使用 WebSocket 订阅账户和持仓数据,接收首次订阅全量数据,及事件解发推送和定时推送更新。
在跨币种保证金账户模式启用自动借币的情况下,我们可通过 REST API 获取产品的最大可用数量。
最后,本文亦讲解了如何使用成交 ID(tradeId 字段),进行订单成交推送与持仓的对账。
希望这些技巧和诀窍能够令您更了解 V5 API,让您在 欧易 统一账户交易系统中更得心应手!
由于 欧易 会持续不断地改进统一账户交易系统,上文提到的这些想法均会随之发生变动。请查阅 V5 API 文档以得知最新的规范:做市商申请