WebSocket: Market Data API
market_data.proto
This schema defines the Protobuf messages used for communication with the Cube Market Data Service (Mendelev, MD). The proto
definition file can be found here.
Order Book Data
The market data service exposes a websocket endpoint for order book data for a given market at wss://api.cube.exchange/md/book/:market_id
. The order book can be consumed by both price level through the Market by Price (MBP) and order-by-order through the Market by Order (MBO). In addition, clients can subscribe to the trade stream and price candlesticks.
Upon connection, clients should submit a Config
and then process a stream of MdMessages
. Note that this message type is distinct from the MdMessage
, where the former is a wrapper containing one or more of the latter.
Aggregate Book Tops Data
The market data service exposes a websocket endpoint for aggregated tops-of-book for all markets at wss://api.cube.exchange/md/tops
. Client should process AggMessage
.
Heartbeats
Application-level heartbeats are expected every 30 seconds. If more than one interval is missed, the market data service will disconnect the websocket.
MdMessage
Every exchange message from /book/:market_id
will be wrapped as an MdMessages
which contains multiple MdMessage
's.
heartbeat
Server heartbeat reply
summary
24h summary
trades
Recent trades
mbo_snapshot
Market by order snapshot
mbo_diff
Market by order diff
mbp_snapshot
Market by price snapshot
mbp_diff
Market by price diff
kline
Candlestick
market_status
market_id
optional
The market ID that this message is for. Null for MdMessage.Heartbeat
.
MarketByPrice
Market by price snapshot message. This is chunked into num_chunks
and starts with chunk = 0
. A snapshot is sent on first connect. Level
's should be concatened until chunk = num_chunks - 1
. Currently, the chunks and levels are streamed from tightest price level outwards with interleaved Bid and Ask levels, but no ordering is guaranteed.
levels
repeated
chunk
num_chunks
MarketByPrice.Level
Each price level is the aggregate total quantity of orders placed at that price.
price
quantity
side
MarketByPriceDiff
Market by price diff message. Book updates for the MBP feed are sent as diffs after the initial snapshot. The number of total side levels are for reconciliation.
diffs
repeated
total_bid_levels
Total number of bid levels after this diff is applied.
total_ask_levels
Total number of ask levels after this diff is applied.
MarketByPriceDiff.Diff
A price level diff overwrites the existing price level.
price
quantity
side
op
MarketByOrder
Market by order snapshot message. This is chunked into num_chunks
and starts with chunk = 0
. A snapshot is sent on first connect. Level
's should be concatened until chunk = num_chunks - 1
. Orders are sent in order of FIFO queue priority so the first order of a level should be the first order to be matched when that level is aggressed.
orders
repeated
chunk
num_chunks
MarketByOrder.Order
A resting order.
price
quantity
exchange_order_id
side
priority
Order priority for execution. Valid within a price level and side. That is, orders must first be sorted by side and price (in descending order for bids and ascending for asks), and then the OrderPriority within the level. A lower value is a higher priority.
MarketByOrderDiff
Market by order diff message. Book updates for the MBO feed are sent as diffs after the initial snapshot. The number of total side levels and orders are for reconciliation.
Note that for orders that are cancel-replace'd (a modify that lost queue priority), the new price and quantity will be reported as a REPLACE
but the exchange order ID will not change.
diffs
repeated
total_bid_levels
Total number of bid levels after this diff is applied.
total_ask_levels
Total number of ask levels after this diff is applied.
total_bid_orders
Total number of bid orders after this diff is applied.
total_ask_orders
Total number of ask orders after this diff is applied.
MarketByOrderDiff.Diff
An order diff creates, updates, or deletes a resting order based on the exchange_order_id
price
quantity
exchange_order_id
side
op
priority
MarketStatus
transact_time
market_state
Trades
Trades since the latest Trades
message. The result of the trades will also appear in the MBP and MBO feeds independently as updates to the resting orders and levels, respectively.
trades
repeated
Trades.Trade
tradeId
The ID assigned to this trade. All trades that occur from the same event will be assigned the same ID, and are considered to be an atomic batch.
price
The price that this trade occurred at.
aggressing_side
The side of the aggressing order.
resting_exchange_order_id
fill_quantity
transact_time
aggressing_exchange_order_id
Summary
Rolling 24h stats.
open
optional
24h open price
close
optional
Latest price
low
optional
24h low price
high
optional
24h high price
base_volume_lo
Low 64-bits of the base quantity traded
base_volume_hi
High 64-bits of the base quantity traded
quote_volume_lo
Low 64-bits of the quote quantity traded
quote_volume_hi
High 64-bits of the quote quantity traded
Kline
Candlestick bar.
interval
start_time
The unix nanosecond timestamp that this kline covers.
open
optional
Kline open price.
close
optional
Kline close price.
high
optional
Kline high price.
low
optional
Kline low price.
volume_lo
Low 64-bits of the base quantity traded.
volume_hi
High 64-bits of the base quantity traded.
Heartbeat
A client and server heartbeat. The heartbeat reply, including the timestamp value, comes from the market data service.
request_id
A request ID that is echoed back on the Heartbeat
timestamp
MdMessages
A wrapper containing one or more Market Data messages, each of which will be an MdMessage
.
messages
repeated
AggMessage
Every exchange message from /tops
will be wrapped as an AggMessage
.
heartbeat
Server heartbeat reply
top_of_books
Top of books
rate_updates
Rates for all assets
TopOfBook
Top of book
market_id
transact_time
bid_price
optional
The best bid price of the direct or implied book, whichever is better.
bid_quantity
optional
The total bid quantity at the best bid price.
ask_price
optional
The best ask price of the direct or implied book, whichever is better.
ask_quantity
optional
The total ask quantity at the best ask price.
last_price
optional
The last trade price.
rolling24h_price
optional
The 24h open price.
market_state
Which trading operations are currently allowed on this market.
TopOfBooks
Top of books for all books that were updates since the last top-of-books message.
tops
repeated
RateUpdate
Rate update. Used in conjuction with another rate update to get the price of that divisor. Rate's should not be used alone. For example, given a RateUpdate for assetId = BTC, updateSide = BASE
of r1
, and assetId = EUR, updateSide = QUOTE
of r2
, the BTC-EUR price estimate is r1 * r2
.
asset_id
timestamp
The nanosecond timestamp of the update.
rate
The asset rate at the given timestamp.
side
RateUpdates
Rates for all assets. Published on connect and updates since the last rate-updates message.
updates
repeated
ClientMessage
Client heartbeats and configs. This wrapper is used for both /book/:market_id
and /tops
, but config
messages are ignored on the latter.
heartbeat
config
Config
Set the message subscriptions for /book/:market_id
. At most one of mbp
and mbo
can be set.
mbp
Enable MBP feeds
mbo
Enable MBO feeds
trades
Enable recent trades
summary
Enable 24h summary
klines
repeated
Enable price klines
market_ids
repeated
Market's to subscribe to. Limit 3.
Enums
Side
Side specifies whether the level, order, or diff, is for buying or selling the base asset.
BID
0
Bids buy the base asset with the quote asset.
ASK
1
Asks (or offers) sell the base asset and get the quote asset.
KlineInterval
The candlestick interval.
S1
0
1 second
M1
1
1 minute
M15
2
15 minutes
H1
3
1 hour
H4
4
4 hours
D1
5
1 day
MarketState
The per-market matching engine state. Affects order-entry.
UNSPECIFIED
0
Sentinel
NORMAL_OPERATION
1
The market is in its normal operating state. All order operations are supported.
CANCEL_ONLY
2
The market is in cancel-only mode. Existing orders are not automatically canceled, and may be filled when the market transitions back to normal-operation.
AggressingSide
The side of the aggressing order. This also indicates if the aggressing order was an implied order (i.e aggressed into a different market and executed into this one through implieds)
AGGRESSING_BID
0
AGGRESSING_ASK
1
AGGRESSING_IMPLIED_BID
2
AGGRESSING_IMPLIED_ASK
3
RateUpdateSide
The side of the rate update. Given a BASE
rate of r
, the QUOTE
rate is 1 / r
, and vice versa.
BASE
0
The asset serves as the base asset for the given rate.
QUOTE
1
The asset serves as the quote asset for the given rate.
MarketByPriceDiff.DiffOp
The operation to apply for this price level. Currently, new price levels are created with REPLACE
.
ADD
0
This operation is NOT used for MBP. The operation of adding a new price level is specified as REPLACE
.
REMOVE
1
This operation is used when a price level is removed from the book.
REPLACE
2
This operation is used when a new price level is added or an existing price level is modified.
MarketByOrderDiff.DiffOp
The operation to apply for this price level. For example, an resting order that gets filled will be REPLACE
'd with the new resting quantity. An order is REMOVE
'd when it is fully filled or canceled.
ADD
0
REMOVE
1
REPLACE
2
Scalar Value Types
double
f64
double
float
float64
float
f32
float
float
float32
int32
Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.
i32
int32
int
int32
int64
Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.
i64
int64
int/long
int64
uint32
Uses variable-length encoding.
u32
uint32
int/long
uint32
uint64
Uses variable-length encoding.
u64
uint64
int/long
uint64
sint32
Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.
i32
int32
int
int32
sint64
Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.
i64
int64
int/long
int64
fixed32
Always four bytes. More efficient than uint32 if values are often greater than 2^28.
u64
uint32
int
uint32
fixed64
Always eight bytes. More efficient than uint64 if values are often greater than 2^56.
u64
uint64
int/long
uint64
sfixed32
Always four bytes.
i32
int32
int
int32
sfixed64
Always eight bytes.
i64
int64
int/long
int64
bool
bool
bool
boolean
bool
string
A string must always contain UTF-8 encoded or 7-bit ASCII text.
String
string
str/unicode
string
bytes
May contain any arbitrary sequence of bytes.
Vec
string
str
[]byte
Last updated