Maintain Price Levels For A Single-Symbol Order Book
OptiverSoftware Engineer · Technical ScreenLast updated
Design and implement a single-symbol limit order book that tracks individual orders and aggregates quantity by price level, supporting order additions, modifications, cancellations, and best price queries.
Problem Statement
Design a data structure for maintaining active price levels in an order book for a single financial instrument. The order book supports two sides: BUY (bids) and SELL (asks).
Each order has a unique integer order_id, a side ('BUY' or 'SELL'), a positive integer price, and a positive integer quantity.
Implement the OrderBook class with the following methods:
__init__(): Initializes an empty order book.add_order(order_id: int, side: str, price: int, quantity: int) -> bool: Inserts a new order into the book. ReturnsTrueif successfully inserted, orFalseif an order withorder_idalready exists.modify_order(order_id: int, new_quantity: int) -> bool: Updates the remaining quantity of an existing order. Ifnew_quantity bool: Removes the order with the givenorder_id. ReturnsTrueif removed, orFalseiforder_iddoes not exist.get_volume_at_price(side: str, price: int) -> int: Returns the total aggregate quantity currently available at the specifiedsideandprice. Returns0if there are no active orders at that level.get_best_bid() -> int | None: Returns the highest price among activeBUYorders, orNoneif there are no buy orders.get_best_ask() -> int | None: Returns the lowest price among activeSELLorders, orNoneif there are no sell orders.
Constraints
1 <= order_id <= 10^9sideis either'BUY'or'SELL'1 <= price <= 10^61 <= quantity, new_quantity <= 10^6- At most
2 * 10^5calls will be made in total across all methods. - Operations should achieve
O(log P)orO(1)time complexity, wherePis the number of distinct price levels.
Example
book = OrderBook()
book.add_order(1, "BUY", 100, 10) # Returns True
book.add_order(2, "BUY", 100, 15) # Returns True
book.add_order(3, "BUY", 99, 20) # Returns True
book.add_order(4, "SELL", 105, 5) # Returns True
book.get_best_bid() # Returns 100
book.get_best_ask() # Returns 105
book.get_volume_at_price("BUY", 100) # Returns 25 (10 + 15)
book.modify_order(1, 5) # Returns True (quantity reduced to 5)
book.get_volume_at_price("BUY", 100) # Returns 20 (5 + 15)
book.cancel_order(2) # Returns True
book.get_volume_at_price("BUY", 100) # Returns 5
book.cancel_order(1) # Returns True (100 price level now empty)
book.get_best_bid() # Returns 99
Edge Cases
- Canceling or modifying an order that does not exist should return
Falseand not alter state. - Adding an order with an ID that already exists should be rejected.
- When the last order at a price level is canceled or reduced to 0, that price level must be completely cleared so it no longer affects
get_best_bidorget_best_ask. - Book may be completely empty on one or both sides.
Hints
Hint 1
Use a hash map to map each `order_id` to its metadata (side, price, quantity) to support `O(1)` order lookup.
Hint 2
Maintain aggregate volumes in separate price-to-volume maps for each side, and keep active price levels sorted or in a heap to quickly find the best bid (max) and best ask (min).
Hint 3
If using heaps for best bid/ask, employ lazy deletion to discard stale price levels whose total volume has dropped to zero.
Follow-up questions
- How would you extend this design to support matching/crossing incoming market orders against the existing book in price-time priority?
- If heap lazy deletion accumulates too many empty price levels during high-frequency cancel activity, what alternative balanced tree or sorted map structures would maintain strict worst-case bounds?
- How would your design change if memory efficiency was prioritized in a cache-conscious C++ implementation?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.