Skip to content
Daniel Esambu
Work
Work
Projects
Things I've built
Leka
A C++20 matching engine
Latency Lab
(opens in a new tab)
A C++ course I wrote
Resume
The formal version
Writing
Writing
Poetry
Poems, shelved by what they're about
Essays
Notes and essays
Math
Math
Notes
Notes I've written up
IB papers
Worked exam questions
Calculus lessons
(opens in a new tab)
On YouTube
Life
Life
Photos
Things I stopped to look at
Training
Reps, not phases
Modeling
Measurements and photos
Resume
Say hi
Say hi
Resume
Menu
Leka
A low-latency C++20 price-time-priority limit order book and matching engine
Replay viewer
Toggle main menu visibility
Loading...
Searching...
No Matches
matching_engine.hpp
1
#ifndef MATCHING_ENGINE_HPP
2
#define MATCHING_ENGINE_HPP
3
4
#include "lob/book/order_book.hpp"
5
#include "lob/matching/execution.hpp"
6
#include "lob/matching/sequence_number_generator.hpp"
7
#include "
lob/order/order_event.hpp
"
8
9
#include <vector>
10
11
namespace
lob {
12
13
/**
14
* @brief Matches incoming orders against resting liquidity in an OrderBook.
15
*
16
* The engine owns matching decisions while OrderBook owns resting order
17
* storage and index consistency. Market orders are processed here rather
18
* than inserted into the resting book.
19
*/
20
class
MatchingEngine
{
21
public
:
22
/** Creates an engine that operates on the supplied book. */
23
explicit
MatchingEngine
(
OrderBook
& orderBook);
24
MatchingEngine
(
const
MatchingEngine
&) =
delete
;
25
MatchingEngine
& operator=(
const
MatchingEngine
&) =
delete
;
26
27
/**
28
* @brief Processes an incoming order and returns generated executions.
29
*
30
* The engine repeatedly examines the best opposing price level and its
31
* FIFO head. Limit orders cross only at prices permitted by their limit;
32
* market orders cross any available opposing liquidity. Each execution is
33
* priced from the resting order, preserving price-time priority.
34
*
35
* A remaining limit quantity is added to the book with its original
36
* submitted quantity preserved. Fully executed orders and unfilled market
37
* remainders are not stored in the book.
38
*
39
* @param orderId Unique identifier for the incoming order.
40
* @param price Limit price. Ignored for market orders.
41
* @param quantity Original quantity submitted by the caller.
42
* @param timestamp Timestamp assigned to the incoming order.
43
* @param orderSide Whether the order buys or sells.
44
* @param orderType Whether the order is a limit or market order.
45
* @return Executions in the order they occurred.
46
* @throws std::invalid_argument if an input value is invalid.
47
* @throws std::logic_error if the order ID is already present.
48
* @throws std::overflow_error if sequence numbers are exhausted.
49
*
50
* @details This convenience form returns a fresh vector on every call,
51
* so it allocates on the first execution just as returning any
52
* non-empty vector by value would. It exists for tests, tools, and
53
* call sites that do not run repeatedly on a latency-sensitive path.
54
* A caller in that position should use the buffer-taking overload
55
* below instead, reusing one vector across calls.
56
*/
57
std::vector<Execution>
processOrder
(
58
OrderId
orderId,
59
Price
price,
60
Quantity
quantity,
61
Timestamp
timestamp,
62
OrderSide orderSide,
63
OrderType orderType);
64
65
/**
66
* @brief Same as above, but appends into a caller-owned buffer.
67
*
68
* @c out is cleared before matching begins, then filled in the order
69
* executions occurred. Its capacity is otherwise left alone: a caller
70
* that reuses the same vector across many calls pays for at most one
71
* allocation, ever, once that vector's capacity has grown to cover
72
* the largest execution burst seen so far. This is the form to use on
73
* a repeatedly-called, latency-sensitive path.
74
*
75
* @return The number of executions appended, equal to @c out.size().
76
*/
77
std::size_t
processOrder
(
78
OrderId
orderId,
79
Price
price,
80
Quantity
quantity,
81
Timestamp
timestamp,
82
OrderSide orderSide,
83
OrderType orderType,
84
std::vector<Execution>& out);
85
86
/**
87
* @brief Dispatches an event before interpreting its payload.
88
*
89
* NEW is the only event that can execute, so it is also the only event
90
* that consumes a sequence number. CANCEL and REDUCE return no
91
* executions and cannot cross the book, because neither can move an
92
* order to a price on the opposite side. A reprice is submitted as
93
* CANCEL followed by NEW, which routes it through the matcher and so
94
* cannot leave the book crossed.
95
*
96
* @details See processOrder() above for the same allocation tradeoff:
97
* this by-value form is a convenience wrapper, not the hot-path API.
98
*/
99
std::vector<Execution>
processEvent
(
const
OrderEvent
& event);
100
/** @brief Event-oriented alias for processEvent(). */
101
std::vector<Execution>
processOrder
(
const
OrderEvent
& event);
102
103
/**
104
* @brief Buffer-taking form of processEvent(); see processOrder() above.
105
* @return The number of executions appended, equal to @c out.size().
106
*/
107
std::size_t
processEvent
(
const
OrderEvent
& event, std::vector<Execution>& out);
108
109
private
:
110
OrderBook
& orderBook;
111
SequenceNumberGenerator
sequenceNumberGenerator;
112
113
/**
114
* @brief The matching loop shared by every entry point above.
115
*
116
* Appends to @c out without clearing it first, so the two public
117
* overloads control clearing and this stays a single source of truth
118
* for the matching algorithm regardless of which entry point is used.
119
*/
120
void
matchOrder(
121
OrderId
orderId,
122
Price
price,
123
Quantity
quantity,
124
Timestamp
timestamp,
125
OrderSide orderSide,
126
OrderType orderType,
127
std::vector<Execution>& out);
128
};
129
130
}
// namespace lob
131
132
#endif
// MATCHING_ENGINE_HPP
lob::MatchingEngine::MatchingEngine
MatchingEngine(OrderBook &orderBook)
Creates an engine that operates on the supplied book.
Definition
matching_engine.cpp:14
lob::MatchingEngine::processOrder
std::vector< Execution > processOrder(OrderId orderId, Price price, Quantity quantity, Timestamp timestamp, OrderSide orderSide, OrderType orderType)
Processes an incoming order and returns generated executions.
Definition
matching_engine.cpp:61
lob::MatchingEngine::processEvent
std::vector< Execution > processEvent(const OrderEvent &event)
Dispatches an event before interpreting its payload.
Definition
matching_engine.cpp:18
lob::OrderBook
Owns resting limit orders and maintains their book indexes.
Definition
order_book.hpp:29
lob::OrderEvent
Type-safe event-first command for the matching engine.
Definition
order_event.hpp:77
lob::OrderId
Type-safe identifier for an order; zero is reserved as invalid.
Definition
order_id.hpp:10
lob::Price
Type-safe nonzero price value used for price ordering.
Definition
price.hpp:9
lob::Quantity
Type-safe unsigned order quantity; zero represents a filled state.
Definition
quantity.hpp:8
lob::SequenceNumberGenerator
Generates process-wide monotonic sequence numbers.
Definition
sequence_number_generator.hpp:14
lob::Timestamp
Nanoseconds since the Unix epoch; zero is reserved as invalid.
Definition
timestamp.hpp:10
order_event.hpp
Defines event-first order command payloads and dispatch types.
include
lob
matching
matching_engine.hpp
Generated by
1.18.0