|
Leka
A low-latency C++20 price-time-priority limit order book and matching engine
|
Matches incoming orders against resting liquidity in an OrderBook. More...
#include <matching_engine.hpp>
Public Member Functions | |
| MatchingEngine (OrderBook &orderBook) | |
| Creates an engine that operates on the supplied book. | |
| MatchingEngine (const MatchingEngine &)=delete | |
| MatchingEngine & | operator= (const MatchingEngine &)=delete |
| std::vector< Execution > | processOrder (OrderId orderId, Price price, Quantity quantity, Timestamp timestamp, OrderSide orderSide, OrderType orderType) |
| Processes an incoming order and returns generated executions. | |
| std::size_t | processOrder (OrderId orderId, Price price, Quantity quantity, Timestamp timestamp, OrderSide orderSide, OrderType orderType, std::vector< Execution > &out) |
| Same as above, but appends into a caller-owned buffer. | |
| std::vector< Execution > | processEvent (const OrderEvent &event) |
| Dispatches an event before interpreting its payload. | |
| std::vector< Execution > | processOrder (const OrderEvent &event) |
| Event-oriented alias for processEvent(). | |
| std::size_t | processEvent (const OrderEvent &event, std::vector< Execution > &out) |
| Buffer-taking form of processEvent(); see processOrder() above. | |
Matches incoming orders against resting liquidity in an OrderBook.
The engine owns matching decisions while OrderBook owns resting order storage and index consistency. Market orders are processed here rather than inserted into the resting book.
Definition at line 20 of file matching_engine.hpp.
|
explicit |
Creates an engine that operates on the supplied book.
Definition at line 14 of file matching_engine.cpp.
| std::vector< Execution > lob::MatchingEngine::processOrder | ( | OrderId | orderId, |
| Price | price, | ||
| Quantity | quantity, | ||
| Timestamp | timestamp, | ||
| OrderSide | orderSide, | ||
| OrderType | orderType ) |
Processes an incoming order and returns generated executions.
Convenience wrapper: identical allocation behavior to the pre-buffer API.
The engine repeatedly examines the best opposing price level and its FIFO head. Limit orders cross only at prices permitted by their limit; market orders cross any available opposing liquidity. Each execution is priced from the resting order, preserving price-time priority.
A remaining limit quantity is added to the book with its original submitted quantity preserved. Fully executed orders and unfilled market remainders are not stored in the book.
| orderId | Unique identifier for the incoming order. |
| price | Limit price. Ignored for market orders. |
| quantity | Original quantity submitted by the caller. |
| timestamp | Timestamp assigned to the incoming order. |
| orderSide | Whether the order buys or sells. |
| orderType | Whether the order is a limit or market order. |
| std::invalid_argument | if an input value is invalid. |
| std::logic_error | if the order ID is already present. |
| std::overflow_error | if sequence numbers are exhausted. |
This convenience form returns a fresh vector on every call, so it allocates on the first execution just as returning any non-empty vector by value would. It exists for tests, tools, and call sites that do not run repeatedly on a latency-sensitive path. A caller in that position should use the buffer-taking overload below instead, reusing one vector across calls.
Definition at line 61 of file matching_engine.cpp.
References processOrder().
Referenced by processOrder().
| std::size_t lob::MatchingEngine::processOrder | ( | OrderId | orderId, |
| Price | price, | ||
| Quantity | quantity, | ||
| Timestamp | timestamp, | ||
| OrderSide | orderSide, | ||
| OrderType | orderType, | ||
| std::vector< Execution > & | out ) |
Same as above, but appends into a caller-owned buffer.
out is cleared before matching begins, then filled in the order executions occurred. Its capacity is otherwise left alone: a caller that reuses the same vector across many calls pays for at most one allocation, ever, once that vector's capacity has grown to cover the largest execution burst seen so far. This is the form to use on a repeatedly-called, latency-sensitive path.
out.size(). Definition at line 69 of file matching_engine.cpp.
| std::vector< Execution > lob::MatchingEngine::processEvent | ( | const OrderEvent & | event | ) |
Dispatches an event before interpreting its payload.
Convenience wrapper: identical allocation behavior to the pre-buffer API.
NEW is the only event that can execute, so it is also the only event that consumes a sequence number. CANCEL and REDUCE return no executions and cannot cross the book, because neither can move an order to a price on the opposite side. A reprice is submitted as CANCEL followed by NEW, which routes it through the matcher and so cannot leave the book crossed.
See processOrder() above for the same allocation tradeoff: this by-value form is a convenience wrapper, not the hot-path API.
Definition at line 18 of file matching_engine.cpp.
References processEvent().
Referenced by processEvent(), and processOrder().
| std::vector< Execution > lob::MatchingEngine::processOrder | ( | const OrderEvent & | event | ) |
Event-oriented alias for processEvent().
Forwards the event-oriented overload to processEvent().
Definition at line 56 of file matching_engine.cpp.
References processEvent().
| std::size_t lob::MatchingEngine::processEvent | ( | const OrderEvent & | event, |
| std::vector< Execution > & | out ) |
Buffer-taking form of processEvent(); see processOrder() above.
Dispatches by event type so only the active payload is interpreted.
out.size(). Definition at line 25 of file matching_engine.cpp.
References lob::OrderEvent::getCancelOrder(), lob::OrderEvent::getEventType(), lob::OrderId::isValid(), lob::ReduceOrder::newQuantity, lob::CancelOrder::orderId, lob::NewOrder::orderId, lob::ReduceOrder::orderId, lob::NewOrder::orderSide, lob::NewOrder::orderType, lob::NewOrder::price, lob::NewOrder::quantity, and lob::NewOrder::timestamp.