Matching Engine
Understanding the order matching algorithm
Overview
The matching engine is the core component of the stock exchange that matches buy and sell orders. It uses a price-time priority algorithm to ensure fair and efficient order execution.
How It Works
Price-Time Priority
The matching engine follows two fundamental rules:
-
Price Priority: Orders with better prices are matched first
- For buy orders: Higher prices have priority
- For sell orders: Lower prices have priority
-
Time Priority: Among orders at the same price, earlier orders are matched first (FIFO - First In, First Out)
This is the same matching algorithm used by major stock exchanges worldwide, including NYSE and NASDAQ.
Order Types
Limit Orders
A limit order specifies the maximum price you're willing to pay (buy) or minimum price you'll accept (sell).
{
"type": "LIMIT",
"bid": true,
"price": 1000,
"size": 10
}Characteristics:
- ✅ Price protection
- ✅ May not execute immediately
- ✅ Remains in orderbook until filled or cancelled
Market Orders
A market order executes immediately at the best available price.
{
"type": "MARKET",
"bid": true,
"size": 10
}Characteristics:
- ✅ Immediate execution
- ❌ No price protection
- ✅ Never remains in orderbook
Matching Process
Order Received
When a new order arrives, the matching engine determines if it can be immediately matched.
Check Opposite Side
The engine looks at the opposite side of the orderbook:
- Buy orders check the ask side
- Sell orders check the bid side
Match at Best Price
If there's a matching order:
- The trade executes at the maker's price (the order already in the book)
- Both orders are reduced by the matched quantity
- A trade record is created
Partial Fills
If the incoming order is larger than available liquidity:
- Multiple matches occur at different price levels
- The order is partially filled
- Remaining quantity stays in the orderbook (for limit orders)
Add to Orderbook
If unmatched quantity remains (limit orders only):
- The order is added to the appropriate side of the orderbook
- It becomes available for matching with future orders
Example Scenarios
Scenario 1: Full Match
Orderbook State:
Asks: 1005 (50 shares)
1010 (30 shares)
Bids: 995 (40 shares)
990 (50 shares)New Order: Market Buy 50 shares
Result:
- Executes 50 shares at 1005
- Trade recorded: 50 @ 1005
- Ask at 1005 is removed from book
Scenario 2: Partial Fill
Orderbook State:
Asks: 1005 (30 shares)
1010 (50 shares)
Bids: 995 (40 shares)New Order: Market Buy 70 shares
Result:
- Executes 30 shares at 1005
- Executes 40 shares at 1010
- Two trades recorded
- Both asks partially filled
Scenario 3: No Match
Orderbook State:
Asks: 1010 (50 shares)
Bids: 995 (40 shares)New Order: Limit Buy 20 @ 1000
Result:
- No immediate match (1000 < 1010)
- Order added to bid side at 1000
Performance Characteristics
The matching engine is optimized for high performance:
| Operation | Time Complexity |
|---|---|
| Place Order | O(1) amortized |
| Match Order | O(k) where k = number of matches |
| Get Best Bid/Ask | O(1) |
| Cancel Order | O(1) |
The engine can process thousands of orders per second with minimal latency.
Data Structures
The orderbook uses efficient data structures:
- Price Levels: Hash map for O(1) access to each price level
- Order Queue: Linked list for FIFO ordering at each price
- Price Tree: Ordered structure for finding best bid/ask
type Orderbook struct {
asks []*Limit
bids []*Limit
Orders map[int64]*Order
}
type Limit struct {
Price float64
Orders []*Order
TotalVolume int
}Trade Generation
When orders match, the engine generates trade records:
type Trade struct {
Price float64
Size int
Timestamp int64
Bid bool
}These trades represent actual executions and are used for:
- Trade history
- Price charts
- Volume calculations
- Market data feeds