Price-time priority with price levels in a heap and a FIFO per level, partial fills at the resting price, market orders that never rest, and lazy O(1) cancels.
Build the core of the order-book round: the matching engine for one symbol. Prices are integer ticks (paise), quantities whole shares, and the book is single-threaded by design (no locks). Trade and px(ticks) ("101.00" for 10100) are given. Sides are "buy" / "sell", order types "limit" / "market", statuses "open", "partial", "filled", "cancelled".
Order(order_id, trader, side, type, qty, price=None, tif="gtc"): a non-positive qty, a limit order without a positive price or a market order with one raises ValueError. It has seq (arrival number, set by the book), filled, status (starts open) and remaining.BookSide(side) with levels (price to PriceLevel) where a PriceLevel has price, orders (a FIFO, oldest first) and total (live quantity):
add(order) puts the order at the back of its price level; a new price is pushed on a heap (bids: highest first).best() returns the best level that still has live quantity, dropping emptied levels as it meets them; None when empty.depth(n=5) returns [(px, total), ...] best first, only levels with live quantity.OrderBook(symbol) with bids, asks, orders (resting orders by id), trades and processed:
submit(order) numbers the order (seq from 1), then matches it against the opposite side while it crosses (a buy crosses asks at or below its price; a market order crosses everything). Each fill trades min(taker remaining, maker remaining) at the resting order's price and returns Trades numbered from 1 (Trade(trade_id, buy_order, sell_order, price, qty)). Earlier orders at a price fill first. Leftover limit quantity rests in the book; a leftover market order is cancelled, never rested.tif="gtc" (good till cancelled, the default) rests a limit order's leftover. tif="ioc" (immediate-or-cancel) is a limit order that trades whatever crosses now and cancels the rest, exactly like a market order's leftover. A new policy is one branch in the rest-or-cancel step after the matching loop; the loop itself does not change.cancel(order_id) returns True if a resting order was cancelled, False for an unknown, filled or already cancelled id. It must be O(1): reduce the level's total and mark the order cancelled; the order leaves the FIFO lazily when a match reaches it.JavaScript and TypeScript: camelCase (orderId, buyOrder, sellOrder, tradeId), new Order(orderId, trader, side, type, qty, price = null, tif = "gtc"), remaining is a getter, depth returns [[px, total], ...], a bad order throws an Error.
Write your code, then run 10 example tests and 4 hidden tests. Each run is limited to 8 seconds: an infinite loop gets stopped and the runtime restarts, your code stays.