A high-performance, real-time cryptocurrency exchange matching engine built with FastAPI and Python. This system implements a complete order book with multiple order types, real-time WebSocket feeds, and price-time priority matching.
-
Multiple Order Types
- Market Orders: Execute immediately at best available price
- Limit Orders: Execute at specified price or better, remainder stays in book
- IOC (Immediate-or-Cancel): Execute immediately, cancel unfilled portion
- FOK (Fill-or-Kill): Execute completely or cancel entirely
-
Real-time Market Data
- WebSocket feed for L2 order book snapshots (top 10 levels)
- WebSocket feed for trade executions
- Snapshot updates every 100ms for changed symbols
-
Price-Time Priority Matching
- Best price gets matched first
- Orders at same price level matched by time (FIFO)
- Efficient matching using sorted dictionaries and priority queues
-
Supported Symbols
- BTC, ETH, USDT, SOL
The system follows an event-driven architecture with asynchronous task processing:
- MatchingEngine: Core matching logic for all order types
- OrderBook: Maintains bid/ask queues with price-time priority
- Publisher: Broadcasts trade executions and order book updates
- WebSocket Endpoints: Real-time data feeds to clients
- Python 3.12 or higher
- uv package manager (recommended)
- Docker (optional, for containerized deployment)
- Clone the repository:
git clone <repository-url>
cd exchange-assignment- Install dependencies using uv:
uv syncOr using pip:
pip install -r requirements.txt- Create a
.envfile in the root directory:
HOST=0.0.0.0
PORT=8000uv run main.pyOr:
python main.pyThe server will start on http://localhost:8000
docker-compose up --buildGET /health
Returns server health status.
Response:
{
"message": "OK"
}POST /v1/orders
Submit a new order to the matching engine.
Request Body:
{
"type": "limit",
"symbol": "BTC",
"side": "buy",
"quantity": "1.5",
"price": "50000.00"
}Parameters:
type(string): Order type -market,limit,ioc, orfoksymbol(string): Trading symbol -BTC,ETH,USDT, orSOLside(string): Order side -buyorsellquantity(decimal): Order quantity (must be > 0)price(decimal): Limit price (required for limit/ioc/fok, optional for market)
Response:
{
"message": "order created",
"order_id": "123e4567-e89b-12d3-a456-426614174000"
}WS /v1/ws/market-data
Subscribe to real-time order book snapshots (L2 data).
Message Format:
{
"timestamp": "2025-10-08T12:34:56.789",
"symbol": "BTC",
"bids": [
["50000.00", "1.5"],
["49999.00", "2.3"]
],
"asks": [
["50001.00", "0.8"],
["50002.00", "1.2"]
]
}WS /v1/ws/trades
Subscribe to real-time trade executions.
Message Format:
{
"timestamp": "2025-10-08T12:34:56.789",
"symbol": "BTC",
"trade_id": "987f6543-e21b-43c1-b123-987654321000",
"price": "50000.00",
"quantity": "1.5",
"aggressor_side": "buy",
"maker_order_id": "123e4567-e89b-12d3-a456-426614174000",
"taker_order_id": "234e5678-e89b-12d3-a456-426614174001"
}- Match against best available prices on opposite side
- Continue matching until fully filled or no liquidity
- Status:
filledorpartially_filled/cancelledif liquidity exhausted
- Match against acceptable prices (buy at ≤ limit, sell at ≥ limit)
- Unfilled quantity added to order book
- Status:
filled,partially_filled, orpending
- Match immediately at acceptable prices
- Cancel any unfilled quantity (never sits in book)
- Status:
filled,partially_filled, orcancelled
- Check if full quantity can be filled before executing
- Either fill completely or cancel entirely
- Status:
filledorcancelled
exchange-assignment/
├── app/
│ ├── core/
│ │ └── settings.py # Application configuration
│ ├── model/
│ │ ├── order.py # Order data models
│ │ ├── order_book.py # OrderBook implementation
│ │ ├── order_book_factory.py # Factory for managing multiple order books
│ │ └── trade_execution.py # Trade execution data model
│ ├── routes/
│ │ └── v1/
│ │ └── endpoints/
│ │ └── main.py # API endpoints
│ ├── services/
│ │ ├── matching_engine.py # Core matching logic
│ │ └── publisher.py # WebSocket message publisher
│ ├── dependencies.py # FastAPI dependencies
│ └── server.py # FastAPI application setup
├── Dockerfile
├── docker-compose.yml
├── main.py # Application entry point
├── pyproject.toml # Project dependencies
└── README.md
- FastAPI: High-performance async web framework
- Pydantic: Data validation and settings management
- sortedcontainers: Efficient sorted data structures for order books
- uvicorn: ASGI server
- WebSockets: Real-time bidirectional communication
- Async I/O: Non-blocking operations throughout the stack
- Efficient Data Structures: SortedDict for O(log n) price level operations
- Lazy Cleanup: Cancelled orders marked in-place to avoid queue reorganization
- Snapshot Optimization: Only generates snapshots for symbols with changes
- Queue-based Architecture: Decouples order submission from matching
The project follows Python best practices:
- Type hints throughout
- Pydantic models for data validation
- Async/await for concurrency
- Clear separation of concerns
