Introduction
The Live Orderbook will lie at the heart of almost any real-world trading bot or algorithm.
In this tutorial, we illustrate the steps to hook a LiveOrderbook instance up to a message feed and to start extracting information from it.
Configuration
The LiveOrderbook class
configuration object has only one required field: product
. Since an
orderbook represents a single trading pair, any message with a product ID
other than product
will be filtered out.
The other config options are logger
, to pass a global Logger object
to the orderbook; and strictMode
, a boolean, that determines the behavior when a skipped message is detected.
LiveOrderbook
is a writable stream, so once you have a feed message stream, and applied whatever
filters and transformers to it that you like, you can pipe it straight in and the orderbook will
update itself automatically.
A standard template for creating and configuring a LiveOrderbook looks like this:
import * as CBPTT from 'coinbase-pro-trading-toolkit';
const products = ['LTC-USD'];
const logger = CBPTT.utils.ConsoleLoggerFactory({ level: 'debug' });
CBPTT.Factories.CoinbasePro.FeedFactory(logger, products).then((feed: CoinbaseProFeed) => {
// Configure the live book object
const config: LiveBookConfig = {
product: product,
logger: logger
};
const book = new LiveOrderbook(config);
feed.pipe(book);
...
});
Orderbook messages
LiveOrderbook
emits an array of messages in response to certain events.
Event tag | Emitted when | Data provided |
---|---|---|
LiveOrderbook.update | The orderbook changes due to a new order, a cancelled order, or a trade | A descendant of OrderbookMessage causing the change |
LiveOrderbook.trade | a trade occurs | A TradeMessage describing the trade |
LiveOrderbook.ticker | Whenever the ticker is updated | A TickerMessage instance |
LiveOrderbook.snapshot | When an orderbook snapshot is received, usually immediately after subscribing to the message feed. | The SnapshotMessage |
LiveOrderbook.skippedMessage | if a sequencing error in the message feed is detected. | A SkippedMessageEvent |
error | An unrecoverable error occurs | The Error object |
Orderbook methods and properties
All the orderbook methods and properties are near-realtime. You can query the last update time
with book.timeSinceTickerUpdate
or book.timeSinceOrderbookUpdate
which returns the time (is seconds)
since the last update to the orderbook.
Some of the handy properties available on LiveOrderbook
are:
Property | Type | Description |
---|---|---|
sourceSequence | number | The last known sequence number from the underlying feed, if it exists. Some websocket feeds don’t supply sequences, for example. |
sequence | number | The sequence number as generated by the connected feed source. It may or may not correspond to sourceSequence |
numAsks | number | The number of orders on the sell side of the book |
numBids | number | The number of orders on the buy side of the book |
asksTotal | BigJS | The total value of the sell side of the book (in base currency) |
bidsTotal | BigJS | The total value of the buy side of the book (in base currency) |
book | BookBuilder | Provides access to the underlying book builder. Note: Modifying the book will cause the LiveOrderbook to go out of sync. |
ticker | Ticker | Returns the latest ticker information about the book |
baseCurrency | string | The base currency for the trading pair (e.g. BTC in BTC-USD) |
quoteCurrency | string | The quote currency for the trading pair (e.g. USD in BTC-USD) |
ordersForValue
ordersForValue
is probably the most useful method in liveOrderbook
. It allows you to query
the orderbook to determine which orders would be filled for a given trade.
This comes in useful for calculating things like average price, slippage and various other metrics for liquidity that are important for algorithmic trading.
The function takes a side (‘buy’ or ‘sell’) and a value and returns the orders that would be filled by that trade. However, it also returns the cumulative size and cost/value of the trade at each level, from which all the liquidity metrics can be derived.
The 3rd and 4th arguments to ordersForValue
modify the interpretation of the trade. useQuote
instructs
the method to interpret value
in quote currency rather than base currency.
And startingPoint
allows you to specify an offset value (by default it is zero). This allows you to
calculate order tranches (the first 100 BTC, the second 100 BTC etc).
Try it out
Given a running LiveOrderbook instance, the following snippet
console.log(`Number of bids: ${book.numBids} asks: ${book.numAsks}`);
console.log(`Total ${book.baseCurrency} liquidity: ${book.bidsTotal.toFixed(3)} asks: ${book.asksTotal.toFixed(3)}`);
let orders: CumulativePriceLevel[] = book.ordersForValue('buy', 100, false);
console.log(`Cost of buying 100 ${book.baseCurrency}: ${orders[orders.length - 1].cumValue.toFixed(2)} ${book.quoteCurrency}`);
orders = book.ordersForValue('sell', 1000, true);
console.log(`Need to sell ${orders[orders.length - 1].cumSize.toFixed(3)} ${book.baseCurrency} to get 1000 ${book.quoteCurrency}`);
would produce output similar to
Number of bids: 1849 asks: 2297
Total LTC liquidity: 4004381.314 asks: 172100.402
Cost of buying 100 LTC: 4299.23 USD
Need to sell 23.278 LTC to get 1000 USD
To respond to orderbook messages, simple add an event listener to the book. To respond to ticker events you can do something like
book.on('LiveOrderbook.ticker', (ticker: Ticker) => {
console.log(ticker);
});
And to track total trading volume since connecting, you would have
let tradeVolume: number = 0;
book.on('LiveOrderbook.trade', (trade: TradeMessage) => {
tradeVolume += +(trade.size);
});
A full working example can be found in the repository, in tutorials/t002_liveOrderbook.ts
. It
can be executed by running
$ ts-node src/tutorials/t002_liveOrderbook.ts
to obtain output similar to
2017-08-15T20:35:56.317Z - info: Creating new Coinbase Pro Websocket connection to wss://ws-feed.pro.coinbase.com
2017-08-15T20:35:57.661Z - debug: Connection to wss://ws-feed.pro.coinbase.com has been established.
2017-08-15T20:35:57.662Z - debug: Sending subscribe message to WS server
2017-08-15T20:35:58.697Z - info: Snapshot received by LiveOrderbook Demo
Price: 42.89 | Bid: 42.89 | Ask: 42.90 | sequence: 4282257
Orderbook 266
1.3168 1.3168 $ 42.89 $ 42.90 3.8946 3.8946
67.3168 66.0000 $ 42.88 $ 42.91 1.0826 4.9772
67.3268 0.0100 $ 42.87 $ 42.92 1.0000 5.9772
97.3919 30.0652 $ 42.86 $ 42.94 0.1392 6.1164
117.4271 20.0352 $ 42.85 $ 42.95 0.9465 7.0629
160.4720 43.0449 $ 42.84 $ 42.96 52.4897 59.5527
182.9364 22.4644 $ 42.83 $ 42.97 5.8179 65.3706
182.9713 0.0349 $ 42.82 $ 42.98 11.7460 77.1166
223.0063 40.0349 $ 42.81 $ 42.99 7.4361 84.5527
1225.8337 1002.8275 $ 42.80 $ 43.00 213.4548 298.0075
Number of bids: 1846 asks: 2300
Total LTC liquidity: 4025988.612 asks: 171302.649
Cost of buying 100 LTC: 4296.80 USD
Need to sell 1000.000 LTC to get 1000 USD
2017-08-15T20:36:03.704Z - info: Cumulative trade volume: 27.9451
Orderbook 409
1.3168 1.3168 $ 42.89 $ 42.90 3.8946 3.8946
26.3168 25.0000 $ 42.88 $ 42.91 1.0826 4.9772
56.3268 30.0100 $ 42.87 $ 42.92 1.0000 5.9772
...