Websocket API

WebSocket: Market Data API

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.

FieldTypeLabelDescription
heartbeatHeartbeatServer heartbeat reply
summarySummary24h summary
tradesTradesRecent trades
mbo_snapshotMarketByOrderMarket by order snapshot
mbo_diffMarketByOrderDiffMarket by order diff
mbp_snapshotMarketByPriceMarket by price snapshot
mbp_diffMarketByPriceDiffMarket by price diff
klineKlineCandlestick
market_statusMarketStatus
funding_calculationFundingCalculationFunding calculation
funding_applicationFundingApplicationFunding application
contract_statisticsContractStatistics
contract_priceContractPrice
market_iduint64optionalThe 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.

FieldTypeLabelDescription
levelsMarketByPrice.Levelrepeated
chunkuint32
num_chunksuint32

MarketByPrice.Level

Each price level is the aggregate total quantity of orders placed at that price.

FieldTypeLabelDescription
priceuint64
quantityuint64
sideSide

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.

FieldTypeLabelDescription
diffsMarketByPriceDiff.Diffrepeated
total_bid_levelsuint32Total number of bid levels after this diff is applied.
total_ask_levelsuint32Total number of ask levels after this diff is applied.

MarketByPriceDiff.Diff

A price level diff overwrites the existing price level.

FieldTypeLabelDescription
priceuint64
quantityuint64
sideSide
opMarketByPriceDiff.DiffOp

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.

FieldTypeLabelDescription
ordersMarketByOrder.Orderrepeated
chunkuint32
num_chunksuint32

MarketByOrder.Order

A resting order.

FieldTypeLabelDescription
priceuint64
quantityuint64
exchange_order_iduint64Exchange order ID
sideSide
priorityuint64Order 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.

FieldTypeLabelDescription
diffsMarketByOrderDiff.Diffrepeated
total_bid_levelsuint32Total number of bid levels after this diff is applied.
total_ask_levelsuint32Total number of ask levels after this diff is applied.
total_bid_ordersuint32Total number of bid orders after this diff is applied.
total_ask_ordersuint32Total 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

FieldTypeLabelDescription
priceuint64
quantityuint64
exchange_order_iduint64Exchange order ID
sideSide
opMarketByOrderDiff.DiffOp
priorityuint64See MarketByOrder.Order

MarketStatus

FieldTypeLabelDescription
transact_timeuint64
market_stateMarketState

FundingCalculation

FieldTypeLabelDescription
transact_timeuint64Server time that this funding calculation was made.
predicted_funding_rateint64Predicted funding rate percentage for the next funding interval. See FundingApplication.funding_rate for details on calculation.
next_funding_application_timeuint64The server target time for the next funding application. Expressed in nanoseconds.
countdown = next_funding_application_time - transact_time
premium_indexint64Premium (or discount) percentage relative to the index price.
premium_index = (MAX(impact_bid_price - index_price, 0) - MAX(index_price - impact_ask_price, 0)) / index_price
Expressed with 9 decimals.
index_priceuint64The index price used for the premium index calculation. Expressed with 9 decimals.
latest_funding_rateint64The latest funding application's funding_rate.

FundingApplication

FieldTypeLabelDescription
transact_timeuint64
funding_rateint64Funding rate percentage for this interval, calculated based on the average premium index over the funding interval.
funding_rate = premium_index + clamp(interest_rate - premium_index, -clamp, +clamp) </br>
funding_deltaFundingDeltaThe quote amount to be paid (or received) based on the given funding rate, funding interval duration, and current index price.
next_funding_application_timeuint64The server target time for the next funding application.

ContractStatistics

Statistics for the contract.

FieldTypeLabelDescription
transact_timeuint64
open_interestint64The total number of open contracts for this product. Counts both longs and shorts

ContractPrice

Latest contract price information.

FieldTypeLabelDescription
transact_timeuint64
index_priceuint64The spot index price of the contract. Expressed with 9 decimals.
mark_priceuint64The mark price at transact_time.
funding_basis = funding_rate * (time until funding / funding interval) mark_price = (1 + funding_basis) * index_price </br>

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.

FieldTypeLabelDescription
tradesTrades.Traderepeated

Trades.Trade

FieldTypeLabelDescription
tradeIduint64The 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.
priceuint64The price that this trade occurred at.
aggressing_sideAggressingSideThe side of the aggressing order.
resting_exchange_order_iduint64The Exchange order ID of the resting order.
fill_quantityuint64
transact_timeuint64The transact time assigned by the matching engine for this trade. All trades that occur from the same event will be assigned the same transact time.
aggressing_exchange_order_iduint64The Exchange order ID of the aggressing order.

Summary

Rolling 24h stats.

FieldTypeLabelDescription
openuint64optional24h open price
closeuint64optionalLatest price
lowuint64optional24h low price
highuint64optional24h high price
base_volume_louint64Low 64-bits of the base quantity traded
base_volume_hiuint64High 64-bits of the base quantity traded
quote_volume_louint64Low 64-bits of the quote quantity traded
quote_volume_hiuint64High 64-bits of the quote quantity traded

