Market data types in binapi2 fall into seven categories: order book, trades, klines, tickers, mark price and funding, futures analytics, and exchange metadata. Each is available via one or more of the three API surfaces (REST, WebSocket API, streams). This document covers every market data type and explains when each surface is the right choice.
End-to-end example. For a full, runnable recorder that composes all-market streams, a scoring-based symbol selector, per-symbol Tier-0 feed recording with rotating zstd sinks, and periodic REST sync — all on a single
cobalt::main— seeexamples/binapi2/fapi/async-recorder/and the design docdocs/binapi2/plans/async_recorder.md.
The order book is the central limit order book for a symbol: all resting limit orders, grouped into bids (buy orders) and asks (sell orders). The highest bid and lowest ask form the spread. Orders are aggregated by price level — you see the total quantity at each price, not individual orders.
struct order_book_request_t
{
symbol_t symbol{}; // required
std::optional<int> limit{}; // 5, 10, 20, 50, 100, 500, 1000
};
struct order_book_response_t
{
std::uint64_t lastUpdateId{};
timestamp_ms_t E{}; // message output time
timestamp_ms_t T{}; // transaction time
std::vector<price_level_t> bids{};
std::vector<price_level_t> asks{};
};
struct price_level_t
{
decimal_t price{};
decimal_t quantity{};
};Returns one snapshot of the book. lastUpdateId is the monotonic sequence
number of the last update included — critical for synchronizing with the
diff-depth stream (below). bids are descending by price, asks ascending.
Use for: one-shot depth queries, initial snapshot for local order book synchronization, pre-trade quote lookups.
struct diff_book_depth_subscription
{
symbol_t symbol{};
std::string speed{"100ms"}; // or "250ms" or "500ms"
};
struct depth_stream_event_t
{
timestamp_ms_t event_time{}; // E
timestamp_ms_t transaction_time{}; // T
symbol_t symbol{}; // s
std::uint64_t first_update_id{}; // U
std::uint64_t final_update_id{}; // u
std::uint64_t prev_final_update_id{}; // pu — previous event's u
std::vector<price_level_t> bids{}; // b
std::vector<price_level_t> asks{}; // a
};The stream pushes deltas — levels that changed since the previous event.
A level with quantity == 0 means "remove this price". You maintain the full
book locally by applying each delta.
first_update_id, final_update_id, and prev_final_update_id let you
detect gaps. If event.prev_final_update_id != last_applied_u, you missed
an update — the book is out of sync and you must re-fetch a snapshot.
The speed parameter selects the push frequency: 100 ms (fastest), 250 ms,
or 500 ms.
struct partial_book_depth_subscription
{
symbol_t symbol{};
int levels{5}; // 5, 10, or 20
std::string speed{"100ms"};
};Same event type (depth_stream_event_t) but each frame contains the top N
levels of the full book (not deltas). No reconstruction needed — just
replace your book snapshot on each event. Simpler but less efficient for deep
books.
Combining the REST snapshot and the diff-depth stream correctly requires a careful sync algorithm:
- Subscribe to the diff stream, buffer events.
- Fetch a REST snapshot.
- Discard buffered events where
final_update_id < snapshot.lastUpdateId. - Verify the next buffered event brackets the snapshot (
first_update_id <= snapshot.lastUpdateId + 1 <= final_update_id). If not, resync. - Apply remaining buffered events and continue live.
- On any gap, restart from step 1.
binapi2 implements this as order_book::local_order_book:
auto streams = api.create_market_stream();
auto rest = co_await api.create_rest_client();
order_book::local_order_book book(*streams, (*rest)->market_data);
book.set_snapshot_callback([](const auto& snap) { /* ... */ });
co_await book.async_run(symbol_t{"BTCUSDT"}, 1000);A pipelined variant order_book::pipeline_order_book runs network,
parser, and logic in three dedicated threads connected via SPSC ring buffers
— use this when you need to keep the network thread unblocked by book logic.
If you only need the top of book (best bid and ask), the WS API book-ticker request is simpler than maintaining a full book:
// Single symbol → single ticker
struct websocket_api_book_ticker_request_t { symbol_t symbol{}; };
// No symbol → array of tickers (all symbols)
struct websocket_api_book_tickers_request_t { };
struct book_ticker_t
{
symbol_t symbol{};
decimal_t bidPrice{};
decimal_t bidQty{};
decimal_t askPrice{};
decimal_t askQty{};
timestamp_ms_t time{};
std::optional<std::uint64_t> lastUpdateId{};
};Same book_ticker_t type is also available via REST (book_ticker_request_t)
and as a streaming event (book_ticker_stream_event_t). Three ways to get
the same data — choose based on latency needs.
A trade is a completed match between a buyer and a seller. Each trade has a price, quantity, timestamp, and direction. On Binance futures, individual trades are available both as recent/historical snapshots (REST) and as a live feed (stream).
struct recent_trades_request_t
{
symbol_t symbol{};
std::optional<int> limit{}; // default 500, max 1000
};
struct recent_trade_t
{
std::uint64_t id{};
decimal_t price{};
decimal_t qty{};
decimal_t quoteQty{}; // price * qty
timestamp_ms_t time{};
bool isBuyerMaker{};
};isBuyerMaker is Binance's signed-trade indicator: true means the buyer
was the resting order (market sell). Used to classify trades as "buy" or
"sell" aggression.
Aggregate trades merge consecutive trades at the same price from the same taker side into one record — a cleaner tape for charting and analytics:
struct aggregate_trade_t
{
std::uint64_t a{}; // aggregate trade ID
decimal_t p{}; // price
decimal_t q{}; // quantity
std::uint64_t f{}; // first trade ID
std::uint64_t l{}; // last trade ID
timestamp_ms_t T{}; // trade time
bool m{}; // was buyer the maker
};Historical trades (historical_trades_request_t) is the same as recent
trades but accepts a fromId cursor to paginate backward.
struct aggregate_trade_subscription { symbol_t symbol{}; };
struct aggregate_trade_stream_event_t
{
timestamp_ms_t event_time{}; // E
symbol_t symbol{}; // s
std::uint64_t aggregate_trade_id{}; // a
decimal_t price{}; // p
decimal_t quantity{}; // q
std::uint64_t first_trade_id{}; // f
std::uint64_t last_trade_id{}; // l
timestamp_ms_t trade_time{}; // T
bool is_buyer_maker{}; // m
};One event per aggregate trade — the live trade tape. For charting, trading signals, and any "what's happening right now" logic.
Duplication note: REST returns a historical list, the stream pushes live events. There is no individual-trade stream — aggregation is the only live feed format.
A kline (Japanese: 蝋足, candlestick) summarizes price action over a time interval: open, high, low, close, volume. Intervals range from 1 minute to 1 month.
_1m, _3m, _5m, _15m, _30m, _1h, _2h, _4h, _6h, _8h, _12h, _1d, _3d, _1w, _1M
The underscore prefix avoids conflict with C++ integer literals. Wire format
is the Binance convention ("1m", "1h", etc.).
struct klines_request_t
{
symbol_t symbol{};
kline_interval_t interval{};
std::optional<timestamp_ms_t> startTime{};
std::optional<timestamp_ms_t> endTime{};
std::optional<int> limit{}; // default 500, max 1500
};
struct kline_t
{
timestamp_ms_t open_time{};
decimal_t open{};
decimal_t high{};
decimal_t low{};
decimal_t close{};
decimal_t volume{};
timestamp_ms_t close_time{};
decimal_t quote_volume{}; // volume in quote asset
std::uint64_t trades{};
decimal_t taker_buy_volume{};
decimal_t taker_buy_quote_volume{};
};Returns an array of closed candles (plus the currently-forming one if the time range includes "now"). The glaze deserializer reads klines from Binance's array format (not object format):
[[1566727587000,"0.29","0.29","0.28","0.28","2.54",1566728591999,"0.74",3,"2.54","0.74","0"]]This is a binapi2 design choice — positional parsing avoids named field overhead for this high-volume type.
Variants:
| Request | Data source | Notes |
|---|---|---|
klines_request_t |
The symbol's trade tape | Standard candles |
continuous_kline_request_t |
Pair + contract type (perpetual/current quarter/next quarter) | For delivery contracts — aggregates without the expiry rollover |
index_price_klines_request_t |
Underlying spot index | Tracks the index, not the futures contract |
mark_price_klines_request_t |
Mark price series | For margin and P&L analysis |
premium_index_klines_request_t |
Premium index (mark minus index) | The funding premium signal |
All five variants share the same response shape (std::vector<kline_t>).
struct kline_subscription
{
symbol_t symbol{};
kline_interval_t interval{};
};
struct kline_stream_event_t
{
timestamp_ms_t event_time{}; // E
symbol_t symbol{}; // s
struct kline_data_t {
timestamp_ms_t start_time{};
timestamp_ms_t close_time{};
symbol_t symbol{};
kline_interval_t interval{};
std::uint64_t first_trade_id{};
std::uint64_t last_trade_id{};
decimal_t open{};
decimal_t close{};
decimal_t high{};
decimal_t low{};
decimal_t volume{};
std::uint64_t trades{};
bool is_closed{};
decimal_t quote_volume{};
decimal_t taker_buy_volume{};
decimal_t taker_buy_quote_volume{};
} kline{};
};The stream pushes the currently-forming kline after every trade in that
interval, until the interval closes. When kline.is_closed == true, that
kline is final and a new one starts on the next event.
Typical usage: maintain a rolling deque of closed klines from REST history,
then replace the last element with every stream event (or append when
is_closed flips).
A continuous contract kline stream variant exists for delivery contracts,
keyed on (pair, contract_type, interval).
A ticker is a compact summary of a symbol's recent market state. Binance offers several ticker types with different field sets and update strategies.
book_ticker_t (see order book section) is the top-of-book snapshot. Same
type on all three surfaces. The stream variant pushes on every book change
(no frequency cap):
struct book_ticker_subscription { symbol_t symbol{}; };
struct book_ticker_stream_event_t
{
std::uint64_t update_id{}; // u
symbol_t symbol{}; // s
decimal_t best_bid_price{}; // b
decimal_t best_bid_quantity{}; // B
decimal_t best_ask_price{}; // a
decimal_t best_ask_quantity{}; // A
timestamp_ms_t transaction_time{}; // T
timestamp_ms_t event_time{}; // E
};struct price_ticker_t
{
symbol_t symbol{};
decimal_t price{};
timestamp_ms_t time{};
};Just the last traded price. REST v1 (price_ticker_request_t) and v2
(price_ticker_v2_request_t) differ only in a minor endpoint path — use v2
for new code. Also available via WS API and as an all-symbols array.
struct ticker_24hr_t
{
symbol_t symbol{};
decimal_t priceChange{};
decimal_t priceChangePercent{};
decimal_t weightedAvgPrice{};
decimal_t lastPrice{};
decimal_t lastQty{};
decimal_t openPrice{};
decimal_t highPrice{};
decimal_t lowPrice{};
decimal_t volume{};
decimal_t quoteVolume{};
timestamp_ms_t openTime{};
timestamp_ms_t closeTime{};
std::uint64_t firstId{};
std::uint64_t lastId{};
std::uint64_t count{};
};The typical "market overview" data: open, high, low, close, volume, and percentage change for the last 24 hours. Exchanges usually display this as the ticker strip on a trading UI. Update frequency: ~1s via the stream.
struct mini_ticker_stream_event_t
{
timestamp_ms_t event_time{};
symbol_t symbol{};
decimal_t close{};
decimal_t open{};
decimal_t high{};
decimal_t low{};
decimal_t base_volume{};
decimal_t quote_volume{};
};Same idea as the 24-hour ticker but without the derived fields (percent
change, weighted average). Smaller payload — useful when subscribing to
stream-all-mini-tickers for every symbol.
For any per-symbol stream (book ticker, mini ticker, 24hr ticker), there is an all-market variant that pushes a single event containing an array for every active symbol:
all_market_book_ticker_subscription→/ws/!bookTickerall_market_ticker_subscription→/ws/!ticker@arrall_market_mini_ticker_subscription→/ws/!miniTicker@arr
The event type is a std::vector<per_symbol_event_t> wrapped in a top-level
container. Use this when you need market-wide data and don't want hundreds
of individual subscriptions.
The mark price is the exchange's reference price for margin calculations. Binance computes it as a weighted combination of the spot index price and the moving average of the futures price, damped to prevent manipulative liquidations.
The funding rate is the periodic payment between perpetual longs and shorts. It's calculated from the premium of the futures price over the index price (the "premium index") plus a fixed interest component. Paid every 8 hours by default. Positive rate → longs pay shorts.
struct mark_price_t
{
symbol_t symbol{};
decimal_t markPrice{};
decimal_t indexPrice{};
decimal_t estimatedSettlePrice{};
decimal_t lastFundingRate{}; // most recent funding applied
decimal_t interestRate{};
timestamp_ms_t nextFundingTime{};
timestamp_ms_t time{};
};mark_price_request_t fetches one symbol, mark_prices_request_t fetches
all symbols at once.
funding_rate_request_t returns historical funding rates for one symbol
with optional time range. funding_rate_info_request_t returns the
interest rate and funding rate cap/floor for every symbol — what
you need to estimate future funding.
struct mark_price_subscription
{
symbol_t symbol{};
bool every_1s{false}; // false → every 3s, true → every 1s
};
struct mark_price_stream_event_t
{
timestamp_ms_t event_time{};
symbol_t symbol{};
decimal_t mark_price{};
decimal_t index_price{};
decimal_t estimated_settle_price{};
decimal_t funding_rate{};
timestamp_ms_t next_funding_time{};
};The all-market variant all_market_mark_price_subscription pushes a single
event with an array of mark_price_stream_event_t, one per active symbol.
Same every_1s option.
Design note: mark price is the only stream where the per-symbol and all-market variants have the same event shape — useful for unified handlers.
Binance exposes a set of aggregated statistics useful for market analysis. Only available on REST (no stream variant, no testnet).
| Request | Returns | What it measures |
|---|---|---|
open_interest_request_t |
open_interest_t |
Total open positions (long + short) in one symbol |
open_interest_statistics_request_t |
historical OI array | Open interest time series (30min / 1h / 2h / 4h / 6h / 12h / 1d periods) |
top_long_short_account_ratio_request_t |
ratio time series | Long vs short accounts among top traders |
top_trader_long_short_ratio_request_t |
ratio time series | Long vs short positions among top traders |
long_short_ratio_request_t |
ratio time series | Long/short ratio across all accounts |
taker_buy_sell_volume_request_t |
volume time series | Taker buy vs sell volume (aggression) |
basis_request_t |
basis time series | Futures premium / discount to spot |
These are important sentiment indicators for traders but are pull-only —
typically fetched every minute or every period. None are available on
testnet (the endpoints return plain ok text instead of JSON).
struct exchange_info_request_t { }; // no parameters
struct exchange_info_response_t
{
std::string timezone{};
timestamp_ms_t serverTime{};
std::vector<rate_limit_t> rateLimits{};
std::vector<asset_info_t> assets{};
std::vector<symbol_info_t> symbols{};
};
struct symbol_info_t
{
symbol_t symbol{};
pair_t pair{};
contract_type_t contractType{};
timestamp_ms_t deliveryDate{}; // 0 for perpetuals
timestamp_ms_t onboardDate{};
contract_status_t status{};
decimal_t maintMarginPercent{};
decimal_t requiredMarginPercent{};
std::string baseAsset{};
std::string quoteAsset{};
std::string marginAsset{};
int pricePrecision{};
int quantityPrecision{};
int baseAssetPrecision{};
int quotePrecision{};
std::vector<symbol_filter_t> filters{};
// ... plus order types, time-in-force, trigger protect, liquidation fee
};exchange_info_response_t is the one-stop reference: all tradeable symbols,
their precision, their filters (price tick size, quantity step size, min
notional, max leverage), rate limits, and the server clock.
You should call this at startup and cache the result. It gives you the
rules you must follow when building order requests (min/max price, quantity
step, min notional value). Sending an order that violates a filter is
rejected with a -4xxx Binance error code.
symbol_filter_t is a std::variant over all Binance filter types
(PRICE_FILTER, LOT_SIZE, MARKET_LOT_SIZE, MAX_NUM_ORDERS,
MAX_NUM_ALGO_ORDERS, MIN_NOTIONAL, PERCENT_PRICE) — unwrap with
std::visit or std::get_if.
struct server_time_request_t { };
struct server_time_response_t { timestamp_ms_t serverTime{}; };Use at startup to estimate clock skew for signing (Binance rejects requests
whose timestamp + recvWindow < serverTime).
Auto-deleveraging (ADL) is the mechanism by which winning counterparty
positions are force-closed to cover losses when the insurance fund is
depleted. adl_risk_request_t returns the ADL queue indicator (0–4) for a
symbol — useful for assessing your own ADL exposure.
| Request | Purpose |
|---|---|
composite_index_info_request_t |
Index constituents and weights |
index_constituents_request_t |
Which symbols make up an index |
asset_index_request_t |
Multi-asset margin asset index values |
insurance_fund_request_t / insurance_funds_request_t |
Current insurance fund balance (single symbol or all) |
delivery_price_request_t |
Settlement price history for expired delivery contracts |
trading_schedule_request_t |
Trading sessions / holidays |
rpi_depth_request_t |
Retail Price Improvement order book variant |
This section is a quick catalog of what each data type enables. Pick the type(s) you need for your use case.
- Streams: book ticker, price ticker, or 24hr ticker per symbol.
- Derived: maintain a symbol→last-price map updated from the stream, use for position valuation and risk calculations.
- REST + Stream:
order_book_request_tsnapshot + diff depth stream. - binapi2:
local_order_book::async_run()orpipeline_order_book.
- Streams: aggregate trade stream → detect bursts, compute VWAP, classify
aggressor direction via
is_buyer_maker. - Historical:
recent_trades_request_toraggregate_trades_request_tfor backfill.
- REST:
klines_request_tfor historical backfill (up to 1500 candles per call; paginate viastartTime/endTimefor longer series). - Stream: kline stream to update the current forming candle.
- REST:
mark_price_request_tfor current mark/funding, funding rate history viafunding_rate_request_t. - Stream: mark price stream to track premium in real time.
- REST only: long/short ratios, top trader ratios, taker volume, basis, open interest statistics. Poll on a minute timer.
- REST:
exchange_info_request_tat startup. Validate every order against its symbol's filters before sending.
| Data type | REST request | WS API request | Stream subscription | Response / event type |
|---|---|---|---|---|
| Order book snapshot | order_book_request_t |
— | — | order_book_response_t |
| Order book deltas | — | — | diff_book_depth_subscription |
depth_stream_event_t |
| Partial depth | — | — | partial_book_depth_subscription |
depth_stream_event_t |
| Book ticker | book_ticker_request_t / book_tickers_request_t |
websocket_api_book_ticker_request_t / _tickers_ |
book_ticker_subscription / all_market_book_ticker_subscription |
book_ticker_t / book_ticker_stream_event_t |
| Price ticker | price_ticker_request_t / price_ticker_v2_request_t |
websocket_api_price_ticker_request_t / _tickers_ |
— | price_ticker_t |
| 24hr ticker | ticker_24hr_request_t / ticker_24hrs_request_t |
— | ticker_subscription / all_market_ticker_subscription |
ticker_24hr_t / ticker_stream_event_t |
| Mini ticker | — | — | mini_ticker_subscription / all_market_mini_ticker_subscription |
mini_ticker_stream_event_t |
| Recent trades | recent_trades_request_t |
— | — | std::vector<recent_trade_t> |
| Historical trades | historical_trades_request_t |
— | — | std::vector<recent_trade_t> |
| Aggregate trades | aggregate_trades_request_t |
— | aggregate_trade_subscription |
std::vector<aggregate_trade_t> / aggregate_trade_stream_event_t |
| Klines | klines_request_t + 4 variants |
— | kline_subscription / continuous_contract_kline_subscription |
std::vector<kline_t> / kline_stream_event_t |
| Mark price | mark_price_request_t / mark_prices_request_t |
— | mark_price_subscription / all_market_mark_price_subscription |
mark_price_t / mark_price_stream_event_t |
| Funding rate history | funding_rate_request_t |
— | — | std::vector<funding_rate_t> |
| Funding rate info | funding_rate_info_request_t |
— | — | std::vector<funding_rate_info_t> |
| Open interest | open_interest_request_t |
— | — | open_interest_t |
| OI statistics | open_interest_statistics_request_t |
— | — | std::vector<open_interest_statistics_entry_t> |
| Long/short ratios | long_short_ratio_request_t and siblings |
— | — | arrays of ratio entries |
| Taker buy/sell volume | taker_buy_sell_volume_request_t |
— | — | array |
| Basis | basis_request_t |
— | — | array |
| Exchange info | exchange_info_request_t |
— | — | exchange_info_response_t |
| Server time | server_time_request_t |
— | — | server_time_response_t |
| Liquidation orders | — | — | liquidation_order_subscription / all_market_liquidation_order_subscription |
liquidation_order_stream_event_t |
| Contract info events | — | — | contract_info_subscription |
contract_info_stream_event_t |
| Composite index | — | — | composite_index_subscription |
composite_index_stream_event_t |
| Asset index | asset_index_request_t |
— | asset_index_subscription / all_asset_index_subscription |
asset_index_t / asset_index_stream_event_t |
| Trading session events | — | — | trading_session_subscription |
trading_session_stream_event_t |
| ADL risk | adl_risk_request_t |
— | — | array |
| Insurance fund | insurance_fund_request_t / insurance_funds_request_t |
— | — | insurance_fund_response_t |
| Delivery price | delivery_price_request_t |
— | — | array |
| RPI depth | rpi_depth_request_t |
— | — | order-book-like |
| Trading schedule | trading_schedule_request_t |
— | — | array |