Subscription.book
Reads the order book maintained by this depth subscription itself. Only applies to subscriptions whose channel is depth.
book()
book(n)Examples
Subscribe to a 20-level order book, and on each update read the best bid price, the best ask price, and the total order quantity of the top 5 levels.
javascript
function main() {
var sub = ctx.subscribe(exchange, {channel: "depth", depth: 20})
while (true) {
var ev = ctx.poll(sub, 1000)
if (!ev || ev.kind !== 3) {
continue
}
var book = sub.book(5) // ev.book(5) also works
if (book.bids.length === 0 || book.asks.length === 0) {
continue // complete order book not received yet
}
var bidQty = 0
var askQty = 0
book.bids.forEach(function(level) { bidQty += level[1] })
book.asks.forEach(function(level) { askQty += level[1] })
Log("bid1:", book.bids[0][0], "ask1:", book.asks[0][0])
Log("top 5 bidQty:", bidQty, "askQty:", askQty)
}
}
python
def main():
sub = ctx.subscribe(exchange, {"channel": "depth", "depth": 20})
while True:
ev = ctx.poll(sub, 1000)
if ev is None or ev.kind != 3:
continue
book = sub.book(5) # ev.book(5) also works
if not book["bids"] or not book["asks"]:
continue # complete order book not received yet
bid_qty = sum(level[1] for level in book["bids"])
ask_qty = sum(level[1] for level in book["asks"])
Log("bid1:", book["bids"][0][0], "ask1:", book["asks"][0][0])
Log("top 5 bidQty:", bid_qty, "askQty:", ask_qty)
rust
fn main() {
let sub = ctx::subscribe(exchange, ctx::SubOpts::depth(20)).unwrap();
loop {
match ctx::poll(&[sub.id()], Some(1000)) {
ctx::Polled::Event(_) => {
let book = match sub.book(5) {
Ok(b) => b,
Err(e) => panic!("book failed: {e}"),
};
if book.bids.is_empty() || book.asks.is_empty() {
continue;
}
let bid_qty: f64 = book.bids.iter().map(|l| l.1).sum();
let ask_qty: f64 = book.asks.iter().map(|l| l.1).sum();
Log!("bid1:", book.bids[0].0, "ask1:", book.asks[0].0);
Log!("top 5 bidQty:", bid_qty, "askQty:", ask_qty);
}
ctx::Polled::Stopped => break,
_ => {}
}
}
}Returns
| Type | Description |
object |
|
Arguments
| Name | Type | Required | Description |
n | number | No | Number of price levels returned per side. If omitted, the number of levels specified when subscribing is used ( |
See Also
Remarks
A depth event (kind is 3) only indicates that the order book has been updated; it does not carry any price level data. The order book is continuously updated inside the docker as the exchange pushes data, independent of how fast the strategy reads events, so whatever is read at any moment is always the latest complete order book. ev.book(n) on a depth event reads the same order book.
Each depth subscription maintains its own order book: two subscriptions on the same symbol with depth set to 5 and 20 respectively do not affect each other, and each reads an order book with its corresponding number of levels.
Calling it on a non-depth subscription or on a subscription object that has already been unsubscribed throws an exception.
In Python it is sub.book(n=None), returning a dict {"bids": [[price, amount], ...], "asks": [...]} (can also be written as b.bids); depth events likewise provide ev.book(n). In Rust it is sub.book(n: usize) -> Result<ctx::Book, String>, where bids and asks of ctx::Book are Vec<(f64, f64)> (price, amount); after importing sdk::ctx::EventExt, depth events can also use ev.book(n). ctx::Sub can be copied, and after being passed to another thread it can still read this order book (but unsubscribing can only be done in the thread that created the subscription).