Slick OrderBook 1.1.0
High-Performance C++23 OrderBook Library
Loading...
Searching...
No Matches
orderbook_l3.hpp
Go to the documentation of this file.
1// Copyright 2026 Slick Quant
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
17#include <memory>
18#include <algorithm>
19#include <vector>
20#include <array>
21#include <tuple>
22#include <functional>
23
25
63public:
65 using Comparator = std::function<bool(Price, Price)>;
67
68 // Default constructor (for array initialization on MSVC)
69 PriceComparator() : compare_(detail::BidComparatorL3{}) {}
70
71 explicit PriceComparator(Side side)
72 : compare_(side == Side::Buy
73 ? Comparator{detail::BidComparatorL3{}}
74 : Comparator{detail::AskComparatorL3{}}
75 )
76 {}
77 bool operator()(Price a, Price b) const noexcept {
78 return compare_(a, b);
79 }
80 };
82
88 explicit OrderBookL3(SymbolId symbol,
89 std::size_t interested_num_levels = 10,
90 std::size_t initial_order_capacity = 1024,
91 std::size_t initial_level_capacity = 32);
92
94 virtual ~OrderBookL3();
95
96 // Non-copyable, movable
97 OrderBookL3(const OrderBookL3&) = delete;
99 OrderBookL3(OrderBookL3&&) noexcept = default;
100 OrderBookL3& operator=(OrderBookL3&&) noexcept = default;
101
103 [[nodiscard]] SymbolId symbol() const noexcept { return symbol_; }
104
118 bool addOrModifyOrder(OrderId order_id, Side side, Price price, Quantity quantity,
119 Timestamp timestamp, uint64_t priority,
120 uint64_t seq_num = 0, bool is_last_in_batch = true);
121
134 bool addOrder(OrderId order_id, Side side, Price price, Quantity quantity,
135 Timestamp timestamp, uint64_t priority = 0, uint64_t seq_num = 0, bool is_last_in_batch = true);
136
150 bool modifyOrder(OrderId order_id, Price new_price, Quantity new_quantity,
151 Timestamp new_timestamp, uint64_t new_priority = 0,
152 uint64_t seq_num = 0, bool is_last_in_batch = true);
153
162 bool deleteOrder(OrderId order_id, Timestamp timestamp, uint64_t seq_num = 0, bool is_last_in_batch = true);
163
173 virtual bool executeOrder(OrderId order_id, Quantity executed_quantity, Timestamp timestamp,
174 uint64_t seq_num = 0, bool is_last_in_batch = true);
175
179 [[nodiscard]] const detail::Order* findOrder(OrderId order_id) const noexcept;
180
184 template<Side SIDE>
185 [[nodiscard]] const detail::PriceLevelL3* getBestLevel() const noexcept;
186
189 [[nodiscard]] const detail::PriceLevelL3* getBestBid() const noexcept;
190
193 [[nodiscard]] const detail::PriceLevelL3* getBestAsk() const noexcept;
194
197 [[nodiscard]] TopOfBook getTopOfBook() const noexcept;
198
203 [[nodiscard]] const PriceLevelMap& getLevelsL3(Side side) const noexcept {
204 SLICK_ASSERT(side < SideCount);
205 return levels_[side];
206 }
207
213 [[nodiscard]] std::vector<detail::PriceLevelL2> getLevelsL2(Side side, std::size_t depth = 0) const;
214
220 [[nodiscard]] std::pair<const detail::PriceLevelL3*, uint16_t> getLevel(Side side, Price price) const noexcept;
221
222 [[nodiscard]] std::pair<detail::PriceLevelL3*, uint16_t> getLevel(Side side, Price price) noexcept;
223
228 [[nodiscard]] const detail::PriceLevelL3* getLevelByIndex(Side side, uint16_t index) const noexcept;
229
233 [[nodiscard]] std::size_t levelCount(Side side) const noexcept;
234
237 [[nodiscard]] std::size_t orderCount() const noexcept { return order_map_.size(); }
238
242 [[nodiscard]] std::size_t orderCount(Side side) const noexcept;
243
247 [[nodiscard]] bool isEmpty(Side side) const noexcept;
248
251 [[nodiscard]] bool isEmpty() const noexcept;
252
258 void clearSide(Side side, Timestamp timestamp = 0);
259
263 void clear(Timestamp timestamp = 0);
264
266 void addObserver(std::shared_ptr<IOrderBookObserver> observer) {
267 observers_.addObserver(std::move(observer));
268 }
269
270 bool removeObserver(const std::shared_ptr<IOrderBookObserver>& observer) {
271 return observers_.removeObserver(observer);
272 }
273
274 void clearObservers() noexcept {
275 observers_.clearObservers();
276 }
277
278 [[nodiscard]] std::size_t observerCount() const noexcept {
279 return observers_.observerCount();
280 }
281
284 [[nodiscard]] uint64_t getLastSeqNum() const noexcept {
285 return last_seq_num_;
286 }
287
292 void emitSnapshot(Timestamp timestamp);
293
294protected:
296 std::tuple<detail::PriceLevelL3*, uint16_t, bool> getOrCreateLevel(Side side, Price price);
297
299 bool removeLevelIfEmpty(Side side, Price price) noexcept;
300
302 void releaseSide(Side side) noexcept;
303
305 void notifyOrderUpdate(const detail::Order* order, Quantity old_quantity, Price old_price,
306 Timestamp timestamp, uint16_t level_index, uint8_t change_flags, uint64_t seq_num) const;
307
309 void notifyOrderDelete(const detail::Order* order, Timestamp timestamp, uint16_t level_index, uint8_t change_flags, uint64_t seq_num) const;
310
312 [[nodiscard]] uint16_t calculateLevelIndex(Side side, Price price) const noexcept;
313
315 void notifyTrade(OrderId passive_order_id, OrderId aggressive_order_id,
316 Side aggressor_side, Price price, Quantity quantity, Timestamp timestamp) const;
317
319 void notifyPriceLevelUpdate(Timestamp timestamp, Side side, Price price, Quantity total_quantity, size_t order_count, uint16_t level_index, uint8_t change_flags, uint64_t seq_num) const;
320
324 void notifyTopOfBookIfChanged(Timestamp timestamp);
325
326protected:
327 SymbolId symbol_; // Symbol identifier
328 std::array<PriceLevelMap, SideCount> levels_; // Price levels per side (indexed by Side enum)
329 detail::OrderMap order_map_; // OrderId -> Order* lookup
330 detail::ObjectPool<detail::Order> order_pool_; // Memory pool for Order objects
331 ObserverManager observers_; // Observer notifications
332 TopOfBook cached_tob_; // Cached top-of-book for efficient change detection
333 uint64_t last_seq_num_; // Last processed sequence number (0 = not tracking)
334 uint16_t change_starting_index_ = INVALID_INDEX; // The lowerest level had changed in a batch. The value reset to INVALID_INDEX after TopOfBook change notified
335 std::size_t interested_num_levels_; // The top N levels to track for observer notifications (0 = all levels)
336};
338
339template<>
340inline const detail::PriceLevelL3* OrderBookL3::getBestLevel<Side::Buy>() const noexcept {
341 return getBestBid();
342}
343
344template<>
345inline const detail::PriceLevelL3* OrderBookL3::getBestLevel<Side::Sell>() const noexcept {
346 return getBestAsk();
347}
348
350
351// Include implementation for header-only mode
352#ifdef SLICK_ORDERBOOK_HEADER_ONLY
354#endif
355
Base interface for orderbook observers Observers receive callbacks for orderbook events.
Definition observer.hpp:20
Observer manager for notifying multiple observers Uses type erasure to support both concept-based and...
Definition observer.hpp:52
Level 3 OrderBook - Individual order tracking with price-time priority.
OrderBookL3(const OrderBookL3 &)=delete
uint64_t getLastSeqNum() const noexcept
Get last processed sequence number.
detail::FlatMap< Price, detail::PriceLevelL3, PriceComparator > PriceLevelMap
std::size_t observerCount() const noexcept
detail::ObjectPool< detail::Order > order_pool_
OrderBookL3(OrderBookL3 &&) noexcept=default
std::array< PriceLevelMap, SideCount > levels_
const detail::PriceLevelL3 * getBestLevel() const noexcept
Get the best price level for a given side.
std::size_t orderCount() const noexcept
Get total number of orders.
bool removeObserver(const std::shared_ptr< IOrderBookObserver > &observer)
OrderBookL3 & operator=(const OrderBookL3 &)=delete
Object pool for zero-allocation management of frequently created/destroyed objects.
Hash table for fast OrderId -> Order* lookup Uses std::unordered_map for simplicity and performance P...
Definition order_map.hpp:16
#define SLICK_NAMESPACE_END
Definition config.hpp:127
#define SLICK_DLL_INTERFACE_WARNINGS_PUSH
Definition config.hpp:47
#define SLICK_CACHE_ALIGNED
Definition config.hpp:123
#define SLICK_NAMESPACE_BEGIN
Definition config.hpp:126
#define SLICK_API
Definition config.hpp:13
#define SLICK_DLL_INTERFACE_WARNINGS_POP
Definition config.hpp:48
#define SLICK_ASSERT(expr)
Definition config.hpp:135
std::map< Key, Value, Compare > FlatMap
Cache-friendly sorted map.
Definition flat_map.hpp:37
int64_t Quantity
Quantity type - volume or size.
Definition types.hpp:21
int64_t Price
Price type - fixed-point representation Example: For 4 decimal places, price = actual_price * 10000 T...
Definition types.hpp:18
uint64_t OrderId
Unique order identifier.
Definition types.hpp:24
Side
Order side - using enum for easy array indexing.
Definition types.hpp:35
constexpr uint16_t INVALID_INDEX
Definition types.hpp:32
uint16_t SymbolId
Symbol identifier - can be hash or sequential ID.
Definition types.hpp:27
uint64_t Timestamp
Timestamp in nanoseconds since epoch.
Definition types.hpp:30
bool operator()(Price a, Price b) const noexcept
std::function< bool(Price, Price)> Comparator
Top-of-book snapshot - best bid and ask.
Definition events.hpp:142
Order structure for Level 3 orderbook Uses intrusive list design for zero-allocation order queues at ...
Definition order.hpp:14
Price level for Level 3 orderbook (order-by-order) Maintains a queue of individual orders at this pri...