A market-data feed for a single stock sends you order-level events. Build PriceLevelBook, which turns them into an aggregated price-level view.
on_order_insert(order_id: int, side: str, price: int, qty: int) -> None: a new resting order.sideis"BUY"or"SELL". Prices are integer ticks;qty > 0.on_order_modify(order_id: int, price: int, qty: int) -> None: the order now has this price and quantity (same side). Its old contribution must be removed before the new one is added; the price may or may not change.on_order_cancel(order_id: int) -> None: the order is gone.get_price_level(side: str, level_index: int) -> tuple[int, int] | None: the(price, total_qty)of the level at zero-based depthlevel_index, orNoneif that side has fewer levels.
A price level is the sum of qty over all live orders on that side at that price. For "BUY", level 0 is the highest price; for "SELL", level 0 is the lowest. A level with no live orders doesn't exist and must not be counted.
Feeds are noisy: ignore an insert whose order_id is already live, and ignore a modify or cancel for an unknown order_id. Once cancelled, an id may be reused by a later insert.
Queries are frequent and mostly near the top of the book, while the book can hold tens of thousands of levels. Don't re-sort every price on each query.
Constraints: up to 10**5 events; order_id is an integer in 0..2**31 - 1; price and qty are integers in 1..10**9; level_index >= 0. A level's total_qty can exceed 32 bits (it is a 64-bit integer in C++/Java).
book = PriceLevelBook()
book.on_order_insert(1, "BUY", 100, 5)
book.on_order_insert(2, "BUY", 101, 3)
book.on_order_insert(3, "BUY", 100, 2)
book.on_order_insert(4, "SELL", 103, 7)
book.get_price_level("BUY", 0) # (101, 3)
book.get_price_level("BUY", 1) # (100, 7)
book.get_price_level("BUY", 2) # None
book.on_order_modify(2, 100, 4) # moves from 101 to 100
book.get_price_level("BUY", 0) # (100, 11)
book.on_order_cancel(4)
book.get_price_level("SELL", 0) # None