Skip to content

Order Book Matching Engine

pytest !pypi !python-versions pre-commit Ruff

Overview

This package is a simple order book matching engine implementation in Python. Its main features are:

  • price-time priority
  • limit and market orders
  • order cancellation and expiration
  • conversion into polars LazyFrame of orders, executed trades, order book summary (optional polars dependency)

Install

# Core matching engine only
pip install order-matching

# With polars export support (recommended for data science workflows)
pip install order-matching[polars]

Documentation

khrapovs.github.io/OrderBookMatchingEngine

Usage

>>> from datetime import datetime, timedelta
>>> from pprint import pp
>>> import polars as pl

>>> from order_matching.matching_engine import MatchingEngine
>>> from order_matching.order import LimitOrder
>>> from order_matching.side import Side
>>> from order_matching.orders import Orders

>>> matching_engine = MatchingEngine(seed=123)
>>> timestamp = datetime(2023, 1, 1)
>>> transaction_timestamp = timestamp + timedelta(days=1)
>>> buy_order = LimitOrder(side=Side.BUY, price=1.2, size=2.3, timestamp=timestamp, order_id="a", trader_id="x")
>>> sell_order = LimitOrder(side=Side.SELL, price=0.8, size=1.6, timestamp=timestamp, order_id="b", trader_id="y")
>>> executed_trades = matching_engine.match(orders=Orders([buy_order, sell_order]), timestamp=transaction_timestamp)

>>> pp(executed_trades.trades)
[Trade(side=SELL,
       price=1.2,
       size=1.6,
       incoming_order_id='b',
       book_order_id='a',
       execution=LIMIT,
       trade_id='c4da537c-1651-4dae-8486-7db30d67b366',
       timestamp=datetime.datetime(2023, 1, 2, 0, 0))]


Data Export (Polars)

If you installed with [polars] extra, you can export data to polars LazyFrame:

>>> from order_matching.orders import Orders
>>> from order_matching.executed_trades import ExecutedTrades
>>> from order_matching.exporters.polars import PolarsExporter

>>> exporter = PolarsExporter()
>>> orders_df = exporter.export_orders(Orders())
>>> trades_df = exporter.export_trades(ExecutedTrades())

>>> trades_df = ExecutedTrades().to_frame()

Contribute

Install project in editable mode and sync all dependencies:

uv sync --all-groups --all-extras

and use pre-commit to make sure that your code is formatted and linted automatically:

uv run prek install

Run tests:

uv run pytest

Run benchmark and see the result either in the terminal or as a plot in benchmark_history.svg:

./benchmark.sh

Build and serve documentation website:

uv run mkdocs serve