Kline

Candlestick bar.

FieldTypeLabelDescription
intervalKlineInterval
start_timeuint64The unix nanosecond timestamp that this kline covers.
openuint64optionalKline open price.
closeuint64optionalKline close price.
highuint64optionalKline high price.
lowuint64optionalKline low price.
volume_louint64Low 64-bits of the base quantity traded.
volume_hiuint64High 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.

FieldTypeLabelDescription
request_iduint64A request ID that is echoed back on the Heartbeat
timestampuint64

MdMessages

A wrapper containing one or more Market Data messages, each of which will be an MdMessage.

FieldTypeLabelDescription
messagesMdMessagerepeated

AggMessage

Every exchange message from /tops will be wrapped as an AggMessage.

FieldTypeLabelDescription
heartbeatHeartbeatServer heartbeat reply
top_of_booksTopOfBooksTop of books
rate_updatesRateUpdatesRates for all assets

TopOfBook

Top of book

FieldTypeLabelDescription
market_iduint64
transact_timeuint64The transact time of the latest book update on this market.
bid_priceuint64optionalThe best bid price of the direct or implied book, whichever is better.
bid_quantityuint64optionalThe total bid quantity at the best bid price.
ask_priceuint64optionalThe best ask price of the direct or implied book, whichever is better.
ask_quantityuint64optionalThe total ask quantity at the best ask price.
last_priceuint64optionalThe last trade price.
rolling24h_priceuint64optionalThe 24h open price.
market_stateMarketStateWhich 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.

FieldTypeLabelDescription
topsTopOfBookrepeated

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.

FieldTypeLabelDescription
asset_iduint64
timestampuint64The nanosecond timestamp of the update.
rateuint64The asset rate at the given timestamp.
sideRateUpdateSide

RateUpdates

Rates for all assets. Published on connect and updates since the last rate-updates message.

FieldTypeLabelDescription
updatesRateUpdaterepeated

ClientMessage

Client heartbeats and configs. This wrapper is used for both /book/:market_id and /tops, but config messages are ignored on the latter.

FieldTypeLabelDescription
heartbeatHeartbeat
configConfig

Config

Set the message subscriptions for /book/:market_id. At most one of mbp and mbo can be set.

FieldTypeLabelDescription
mbpboolEnable MBP feeds
mboboolEnable MBO feeds
tradesboolEnable recent trades
summaryboolEnable 24h summary
klinesKlineIntervalrepeatedEnable price klines
market_idsuint64repeatedMarket's to subscribe to. Limit 3.

Numeric Types

FundingDelta

Funding delta to be applied per open contract unit, for a particular funding interval. The delta is expressed as a signed (twos-complement) fixed point number with 18 decimal places.

FieldTypeLabelDescription
word0uint64
word1uint64

Enums

Side

Side specifies whether the level, order, or diff, is for buying or selling the base asset.

NameNumberDescription
BID0Bids buy the base asset with the quote asset.
ASK1Asks (or offers) sell the base asset and get the quote asset.

KlineInterval

The candlestick interval.

NameNumberDescription
S101 second
M111 minute
M15215 minutes
H131 hour
H444 hours
D151 day

MarketState

The per-market matching engine state. Affects order-entry.

NameNumberDescription
UNSPECIFIED0Sentinel
NORMAL_OPERATION1The market is in its normal operating state. All order operations are supported.
CANCEL_ONLY2The 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)

NameNumberDescription
AGGRESSING_BID0
AGGRESSING_ASK1
AGGRESSING_IMPLIED_BID2
AGGRESSING_IMPLIED_ASK3

RateUpdateSide

The side of the rate update. Given a BASE rate of r, the QUOTE rate is 1 / r, and vice versa.

NameNumberDescription
BASE0The asset serves as the base asset for the given rate.
QUOTE1The 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.

NameNumberDescription
ADD0This operation is NOT used for MBP. The operation of adding a new price level is specified as REPLACE.
REMOVE1This operation is used when a price level is removed from the book.
REPLACE2This 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.

NameNumberDescription
ADD0
REMOVE1
REPLACE2

Scalar Value Types

.proto TypeNotesRustC++PythonGo
doublef64doublefloatfloat64
floatf32floatfloatfloat32
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.i32int32intint32
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.i64int64int/longint64
uint32Uses variable-length encoding.u32uint32int/longuint32
uint64Uses variable-length encoding.u64uint64int/longuint64
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.i32int32intint32
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.i64int64int/longint64
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.u64uint32intuint32
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.u64uint64int/longuint64
sfixed32Always four bytes.i32int32intint32
sfixed64Always eight bytes.i64int64int/longint64
boolboolboolbooleanbool
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.Stringstringstr/unicodestring
bytesMay contain any arbitrary sequence of bytes.Vec<u8>stringstr[]byte