Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Orderbook

Implementation of a limit order book with price-time priority, together with a synthetic order flow generator so there is something to run it against.

Features

  • Limit and market orders, cancels
  • Matching best price first, FIFO within a price, trades printed at the resting order's price
  • An aggressive order walks as many price levels as it needs and rests the remainder
  • Aggregated depth snapshots and top of book
  • A simulator that generates random order flow around a drifting fair price

Run instructions

pip install -e ".[dev]"
python -m orderbook.cli --steps 2000 --seed 3 --levels 5
             bids         |         asks
           1,700   99.95  |  99.96   300
           1,100   99.92  |  99.97   1,300
             200   99.91  |  99.98   1,700
             900   99.90  |  99.99   2,200
             400   99.89  |  100.00  1,100

      spread 0.01   mid 99.955
      last  99.96
      48 resting orders

last trades
      99.97 x 300 (buy 1720 / sell 1718, aggressor B)
      99.97 x 200 (buy 1720 / sell 1721, aggressor S)
      99.95 x 200 (buy 1712 / sell 1722, aggressor S)
      99.96 x 500 (buy 1726 / sell 1721, aggressor B)

orders 1,726   cancels 274   trades 1,186   volume 248,900   vwap 99.88

Using it directly

from orderbook import OrderBook, Side

book = OrderBook("AAPL")
book.limit(Side.SELL, 10_050, 300)          # 300 @ 100.50
report = book.limit(Side.BUY, 10_100, 500)  # buys 300, rests 200

report.trades        # [Trade(price=10050, qty=300, ...)]
report.resting_qty   # 200
book.best_bid        # 10100
book.depth(5)        # ([(10100, 200)], [])
book.cancel(report.order_id)

Prices are integers in ticks (cents), so 100.50 is 10050. Floats would put orders that should share a price onto two different levels.

Implementation details

OrderBook keeps a dict of price -> PriceLevel per side, and a sorted list of the live prices on that side, maintained with bisect. The list gives the best bid and ask in O(1) and depth queries in order; the dict gives the level for a price in O(1).

A PriceLevel holds its orders in a dict keyed by order id. Dicts keep insertion order, so iterating a level is FIFO — which is what time priority means — while removing a cancelled order in the middle stays O(1). It also tracks the aggregate size at that price so depth queries never sum a queue.

A separate order_id -> Order map makes cancels O(1): a cancel arrives with an id and nothing else, so without it every cancel would be a scan.

add / cancel O(1), plus a bisect insert or removal when a price level appears or empties
best bid / ask O(1)
depth(k) O(k)
match O(number of orders filled)

Tests

pytest

The suite covers the matching rules (price priority, time priority, partial fills, walking levels, an aggressor stopping at its limit), and runs random sessions through the simulator checking after every batch of messages that the book is not crossed, that level sizes equal the sum of their orders, and that emptied levels are removed rather than left at zero.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages