15 total_shares += order->shares;
16 orders.push_back(order);
25 if (!book_messages.contains(msg.message_type)) {
28 this->handle_message(msg);
35 constexpr std::string_view BORDER =
"==========================================\n";
36 constexpr std::string_view MID_RULE =
"-----------+--------------+--------------\n";
39 out <<
" SHARES | PRICE | SIDE \n";
42 const auto print_level =
43 [&](std::uint32_t total_shares, std::uint32_t raw_price, std::string_view
side) {
45 std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
48 "{:>10} | {:>12.4f} | {}\n", total_shares,
make_price(raw_price).to_double(),
side
57 for (
const auto& [raw_price, level] : std::ranges::reverse_view(m_asks)) {
58 print_level(level.total_shares, raw_price,
"Ask");
64 for (
const auto& [raw_price, level] : m_bids) {
65 print_level(level.total_shares, raw_price,
"Bid");
71auto LimitOrderBook::handle_message(
const AddOrderMessage& msg) ->
void {
72 if (
to_string(msg.stock,
sizeof(msg.stock)) != m_stock_symbol) {
76 msg.order_reference_number,
77 msg.buy_sell_indicator,
84auto LimitOrderBook::handle_message(
const AddOrderMPIDAttributionMessage& msg) ->
void {
85 if (
to_string(msg.stock,
sizeof(msg.stock)) != m_stock_symbol) {
89 msg.order_reference_number,
90 msg.buy_sell_indicator,
97auto LimitOrderBook::handle_message(
const OrderExecutedMessage& msg) ->
void {
98 auto order_iter = m_orders.find(msg.order_reference_number);
99 if (order_iter == m_orders.end() || (*order_iter->second)->stock != m_stock_symbol) {
102 remove_order(msg.order_reference_number, msg.executed_shares);
105auto LimitOrderBook::handle_message(
const OrderExecutedWithPriceMessage& msg) ->
void {
106 auto order_iter = m_orders.find(msg.order_reference_number);
107 if (order_iter == m_orders.end() || (*order_iter->second)->stock != m_stock_symbol) {
110 remove_order(msg.order_reference_number, msg.executed_shares);
113auto LimitOrderBook::handle_message(
const OrderCancelMessage& msg) ->
void {
114 auto order_iter = m_orders.find(msg.order_reference_number);
115 if (order_iter == m_orders.end() || (*order_iter->second)->stock != m_stock_symbol) {
118 remove_order(msg.order_reference_number, msg.cancelled_shares);
121auto LimitOrderBook::handle_message(
const OrderDeleteMessage& msg) ->
void {
122 auto iter = m_orders.find(msg.order_reference_number);
123 if (iter != m_orders.end() && (*iter->second)->stock == m_stock_symbol) {
124 auto order = *iter->second;
125 remove_order(msg.order_reference_number, order->shares);
129auto LimitOrderBook::handle_message(
const OrderReplaceMessage& msg) ->
void {
130 auto iter = m_orders.find(msg.original_order_reference_number);
131 if (iter != m_orders.end() && (*iter->second)->stock == m_stock_symbol) {
132 auto old_order = *iter->second;
133 char side = old_order->buy_sell_indicator;
134 const std::string& stock = old_order->stock;
135 remove_order(msg.original_order_reference_number, old_order->shares);
136 add_order(msg.new_order_reference_number,
side, msg.shares, msg.price, stock);
140auto LimitOrderBook::add_order(
141 uint64_t order_ref,
char side, uint32_t
shares, uint32_t
price,
const std::string& stock
143 auto order = std::make_shared<Order>(order_ref,
side,
shares,
price, stock);
145 PriceLevel* level =
nullptr;
148 level = &m_bids[
price];
150 level = &m_asks[
price];
152 order->level = level;
153 level->add_order(order);
154 m_orders[order_ref] = std::prev(level->orders.end());
157auto LimitOrderBook::remove_order(uint64_t order_ref, uint32_t canceled_shares) ->
void {
158 auto iter = m_orders.find(order_ref);
159 if (iter == m_orders.end()) {
163 auto order_iterator = iter->second;
166 auto order_ptr = *order_iterator;
167 PriceLevel* level = order_ptr->level;
169 level->total_shares -= canceled_shares;
170 order_ptr->shares -= canceled_shares;
172 if (order_ptr->shares == 0) {
173 level->remove_order(order_iterator);
174 if (level->orders.empty()) {
175 if (order_ptr->buy_sell_indicator ==
'B') {
176 m_bids.erase(order_ptr->price);
178 m_asks.erase(order_ptr->price);
181 m_orders.erase(iter);
auto print(std::ostream &out, unsigned int delay_ms=0) const -> void
Visualizes the current state of the order book to an output stream.
auto process(const Message &message) -> void
Dispatches and processes a generic ITCH message.
std::list< std::shared_ptr< Order > >::iterator OrderIt
Iterator type for navigating the list of orders within a price level.
std::variant< SystemEventMessage, StockDirectoryMessage, StockTradingActionMessage, RegSHOMessage, MarketParticipantPositionMessage, MWCBDeclineLevelMessage, MWCBStatusMessage, IPOQuotingPeriodUpdateMessage, LULDAuctionCollarMessage, OperationalHaltMessage, AddOrderMessage, AddOrderMPIDAttributionMessage, OrderExecutedMessage, OrderExecutedWithPriceMessage, OrderCancelMessage, OrderDeleteMessage, OrderReplaceMessage, NonCrossTradeMessage, CrossTradeMessage, BrokenTradeMessage, NOIIMessage, RetailPriceImprovementIndicatorMessage, DLCRMessage > Message
A variant able to hold any one of the ITCH 5.0 message structs.
constexpr auto make_price(std::uint32_t raw_value) noexcept -> StandardPrice
Wraps a raw 4-decimal price value in the typed StandardPrice.
auto to_string(const char *source, size_t size) -> std::string
Converts a fixed-width character array to a string, trimming trailing spaces and NUL characters.
An in-memory limit order book reconstructed from a stream of parsed ITCH 5.0 messages.
Strongly typed, fixed-point price representation for ITCH price fields.
Add Order, No MPID Attribution (A): a new displayable order has been accepted and placed on the book.
auto add_order(const std::shared_ptr< Order > &order) -> void
Appends an order to the end of the queue (Time priority).
auto remove_order(const OrderIt &order_it) -> void
Removes a specific order from the queue.