Websocket 行情推送
- 本篇所列出的所有wss接口的baseurl为: wss://wbs-api.mexc.com/ws
- 每个到 wss://wbs-api.mexc.com/ws 的链接有效期不超过24小时,请妥善处理断线重连
- symbol名称中所有交易对均为大写,如:
spot@public.aggre.deals.v3.api.pb@<symbol>
实例:spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT
- websocket没有有效订阅的话,服务器会在30秒时主动断开连接,如果订阅成功但是没有流量,服务器会在一分钟时主动断开,客户端可以发送ping来保持链接
- 1个 ws 连接最多30个订阅
- 请按照文档返回的参数进行处理数据,文档没有返回的参数近期将进行优化处理,请勿使用
实时订阅/取消数据流
- 以下数据可以通过websocket发送以实现订阅或取消订阅数据流。示例如下。
- 响应内容中的
id
是无符号整数,作为往来信息的唯一标识。 - 如果相应内容中的
msg
为相应的请求字段,表示请求发送成功。
protocolbuffers接入方案
当前ws推送采用protobuf的形式,具体接入流程如下:
1.PB文件定义 PB定义文件可以在此连接处获取:https://github.com/mexcdevelop/websocket-proto
2.生成反序列化代码 使用https://github.com/protocolbuffers/protobuf工具编译.proto文件,生成反序列化代码
Java
//在proto文件夹下执行
protoc *.proto --java_out=java文件输出路径
python
//在proto文件夹下执行
protoc *.proto --python_out=python文件输出路径
其他
支持多种语言,包括 C++,C#, Go, Ruby, PHP, JS等。详见[https://github.com/protocolbuffers/protobuf](https://github.com/protocolbuffers/protobuf)。
3.数据反序列化 使用上一步生成的代码,反序列化数据
Java 引入protobuf-java:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>S{protobuf.version}/version><!-- 根据项目实际情况指定版本 -->
</dependency>
解析示例:
// 组装对象
PushDataV3ApiWrapper pushDataV3ApiWrapper = PushDataV3ApiWrapper.newBuilder()
.setChannel("spot@public.aggre.depth.v3.api.pb@10ms")
.setSymbol("BTCUSDTI)
.setSendTime(System.currentTimeMillis())
.build();
// 序列化为byte数组
byte[] serializedData = pushDataV3ApiWrapper.toByteArray();
// 反序列化为 PushDataV3ApiWrapper 对象
PushDataV3ApiWrapper resultV3 = PushDataV3ApiWrapper.parseFrom(serializedData);
python
解析示例:
import PushDataV3ApiWrapper_pb2
#组装对象
PushDataV3ApiWrapper = PushDataV3ApiWrapper_pb2.PushDataV3ApiWrapper()
PushDataV3ApiWrapper.channel = 'spot@public.aggre.depth.v3.api.pb@10ms'
PushDataV3ApiWrapper.symbol ='BTCUSDT'
#序列化为字符串
serializedData = PushDataV3ApiWrapper.SerializeToString()
# 反序列化为 PushDataV3ApiWrapper 对象
result = PushDataV3ApiWrapper_pb2.PushDataV3ApiWrapper()
result.ParseFromString(serializedData)
print(result)
订阅一个信息流
订阅频道响应
{
"id":0,
"code":0,
"msg":"spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT"
}
- 请求
{"method":"SUBSCRIPTION","params":["spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT"]}
取消订阅一个信息流
取消订阅响应
{
"id":0,
"code":0,
"msg":"spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT"
}
- 请求
{"method":"UNSUBSCRIPTION","params":["spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT"]}
PING/PONG机制
PING/PONG响应
{
"id":0,
"code":0,
"msg":"PONG"
}
- 请求
{"method":"PING"}
成交信息
request:
{
"method": "SUBSCRIPTION",
"params": [
"spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT"
]
}
response:
{
"channel": "spot@public.aggre.deals.v3.api.pb@100ms@BTCUSDT",
"publicdeals": {
"dealsList": [
{
"price": "93220.00", //成交价格price
"quantity": "0.04438243", //成交数量quantity
"tradetype": 2,//交易类型tradeType
"time": 1736409765051 //成交时间dealTime
}
],
"eventtype": "spot@public.aggre.deals.v3.api.pb@100ms" //事件类型
},
"symbol": "BTCUSDT", //交易对symbol
"sendtime": 1736409765052 //事件时间eventTime
}
请求参数: spot@public.aggre.deals.v3.api.pb@(100ms|10ms)@<symbol>
成交信息推送每一笔成交的信息。成交,或者说交易的定义是仅有一个吃单者与一个挂单者相互交易
返回参数:
参数名 | 数据类型 | 说明 |
---|---|---|
dealsList | array | 成交信息 |
price | string | 成交价格 |
quantity | string | 成交数量 |
tradetype | int | 交易类型 1:买 2:卖 |
time | long | 成交时间 |
eventtype | string | 事件类型 |
symbol | string | 交易对 |
sendtime | long | 事件时间 |
K线 Streams
request:
{
"method": "SUBSCRIPTION",
"params": [
"spot@public.kline.v3.api.pb@BTCUSDT@Min15"
]
}
response:
{
"channel": "spot@public.kline.v3.api.pb@BTCUSDT@Min15",
"publicspotkline": {
"interval": "Min15", //K线间隔
"windowstart": 1736410500, //这根K线的起始时间
"openingprice": "92925", //这根K线期间第一笔成交价
"closingprice": "93158.47", //这根K线期间末一笔成交价
"highestprice": "93158.47", //这根K线期间最高成交价
"lowestprice": "92800", //这根K线期间最低成交价
"volume": "36.83803224", //这根K线期间成交量
"amount": "3424811.05", //这根K线期间成交额
"windowend": 1736411400 //这根K线的结束时间
},
"symbol": "BTCUSDT",
"symbolid": "2fb942154ef44a4ab2ef98c8afb6a4a7",
"createtime": 1736410707571
}
K线逐秒推送所请求的K线种类(最新一根K线)的更新。
请求参数: spot@public.kline.v3.api.pb@<symbol>@<interval>
返回参数:
参数名 | 数据类型 | 说明 |
---|---|---|
publicspotkline | object | k线信息 |
interval | interval | K线间隔 |
windowstart | long | 这根K线的起始时间 |
openingprice | bigDecimal | 这根K线期间第一笔成交价 |
closingprice | bigDecimal | 这根K线期间末一笔成交价 |
highestprice | bigDecimal | 这根K线期间最高成交价 |
lowestprice | bigDecimal | 这根K线期间最低成交价 |
volume | bigDecimal | 这根K线期间成交量 |
amount | bigDecimal | 这根K线期间成交额 |
windowend | long | 这根K线的结束时间 |
symbol | string | 交易对 |
symbolid | string | 交易对id |
createtime | long | 事件时间 |
K线图间隔参数:
Min -> 分钟; Hour -> 小时; Day -> 天; Week -> 周, M -> 月
- Min1
- Min5
- Min15
- Min30
- Min60
- Hour4
- Hour8
- Day1
- Week1
- Month1
增量深度信息
request:
{
"method": "SUBSCRIPTION",
"params": [
"spot@public.aggre.depth.v3.api.pb@100ms@BTCUSDT"
]
}
response:
{
"channel": "spot@public.aggre.depth.v3.api.pb@100ms@BTCUSDT",
"publicincreasedepths": {
"asksList": [], //asks:卖单
"bidsList": [ //bids:买单
{
"price": "92877.58", //变动的价格档位
"quantity": "0.00000000" //数量
}
],
"eventtype": "spot@public.aggre.depth.v3.api.pb@100ms", //事件类型
"fromVersion" : "10589632359", // 开始version
"toVersion" : "10589632359" // 截止version
},
"symbol": "BTCUSDT", //交易对
"sendtime": 1736411507002 //事件时间
}
如果某个价格对应的挂单量(quantity)为0,表示该价位的挂单已经撤单或者被吃,应该移除这个价位。
请求参数: spot@public.aggre.depth.v3.api.pb@(100ms|10ms)@<symbol>
返回参数:
参数名 | 数据类型 | 说明 |
---|---|---|
price | string | 变动的价格档位 |
quantity | string | 数量 |
eventtype | string | 事件类型 |
fromversion | string | 开始版本号 |
toversion | string | 截止版本号 |
symbol | string | 交易对 |
sendtime | long | 事件时间 |
有限档位深度信息
推送有限档深度信息,levels表示几档买卖单信息, 可选 5/10/20档。
request:
{
"method": "SUBSCRIPTION",
"params": [
"spot@public.limit.depth.v3.api.pb@BTCUSDT@5"
]
}
response:
{
"channel": "spot@public.limit.depth.v3.api.pb@BTCUSDT@5",
"publiclimitdepths": {
"asksList": [ //asks:卖单
{
"price": "93180.18", //变动的价格档位
"quantity": "0.21976424" //数量
}
],
"bidsList": [ //bids:买单
{
"price": "93179.98",
"quantity": "2.82651000"
}
],
"eventtype": "spot@public.limit.depth.v3.api.pb", //事件类型
"version": "36913565463" //版本号
},
"symbol": "BTCUSDT", //交易对
"sendtime": 1736411838730 //事件时间
}
请求参数: spot@public.limit.depth.v3.api.pb@<symbol>@<level>
返回参数:
参数名 | 数据类型 | 说明 |
---|---|---|
price | string | 变动的价格档位 |
quantity | string | 数量 |
eventtype | string | 事件类型 |
version | string | 版本号 |
symbol | string | 交易对 |
sendtime | long | 事件时间 |
按Symbol的最优挂单信息
推送指定交易对最优挂单信息。
request:
{
"method": "SUBSCRIPTION",
"params": [
"spot@public.aggre.bookTicker.v3.api.pb@100ms@BTCUSDT"
]
}
response:
{
"channel": "spot@public.aggre.bookTicker.v3.api.pb@100ms@BTCUSDT",
"publicbookticker": {
"bidprice": "93387.28", // 买单最优挂单价格
"bidquantity": "3.73485", //买单最优挂单数量
"askprice": "93387.29", //卖单最优挂单价格
"askquantity": "7.669875" //卖单最优挂单数量
},
"symbol": "BTCUSDT", //交易对
"sendtime": 1736412092433 //事件时间
}
请求参数: spot@public.aggre.bookTicker.v3.api.pb@(100ms|10ms)@<symbol>
返回参数:
参数名 | 数据类型 | 说明 |
---|---|---|
bidprice | string | 买单最优挂单价格 |
bidquantity | string | 买单最优挂单数量 |
askprice | string | 卖单最优挂单价格 |
askquantity | string | 卖单最优挂单数量 |
symbol | string | 交易对 |
sendtime | long | 事件时间 |
按Symbol的最优挂单信息(批量聚合)
批量聚合版本,推送指定交易对最优挂单信息。
request:
{
"method": "SUBSCRIPTION",
"params": [
"spot@public.bookTicker.batch.v3.api.pb@BTCUSDT"
]
}
response:
{
"channel" : "spot@public.bookTicker.batch.v3.api.pb@BTCUSDT",
"symbol" : "BTCUSDT",
"sendTime" : "1739503249114",
"publicBookTickerBatch" : {
"items" : [ {
"bidPrice" : "96567.37",
"bidQuantity" : "3.362925",
"askPrice" : "96567.38",
"askQuantity" : "1.545255"
} ]
}
}
请求参数: spot@public.bookTicker.batch.v3.api.pb@<symbol>
返回参数:
参数名 | 数据类型 | 说明 |
---|---|---|
bidprice | string | 买单最优挂单价格 |
bidquantity | string | 买单最优挂单数量 |
askprice | string | 卖单最优挂单价格 |
askquantity | string | 卖单最优挂单数量 |
symbol | string | 交易对 |
sendtime | long | 事件时间 |
全交易对行情信息
指定时区的全交易对行情信息,3秒推送一次,包括所有有价格变动的交易对,UTC取值范围:24H,UTC-10,UTC-8,UTC-7,UTC-6,UTC-5,UTC-4,UTC-3,UTC+0,UTC+1,UTC+2,UTC+3,UTC+4,UTC+4:30,UTC+5,UTC+5:30,UTC+6,UTC+7,UTC+8,UTC+9,UTC+10,UTC+11,UTC+12,UTC+12:45,UTC+13
request:
{
"method": "SUBSCRIPTION",
"params": [
"spot@public.miniTickers.pb@UTC+8"
]
}
response:
{
"channel": "spot@public.miniTickers.v3.api.pb@UTC+8",
"sendTime": "1755076614201",
"publicMiniTickers":
{
"items":
[
{
"symbol": "METAUSDT",
"price": "0.055",
"rate": "-0.2361",
"zonedRate": "-0.2361",
"high": "0.119",
"low": "0.053",
"volume": "814864.474",
"quantity": "10764997.16",
"lastCloseRate": "-0.2567",
"lastCloseZonedRate": "-0.2567",
"lastCloseHigh": "0.119",
"lastCloseLow": "0.053"
},
{
"symbol": "FCATUSDT",
"price": "0.0000031",
"rate": "-0.4464",
"zonedRate": "-0.4464",
"high": "0.0000066",
"low": "0.0000025",
"volume": "2825.4350195",
"quantity": "654649950.75",
"lastCloseRate": "-0.4464",
"lastCloseZonedRate": "-0.4464",
"lastCloseHigh": "0.0000066",
"lastCloseLow": "0.0000025"
},
{
"symbol": "CRVETH",
"price": "0.00022592",
"rate": "0.028",
"zonedRate": "0.028",
"high": "0.00022856",
"low": "0.00021024",
"volume": "1062.48406269",
"quantity": "4884456.998",
"lastCloseRate": "0.0276",
"lastCloseZonedRate": "0.0276",
"lastCloseHigh": "0.00022856",
"lastCloseLow": "0.00021024"
}
]
}
}
请求参数: channel": "spot@public.miniTickers.v3.api.pb@<UTC-TIMEZONE>
返回参数:
参数名 | 数据类型 | 说明 |
---|---|---|
symbol | string | 交易对名 |
price | string | 最新价格 |
rate | string | UTC+8时区涨跌幅 |
zonedRate | string | 时区涨跌幅 |
high | string | 滚动最高价 |
low | string | 滚动最低价 |
volume | string | 滚动成交额 |
quantity | string | 滚动成交量 |
lastCloseRate | string | UTC+8时区上期收盘价模式涨跌幅 |
lastCloseZonedRate | string | 上期收盘价模式时区涨跌幅 |
lastCloseHigh | string | 上期收盘价模式滚动最高价 |
lastCloseLow | string | 上期收盘价模式滚动最低价 |
交易对行情信息
指定时区指定交易对的行情信息,3秒推送一次,UTC取值范围:24H,UTC-10,UTC-8,UTC-7,UTC-6,UTC-5,UTC-4,UTC-3,UTC+0,UTC+1,UTC+2,UTC+3,UTC+4,UTC+4:30,UTC+5,UTC+5:30,UTC+6,UTC+7,UTC+8,UTC+9,UTC+10,UTC+11,UTC+12,UTC+12:45,UTC+13
request:
{
"method": "SUBSCRIPTION",
"params": [
"spot@public.miniTicker.v3.api.pb@MXUSDT@UTC+8"
]
}
response:
{
"channel" : "spot@public.miniTicker.v3.api.pb@MXUSDT@UTC+8",
"symbol" : "MXUSDT",
"sendTime" : "1755076752201",
"publicMiniTicker" : {
"symbol" : "MXUSDT",
"price" : "2.5174",
"rate" : "0.0766",
"zonedRate" : "0.0766",
"high" : "2.6299",
"low" : "2.302",
"volume" : "11336518.0264",
"quantity" : "4638390.17",
"lastCloseRate" : "0.0767",
"lastCloseZonedRate" : "0.0767",
"lastCloseHigh" : "2.6299",
"lastCloseLow" : "2.302"
}
}
请求参数: channel": "spot@public.miniTicker.v3.api.pb@<symbol>@<UTC-TIMEZONE>
返回参数:
参数名 | 数据类型 | 说明 |
---|---|---|
symbol | string | 交易对名 |
price | string | 最新价格 |
rate | string | UTC+8时区涨跌幅 |
zonedRate | string | 时区涨跌幅 |
high | string | 滚动最高价 |
low | string | 滚动最低价 |
volume | string | 滚动成交额 |
quantity | string | 滚动成交量 |
lastCloseRate | string | UTC+8时区上期收盘价模式涨跌幅 |
lastCloseZonedRate | string | 上期收盘价模式时区涨跌幅 |
lastCloseHigh | string | 上期收盘价模式滚动最高价 |
lastCloseLow | string | 上期收盘价模式滚动最低价 |
如何正确在本地维护一个orderbook副本
- 连接 Websocket,并订阅 spot@public.aggre.depth.v3.api.pb@(100ms|10ms)@MXBTC 获取增量聚合深度信息
- 访问Rest接口 https://api.mexc.com/api/v3/depth?symbol=MXBTC&limit=1000 获得一个1000档的深度快照
- 每一个新推送消息的fromVersion应该恰好等于上一个推送消息的toVersion+1,否则表示出现了丢包,需要从步骤2重新进行初始化
- 每一个推送消息中的挂单量代表这个价位目前挂单量的绝对值,而不是相对变化。
- 如果推送消息中的toVersion值小于快照中的version,说明推送的消息为过期消息,忽略
- 如果推送消息中的fromVersion值大于快照中的version,说明推送的消息和快照数据之间有缺失,需要从步骤2重新进行初始化
- 现在快照中的version在推送消息的[fromVersion, toVersion]范围之内,可以将推送消息与快照数据进行整合,过程如下:
- 推送消息中的价位在快照中已存在,按照推送消息中的数量,进行重新设置
- 推送消息中的价位在快照中不存在,按照推送消息中的数量,插入新的值
- 推送消息中存在数量为0的价位,在快照中删除此价位
注意: 因为深度快照对价格档位数量有限制,初始快照之外的价格档位如果没有发生数量变化,是不会出现在增量推送消息中的。所以本地的 order book 与真实的 order book 可能会有一些差异。 不过对于大多数用例,5000 的深度限制足以有效地了解市场和交易。