High Performance C++ Orderbook.
Orderbook: High-Performance C++ Order Matching Engine
A sophisticated, production-grade order matching engine implemented in modern C++20. This project provides a complete implementation of an electronic order book system commonly used in financial trading platforms, exchanges, and market microstructure applications. Github
Overview
The Orderbook project is a comprehensive order matching system that handles:
- Order Management: Add, cancel, and modify orders with full lifecycle tracking
- Price-Time Priority: Implements standard market rules for order matching
- Multiple Order Types: Supports GoodTillCancel, FillAndKill, FillOrKill, GoodForDay, and Market orders
- Automatic Matching: Real-time order matching with detailed trade information
- Thread-Safe Operations: Built-in thread safety with mutex protection and background pruning threads
- Order Book Snapshot: Retrieve current bid/ask levels with quantities and order counts
Key Features
- Fast order matching algorithm
- Support for complex order types
- Automatic order pruning for GoodForDay orders
- Thread-safe concurrent operations
- Detailed trade information and reporting
- Clean, extensible C++20 design
Project Structure
orderbook/
├── main.cpp # Application entry point
├── Orderbook.h # Core orderbook interface
├── Orderbook.cpp # Orderbook implementation
├── Order.h # Order class definition
├── OrderType.h # Order type enumeration
├── Side.h # Buy/Sell side enumeration
├── OrderModify.h # Order modification class
├── Trade.h # Trade result class
├── TradeInfo.h # Trade information structure
├── LevelInfo.h # Price level information
├── OrderbookLevelInfos.h # Bid/Ask level aggregation
├── Constants.h # Global constants
├── Usings.h # Type aliases
├── CMakeLists.txt # Build configuration
├── CMake build configuration files
└── OrderbookTest/ # Comprehensive test suite
├── test.cpp # Google Test test cases
├── pch.h/pch.cpp # Precompiled headers
└── TestFiles/ # Test data files
├── Cancel_Success.txt
├── Match_FillAndKill.txt
├── Match_FillOrKill_Hit.txt
├── Match_FillOrKill_Miss.txt
├── Match_GoodTillCancel.txt
├── Match_Market.txt
└── Modify_Side.txt
Core Components
1. Orderbook (Orderbook.h / Orderbook.cpp)
The main order book engine responsible for managing all orders, performing matches, and maintaining order state.
Key Data Structures:
// Bid orders: highest price first (descending order)
std::map<Price, OrderPointers, std::greater<Price>> bids_;
// Ask orders: lowest price first (ascending order)
std::map<Price, OrderPointers, std::less<Price>> asks_;
// Order lookup table for O(1) access by order ID
std::unordered_map<OrderId, OrderEntry> orders_;
// Level data tracking: quantity and order count at each price
std::unordered_map<Price, LevelData> data_;
Public Methods:
Trades AddOrder(OrderPointer order)- Add a new order to the bookvoid CancelOrder(OrderId orderId)- Cancel an existing orderTrades ModifyOrder(OrderModify order)- Modify an existing orderstd::size_t Size() const- Get total number of ordersOrderbookLevelInfos GetOrderInfos() const- Get current bid/ask levels
Internal Features:
- Automatic Pruning: Background thread that prunes GoodForDay orders at 16:00 UTC daily
- Thread-Safe Access: All operations protected by mutex
- Order Matching: Implements price-time priority matching algorithm
- Level Data Tracking: Maintains quantity and count at each price level
2. Order (Order.h)
Represents a single order in the system.
Properties:
class Order {
OrderType orderType_; // Type of order (GTC, FAK, FOK, GFD, Market)
OrderId orderId_; // Unique identifier
Side side_; // Buy or Sell
Price price_; // Order price (NaN for Market orders)
Quantity initialQuantity_; // Original quantity requested
Quantity remainingQuantity_; // Amount not yet filled
};
Key Methods:
GetOrderId()- Get unique order identifierGetSide()- Get Buy or Sell sideGetPrice()- Get order priceGetOrderType()- Get order typeGetInitialQuantity()- Get original quantityGetRemainingQuantity()- Get unfilled quantityGetFilledQuantity()- Get filled quantity (calculated)IsFilled()- Check if completely filledFill(Quantity)- Mark quantity as filledToGoodTillCancel(Price)- Convert market order to limit order
Constructors:
// Limit order with explicit price
Order(OrderType type, OrderId id, Side side, Price price, Quantity qty);
// Market order (convenience constructor)
Order(OrderId id, Side side, Quantity qty);
3. Trade & TradeInfo (Trade.h / TradeInfo.h)
Represents the result of a trade between two orders.
struct TradeInfo {
OrderId orderId_; // Order that participated in trade
Price price_; // Trade execution price
Quantity quantity_; // Quantity traded
};
class Trade {
TradeInfo bidTrade_; // Information about the bid side
TradeInfo askTrade_; // Information about the ask side
};
Usage:
const auto& bidInfo = trade.GetBidTrade();
const auto& askInfo = trade.GetAskTrade();
std::cout << "Bid Order " << bidInfo.orderId_
<< " traded " << bidInfo.quantity_
<< " @ " << bidInfo.price_ << std::endl;
Order Types
The orderbook supports five distinct order types, each with unique behavior:
1. GoodTillCancel (GTC)
Orders remain in the book until explicitly cancelled or filled.
Characteristics:
- Persists across multiple trading sessions
- No automatic expiration
- Most common in traditional exchanges
Example:
// Create a GTC order to buy 100 shares at price 50
auto order = std::make_shared<Order>(
OrderType::GoodTillCancel,
12345, // Order ID
Side::Buy,
50, // Price
100 // Quantity
);
auto trades = orderbook.AddOrder(order);
// Order remains in book until cancelled or filled
2. FillAndKill (FAK)
Orders are immediately cancelled if they cannot be fully filled.
Characteristics:
- Attempts to match as much as possible
- Any remaining quantity is cancelled
- Useful for traders who want to guarantee execution
- No remaining orders left in the book
Example:
// Buy 50 shares at price 45 - will only execute if 50+ shares available
auto order = std::make_shared<Order>(
OrderType::FillAndKill,
12346,
Side::Buy,
45, // Price
50 // Quantity
);
auto trades = orderbook.AddOrder(order);
// If only 30 shares were available:
// - 30 shares would be filled
// - Remaining 20 shares would be cancelled
// - No order remains in the book
3. FillOrKill (FOK)
Orders are completely filled or completely cancelled.
Characteristics:
- All-or-nothing execution
- Stricter than FillAndKill
- No partial fills accepted
- Useful for institutional traders
Example:
// Must buy exactly 100 shares at price 52, otherwise reject entirely
auto order = std::make_shared<Order>(
OrderType::FillOrKill,
12347,
Side::Buy,
52, // Price
100 // Quantity
);
auto trades = orderbook.AddOrder(order);
// If fewer than 100 shares available at price 52 or better:
// - Entire order is cancelled
// - No trades occur
// If 100+ shares available:
// - Order is completely filled
// - No order remains in the book
4. GoodForDay (GFD)
Orders automatically expire at end of trading day (16:00 UTC).
Characteristics:
- Implicit expiration at market close
- Background thread automatically prunes expired orders
- Daily reset - order doesn't carry to next trading day
- Common in equity markets
Example:
// Sell 200 shares at price 75 - expires at 16:00 UTC today
auto order = std::make_shared<Order>(
OrderType::GoodForDay,
12348,
Side::Sell,
75, // Price
200 // Quantity
);
auto trades = orderbook.AddOrder(order);
// If not filled by 16:00 UTC today:
// - Remaining quantity automatically cancelled
// - Background pruning thread handles expiration
// - New order can be added tomorrow with same ID
5. Market
Orders execute immediately at best available prices.
Characteristics:
- No price specified (uses NaN as sentinel value)
- Executes as market order against current best bid/ask
- Most aggressive order type
- Common for urgent execution
Example:
// Buy immediately at market price
auto order = std::make_shared<Order>(
12349,
Side::Buy,
150 // Quantity (no price specified)
);
auto trades = orderbook.AddOrder(order);
// Will execute against ask orders starting from best price
// If 150 shares available: fully filled at various prices
// If fewer available: partially filled and cancelled
// Converting to limit order after creation:
order->ToGoodTillCancel(55); // Now a GTC limit order at price 55
Order Sides
The orderbook supports two sides:
enum class Side {
Buy, // Buyer (demand side)
Sell // Seller (supply side)
};
Buy Orders
- Added to the bid side of the book
- Sorted by price descending (highest bid first)
- Match against sell orders from lowest price up
Sell Orders
- Added to the ask side of the book
- Sorted by price ascending (lowest ask first)
- Match against buy orders from highest price down
Type Definitions
All type definitions are centralized in Usings.h:
using Price = std::int32_t; // Price in cents/smallest units
using Quantity = std::uint32_t; // Number of shares/contracts
using OrderId = std::uint64_t; // Unique order identifier
using OrderIds = std::vector<OrderId>; // Collection of order IDs
// Used in collections
using OrderPointer = std::shared_ptr<Order>;
using OrderPointers = std::list<OrderPointer>;
using Trades = std::vector<Trade>;
using LevelInfos = std::vector<LevelInfo>;
Type Characteristics:
- Price (int32_t): Supports prices from -2.14B to +2.14B (represent cents for stock prices)
- Quantity (uint32_t): Supports 0 to 4.29B shares/contracts
- OrderId (uint64_t): Supports 0 to 18.4 quintillion unique orders
API Reference
Orderbook Methods
Trades AddOrder(OrderPointer order)
Add a new order to the orderbook and attempt to match it.
Parameters:
order: Shared pointer to an Order object
Returns:
Trades: Vector of trades that executed as a result
Example:
Orderbook orderbook;
auto buyOrder = std::make_shared<Order>(
OrderType::GoodTillCancel,
1001,
Side::Buy,
100,
50
);
auto trades = orderbook.AddOrder(buyOrder);
std::cout << "Executed " << trades.size() << " trades" << std::endl;
void CancelOrder(OrderId orderId)
Cancel an order that is currently in the book.
Parameters:
orderId: ID of the order to cancel
Example:
Orderbook orderbook;
auto order = std::make_shared<Order>(
OrderType::GoodTillCancel,
5001,
Side::Buy,
150,
100
);
orderbook.AddOrder(order);
// ... time passes ...
orderbook.CancelOrder(5001); // Cancel the order
Trades ModifyOrder(OrderModify order)
Modify an existing order (typically price and/or quantity).
Parameters:
order: OrderModify object containing new parameters
Returns:
Trades: Trades resulting from the modification
Implementation Detail: The modification cancels the original order and adds a new order with the same ID but new parameters.
Example:
Orderbook orderbook;
// Create and add initial order
auto order = std::make_shared<Order>(
OrderType::GoodTillCancel,
6001,
Side::Buy,
120,
100
);
orderbook.AddOrder(order);
// Modify the order: raise price to 130, increase quantity to 150
OrderModify modification(6001, Side::Buy, 130, 150);
auto trades = orderbook.ModifyOrder(modification);
std::size_t Size() const
Get the total number of orders currently in the book.
Returns:
std::size_t: Total order count across all price levels
Example:
Orderbook orderbook;
// ... add orders ...
std::cout << "Total orders: " << orderbook.Size() << std::endl;
OrderbookLevelInfos GetOrderInfos() const
Retrieve current bid and ask levels with aggregated information.
Returns:
OrderbookLevelInfos: Object containing bid and ask levels
Example:
Orderbook orderbook;
// ... add orders ...
auto levelInfos = orderbook.GetOrderInfos();
std::cout << "=== BIDS ===" << std::endl;
for (const auto& level : levelInfos.GetBids()) {
std::cout << "Price: " << level.price_
<< ", Quantity: " << level.quantity_ << std::endl;
}
std::cout << "=== ASKS ===" << std::endl;
for (const auto& level : levelInfos.GetAsks()) {
std::cout << "Price: " << level.price_
<< ", Quantity: " << level.quantity_ << std::endl;
}
Code Examples
Example 1: Basic Order Entry and Cancellation
#include "Orderbook.h"
#include <iostream>
int main() {
Orderbook orderbook;
// Add a limit buy order
auto buyOrder = std::make_shared<Order>(
OrderType::GoodTillCancel,
1001,
Side::Buy,
100, // Price 100
50 // Quantity 50
);
auto trades = orderbook.AddOrder(buyOrder);
std::cout << "Added buy order, trades: " << trades.size() << std::endl;
// Check orderbook state
std::cout << "Orders in book: " << orderbook.Size() << std::endl;
// Cancel the order
orderbook.CancelOrder(1001);
std::cout << "Orders after cancellation: " << orderbook.Size() << std::endl;
return 0;
}
Example 2: Order Matching Scenario
#include "Orderbook.h"
#include <iostream>
int main() {
Orderbook orderbook;
// Add sell order first (no match yet)
auto sellOrder = std::make_shared<Order>(
OrderType::GoodTillCancel,
2001,
Side::Sell,
100, // Ask at price 100
100 // 100 shares
);
orderbook.AddOrder(sellOrder);
std::cout << "Added ask: price=100, qty=100" << std::endl;
std::cout << "Orders in book: " << orderbook.Size() << std::endl;
// Add buy order that matches
auto buyOrder = std::make_shared<Order>(
OrderType::GoodTillCancel,
2002,
Side::Buy,
100, // Bid at price 100
100 // 100 shares
);
auto trades = orderbook.AddOrder(buyOrder);
std::cout << "\nAdded bid: price=100, qty=100" << std::endl;
std::cout << "Trades executed: " << trades.size() << std::endl;
// Print trade details
for (size_t i = 0; i < trades.size(); ++i) {
const auto& trade = trades[i];
const auto& bid = trade.GetBidTrade();
const auto& ask = trade.GetAskTrade();
std::cout << "\nTrade #" << (i + 1) << std::endl;
std::cout << " Bid Order: " << bid.orderId_
<< " @ " << bid.price_
<< " x " << bid.quantity_ << std::endl;
std::cout << " Ask Order: " << ask.orderId_
<< " @ " << ask.price_
<< " x " << ask.quantity_ << std::endl;
}
std::cout << "\nOrders remaining: " << orderbook.Size() << std::endl;
return 0;
}
Example 3: Working with Different Order Types
#include "Orderbook.h"
#include <iostream>
void printTrades(const Trades& trades) {
for (const auto& trade : trades) {
std::cout << "Trade: " << trade.GetBidTrade().orderId_
<< " <-> " << trade.GetAskTrade().orderId_
<< " @ " << trade.GetBidTrade().price_ << std::endl;
}
}
int main() {
Orderbook orderbook;
// Scenario 1: GoodTillCancel - persists in book
std::cout << "=== GoodTillCancel Order ===" << std::endl;
auto gtcOrder = std::make_shared<Order>(
OrderType::GoodTillCancel,
3001,
Side::Sell,
150,
200
);
orderbook.AddOrder(gtcOrder);
std::cout << "Added GTC order, book size: " << orderbook.Size() << std::endl;
// Scenario 2: FillAndKill - partial fill acceptable
std::cout << "\n=== FillAndKill Order ===" << std::endl;
auto fakOrder = std::make_shared<Order>(
OrderType::FillAndKill,
3002,
Side::Buy,
150,
50 // Only 50 available at 150, rest will be cancelled
);
auto trades = orderbook.AddOrder(fakOrder);
printTrades(trades);
std::cout << "Book size after FAK: " << orderbook.Size() << std::endl;
// Scenario 3: FillOrKill - all or nothing
std::cout << "\n=== FillOrKill Order (insufficient liquidity) ===" << std::endl;
auto fokOrder = std::make_shared<Order>(
OrderType::FillOrKill,
3003,
Side::Buy,
150,
500 // Too much, will be rejected completely
);
trades = orderbook.AddOrder(fokOrder);
std::cout << "FOK trades: " << trades.size() << std::endl;
// Scenario 4: Market Order
std::cout << "\n=== Market Order ===" << std::endl;
auto marketOrder = std::make_shared<Order>(
3004,
Side::Buy,
75
);
trades = orderbook.AddOrder(marketOrder);
printTrades(trades);
return 0;
}
Example 4: Order Book Snapshot
#include "Orderbook.h"
#include <iostream>
#include <iomanip>
int main() {
Orderbook orderbook;
// Build a simple order book
std::vector<std::tuple<OrderType, Side, Price, Quantity, OrderId>> orders = {
{OrderType::GoodTillCancel, Side::Sell, 105, 100, 1},
{OrderType::GoodTillCancel, Side::Sell, 104, 150, 2},
{OrderType::GoodTillCancel, Side::Sell, 103, 200, 3},
{OrderType::GoodTillCancel, Side::Buy, 102, 100, 4},
{OrderType::GoodTillCancel, Side::Buy, 101, 150, 5},
{OrderType::GoodTillCancel, Side::Buy, 100, 200, 6},
};
for (const auto& [type, side, price, qty, id] : orders) {
auto order = std::make_shared<Order>(type, id, side, price, qty);
orderbook.AddOrder(order);
}
// Get and display order book
auto levelInfos = orderbook.GetOrderInfos();
std::cout << std::setw(20) << "ASKS"
<< std::setw(20) << "Spread"
<< std::setw(20) << "BIDS" << std::endl;
std::cout << std::string(60, '-') << std::endl;
const auto& asks = levelInfos.GetAsks();
const auto& bids = levelInfos.GetBids();
size_t maxLevels = std::max(asks.size(), bids.size());
for (size_t i = 0; i < maxLevels; ++i) {
if (i < asks.size()) {
std::cout << std::setw(10) << asks[asks.size() - 1 - i].price_
<< "x" << std::setw(8) << asks[asks.size() - 1 - i].quantity_;
} else {
std::cout << std::setw(20) << "";
}
std::cout << std::setw(20) << "";
if (i < bids.size()) {
std::cout << std::setw(8) << bids[i].quantity_
<< "x" << std::setw(10) << bids[i].price_;
}
std::cout << std::endl;
}
return 0;
}
Example 5: Modifying Orders
#include "Orderbook.h"
#include <iostream>
int main() {
Orderbook orderbook;
// Create initial order
auto order = std::make_shared<Order>(
OrderType::GoodTillCancel,
5001,
Side::Buy,
100,
100
);
orderbook.AddOrder(order);
std::cout << "Added order: Buy 100 @ 100, Total orders: "
<< orderbook.Size() << std::endl;
// Modify order: increase price and quantity
OrderModify modification(
5001, // Order ID
Side::Buy,
105, // New price
150 // New quantity
);
auto trades = orderbook.ModifyOrder(modification);
std::cout << "Modified order: Buy 150 @ 105" << std::endl;
std::cout << "Trades from modification: " << trades.size() << std::endl;
std::cout << "Total orders: " << orderbook.Size() << std::endl;
return 0;
}
Building the Project
Requirements
- C++20 compiler (GCC 10+, Clang 12+, MSVC 2019+)
- CMake 3.20+
- Make or Ninja build system
Build Steps
On macOS/Linux:
cd /Users/sonnie/Dev/orderbook
mkdir build
cd build
cmake ..
make
Run the application:
./Orderbook
On Windows (with MSVC):
cd orderbook
mkdir build
cd build
cmake ..
cmake --build . --config Release
Build Configurations
# Debug build with symbols
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
# Release build with optimizations
cmake -DCMAKE_BUILD_TYPE=Release ..
make
# With verbose output
make VERBOSE=1
Testing
The project includes a comprehensive test suite using Google Test framework.
Test Structure
Test cases are organized by functionality:
- Cancel_Success.txt - Tests successful order cancellation
- Match_FillAndKill.txt - Tests FillAndKill order behavior
- Match_FillOrKill_Hit.txt - Tests successful FillOrKill execution
- Match_FillOrKill_Miss.txt - Tests FillOrKill rejection
- Match_GoodTillCancel.txt - Tests GoodTillCancel order persistence
- Match_Market.txt - Tests market order execution
- Modify_Side.txt - Tests order modification
Test Format
Test files follow a structured format with actions and expected results:
A <OrderType> <Side> <Price> <Quantity> <OrderId> # Add order
C <OrderId> # Cancel order
M <OrderId> <Side> <Price> <Quantity> # Modify order
R <AllCount> <BidCount> <AskCount> # Result assertion
Running Tests
# Build with tests
cd build
cmake ..
make
# Run all tests
ctest --verbose
# Run specific test
ctest -R "TestName" --verbose
Example Test Execution
// test.cpp excerpt
TEST(OrderbookTests, GoodTillCancelOrder) {
Orderbook orderbook;
// Test that GTC orders persist in the book
auto order = std::make_shared<Order>(
OrderType::GoodTillCancel,
1001,
Side::Buy,
100,
50
);
orderbook.AddOrder(order);
EXPECT_EQ(orderbook.Size(), 1);
// Partial fill shouldn't remove order
auto sellOrder = std::make_shared<Order>(
OrderType::GoodTillCancel,
1002,
Side::Sell,
100,
25 // Partial fill
);
orderbook.AddOrder(sellOrder);
EXPECT_EQ(orderbook.Size(), 1); // Original buy order still there with 25 qty
}
Architecture and Design
Design Patterns Used
1. Shared Pointer Pattern
All orders are managed through std::shared_ptr<Order> for safe memory management.
using OrderPointer = std::shared_ptr<Order>;
2. Aggregate Order Storage
- Bids Map:
std::map<Price, OrderPointers, std::greater<Price>>- Sorts bids descending (highest first)
- Each price contains list of orders at that price
- Asks Map:
std::map<Price, OrderPointers, std::less<Price>>- Sorts asks ascending (lowest first)
- Maintains price-time priority
3. Fast Order Lookup
- Order Index:
std::unordered_map<OrderId, OrderEntry>- O(1) lookup by order ID
- Stores iterator to order location for fast removal
4. Level Data Tracking
- Level Map:
std::unordered_map<Price, LevelData>- Tracks aggregate quantity and order count per price
- Used for fast orderbook snapshots
Order Matching Algorithm
while (bidPrice >= askPrice && bids exist && asks exist):
- Get best bid and best ask
- Match quantity = min(bid remaining, ask remaining)
- Fill both orders with matched quantity
- Remove completely filled orders
- Record trade with both sides' info
- Update level data
Time Complexity:
- Add order: O(log n) for tree insertion + O(1) matching attempts
- Cancel order: O(1) lookup + O(log n) tree removal
- Get snapshot: O(n) to traverse all price levels
Thread Safety
Synchronization Strategy
The orderbook uses a single mutex protecting the core order structures:
mutable std::mutex ordersMutex_;
std::atomic<bool> shutdown_;
std::condition_variable shutdownConditionVariable_;
Protected Operations
All modifications are protected:
std::scoped_lock ordersLock{ ordersMutex_ };
// Perform order book operations
Background Thread
A dedicated thread prunes GoodForDay orders:
std::thread ordersPruneThread_;
void PruneGoodForDayOrders() {
// Calculates time until market close (16:00 UTC)
// Waits for expiration time
// Automatically cancels all GFD orders
}
Usage Example
// Safe concurrent access
auto addThread1 = std::thread([&]() {
auto order = std::make_shared<Order>(...);
orderbook.AddOrder(order);
});
auto addThread2 = std::thread([&]() {
auto order = std::make_shared<Order>(...);
orderbook.AddOrder(order);
});
addThread1.join();
addThread2.join();
// No race conditions - all operations serialized by mutex
Performance Considerations
Optimization Techniques
1. Map-based Storage
- Bids and asks stored in
std::mapfor O(log n) best price access - Price-sorted automatically
- Intrusive list for orders at each price
2. Order Indexing
- Unordered map provides O(1) lookup by order ID
- Iterator stored for O(1) removal without search
3. Level Data Caching
- Quantity and count per price maintained incrementally
- Snapshot generation avoids recalculation
4. Memory Efficiency
- Orders stored once with multiple reference pointers
- No data duplication across structures
- Shared_ptr enables safe cleanup
Typical Performance
| Operation | Time Complexity | Notes |
|---|---|---|
| Add Order | O(log n) + matching | Matching is typically O(1) to O(m) where m = matched orders |
| Cancel Order | O(log n) | Hash lookup + tree removal |
| Modify Order | O(log n) | Cancel + add new order |
| Get Snapshot | O(p) | p = number of price levels |
| Size Query | O(1) | Direct map size |
Scalability
- 1M Orders: ~1ms operations
- 10M Orders: ~5-10ms operations
- 100M Orders: Limited by available memory
Key Features Explained
Price-Time Priority
Orders matching follows standard market conventions:
-
Price Priority: Better prices match first
- Highest bids match before lower bids
- Lowest asks match before higher asks
-
Time Priority: Same price, earlier orders match first
- Order added first at price executes first
- Implemented using
std::listper price level
Example:
Book State:
Bids: Asks:
105 x 100 103 x 50
105 x 50 104 x 100
104 x 75 105 x 200
New Buy Order at 104 x 150:
- Matches against 103 x 50 (50 shares)
- Matches against 104 x 100 (100 shares)
- Remaining 0 shares
- Removes matched asks
New Bid State:
105 x 100
105 x 50
104 x 75
104 x 150 (new order partially filled)
Common Workflows
Workflow 1: Simple Trade Execution
Orderbook book;
// Someone wants to buy
auto buy = std::make_shared<Order>(OrderType::GoodTillCancel, 1, Side::Buy, 100, 10);
book.AddOrder(buy); // Added to book
// Someone wants to sell at same price
auto sell = std::make_shared<Order>(OrderType::GoodTillCancel, 2, Side::Sell, 100, 10);
auto trades = book.AddOrder(sell); // Executes immediately
// Check results
for (const auto& trade : trades) {
std::cout << "Executed!" << std::endl;
}
Workflow 2: Partial Fill with Order Modification
Orderbook book;
// Buy order for 100
auto buy = std::make_shared<Order>(OrderType::GoodTillCancel, 1, Side::Buy, 100, 100);
book.AddOrder(buy);
// Sell 60 shares
auto sell = std::make_shared<Order>(OrderType::GoodTillCancel, 2, Side::Sell, 100, 60);
book.AddOrder(sell); // Buy order now has 40 qty remaining
// Increase order size and price
OrderModify mod(1, Side::Buy, 105, 150);
book.ModifyOrder(mod); // Cancels old, adds new for 150 @ 105
Error Handling
The system includes error handling for:
-
Invalid Fill Amounts: Orders cannot be filled more than remaining quantity
order->Fill(999); // Throws if 999 > remaining quantity -
Invalid Price Changes: Only market orders can change type
order->ToGoodTillCancel(50); // Throws if not a market order
Conclusion
This orderbook implementation provides:
The system is suitable for:
- Financial exchanges
- Trading platforms
- Market simulation
- Educational purposes
- High-frequency trading components
Future Enhancements
Possible improvements:
- Persistent order storage
- Order book snapshots and history
- Advanced order types (Stop, Iceberg, etc.)
- Multi-asset support
- Performance metrics and monitoring
- Order book visualization
- Backtesting framework integration
License
Author
Sonny Sarkar https://itsmesonny.vercel.app