Back to trackQuant Developer
Next
Track progress147 items
Order Books

Top-of-Book Ticker

Difficulty

Asked at IMC Trading, Hudson River Trading

Theory: Order Books and Matching

Read the problem, hints and solution here. The editor needs a bigger screen: open this page on a laptop to write and run your code.

Available in Python and C++. You are solving it in Python. Switch to C++

You are building the ticker component of a market data feed: after every order book event, it must publish the current top of book (best bid and best ask).

You receive a sequence of events. Each event is one of:

  • an add event with an order_id, a side, a price and a qty: a new limit order enters the book. side is B for a bid (buy) or S for an ask (sell). Prices are integer ticks. order_id values of add events are unique.
  • a cancel event with an order_id: the order leaves the book. A cancel may reference an id that was never added or was already cancelled; treat that as a no-op.

Implement top_of_book(events) returning one entry per event: the pair (best_bid, best_ask) immediately after applying that event. The best bid is the highest live bid price, the best ask is the lowest live ask price. A side with no live orders has no price. Order quantity never changes and does not affect the top of book in this problem.

def top_of_book(
    events: list[tuple[str, int, str, int, int] | tuple[str, int]],
) -> list[tuple[int | None, int | None]]: ...

An add is ("add", order_id, side, price, qty) with side as "B" or "S", and a cancel is ("cancel", order_id). Use None for a side with no live orders.

Orders are never matched against each other. A bid at or above the best ask does not trade: both orders stay live until they are cancelled, so the book can be crossed (best bid greater than or equal to best ask).

Example

events = [
    ("add", 1, "B", 100, 5),
    ("add", 2, "S", 102, 3),
    ("add", 3, "B", 101, 2),
    ("cancel", 3),
]
top_of_book(events)
# [(100, None), (100, 102), (101, 102), (100, 102)]

Constraints

  • Up to \(10^5\) events.
  • Prices are positive integers; multiple live orders may share a price.
  • Your solution must handle the event volume comfortably: recomputing the best price by scanning every live order on every event will not finish in time.
Terms used in this problem (9)
order book:
The list of resting orders to buy and sell at each price. Bids sit below the current price, asks above it, and each side is kept in price order.
bid:
A resting order to buy, or its price. The best bid is the highest price anyone will pay right now.
ask:
A resting order to sell, or its price, also called the offer. The best ask is the lowest price anyone will sell at right now.
top of book:
The best bid and the best ask, with the quantity resting at each. Most price feeds publish it on every change.
tick:
The smallest step a price can move. Prices in these problems are integers counted in ticks, so there is no rounding.
limit order:
An order to buy at or below a given price, or to sell at or above it. If it cannot trade at once, it rests in the book.
cross:
A bid and an ask cross when the bid price is at or above the ask price, so the two can trade. A crossed book is one where that has happened and not yet been resolved.
market data:
The stream of prices and quantities a venue publishes: trades, quotes and changes to the book.
symbol:
The short code that names an instrument, such as a share or a future.
Rate this problem
Language:
Python 3.12C++23
top_of_book