1 #ifndef jb_itch5_compute_book_hpp 2 #define jb_itch5_compute_book_hpp 16 #include <boost/functional/hash.hpp> 19 #include <unordered_map> 106 template <
typename book_type>
167 JB_LOG(
trace) <<
" " << msgcnt <<
":" << msgoffset <<
" " << msg;
168 auto insert = orders_.emplace(
169 msg.order_reference_number,
170 order_data{msg.stock, msg.buy_sell_indicator, msg.price, msg.shares});
171 if (insert.second ==
false) {
177 order_data const& data = insert.first->second;
178 JB_LOG(
warning) <<
"duplicate order in handle_message(add_order_message)" 179 <<
", id=" << msg.order_reference_number
180 <<
", location=" << msgcnt <<
":" << msgoffset
181 <<
", existing data=" << data <<
", msg=" << msg;
185 auto itbook = books_.find(msg.stock);
186 if (itbook == books_.end()) {
188 itbook = newbk.first;
190 (void)itbook->second.handle_add_order(
191 msg.buy_sell_indicator, msg.price, msg.shares);
193 msg.header, itbook->second,
194 book_update{recvts, msg.stock, msg.buy_sell_indicator, msg.price,
211 recvts, msgcnt, msgoffset, static_cast<add_order_message const&>(msg));
225 JB_LOG(
trace) <<
" " << msgcnt <<
":" << msgoffset <<
" " << msg;
226 handle_order_reduction(
227 recvts, msgcnt, msgoffset, msg.header, msg.order_reference_number,
228 msg.executed_shares);
244 recvts, msgcnt, msgoffset,
245 static_cast<order_executed_message const&>(msg));
259 JB_LOG(
trace) <<
" " << msgcnt <<
":" << msgoffset <<
" " << msg;
260 handle_order_reduction(
261 recvts, msgcnt, msgoffset, msg.header, msg.order_reference_number,
262 msg.canceled_shares);
276 JB_LOG(
trace) <<
" " << msgcnt <<
":" << msgoffset <<
" " << msg;
277 handle_order_reduction(
278 recvts, msgcnt, msgoffset, msg.header, msg.order_reference_number, 0);
292 JB_LOG(
trace) <<
" " << msgcnt <<
":" << msgoffset <<
" " << msg;
294 auto position = orders_.find(msg.original_order_reference_number);
295 if (position == orders_.end()) {
299 <<
"unknown order in handle_message(order_replace_message)" 300 <<
", id=" << msg.original_order_reference_number
301 <<
", location=" << msgcnt <<
":" << msgoffset <<
", msg=" << msg;
306 auto newpos = orders_.find(msg.new_order_reference_number);
307 if (newpos != orders_.end()) {
309 <<
"handle_message(order_replace_message)" 310 <<
", id=" << msg.new_order_reference_number
311 <<
", location=" << msgcnt <<
":" << msgoffset
316 auto itbook = books_.find(position->second.stock);
321 auto update = do_reduce(
322 position, itbook->second, recvts, msgcnt, msgoffset, msg.header,
323 msg.original_order_reference_number, 0);
326 msg.new_order_reference_number,
327 order_data{update.stock, update.buy_sell_indicator, msg.price,
329 (void)itbook->second.handle_add_order(
330 update.buy_sell_indicator, msg.price, msg.shares);
332 update.cxlreplx =
true;
333 update.oldpx = update.px;
334 update.oldqty = -update.qty;
335 update.px = msg.price;
336 update.qty = msg.shares;
338 callback_(msg.header, itbook->second, update);
357 JB_LOG(
trace) <<
" " << msgcnt <<
":" << msgoffset <<
" " << msg;
368 template <
typename message_type>
379 char msgtype = *
static_cast<char const*
>(msg.
buf());
380 JB_LOG(
error) <<
"Unknown message type '" << msgtype <<
"'(" << int(msgtype)
381 <<
") in msgcnt=" << msg.
count()
382 <<
", msgoffset=" << msg.
offset();
387 std::vector<stock_t> result(books_.size());
389 books_.begin(), books_.end(), result.begin(),
390 [](
auto const& x) {
return x.first; });
396 return std::chrono::steady_clock::now();
402 std::unordered_map<stock_t, order_book<book_type>, boost::hash<stock_t>>;
421 message_header const& header, std::uint64_t order_reference_number,
422 std::uint32_t shares) {
424 auto position = orders_.find(order_reference_number);
425 if (position == orders_.end()) {
429 <<
", id=" << order_reference_number
430 <<
", location=" << msgcnt <<
":" << msgoffset
431 <<
", header=" << header
432 <<
", order_reference_number=" << order_reference_number
433 <<
", shares=" << shares;
437 auto itbook = books_.find(position->second.stock);
442 position, itbook->second, recvts, msgcnt, msgoffset, header,
443 order_reference_number, shares);
444 callback_(header, itbook->second, u);
463 std::uint64_t order_reference_number, std::uint32_t shares) {
464 auto& data = position->second;
465 int qty = shares == 0 ? data.qty :
static_cast<int>(shares);
467 if (data.qty < qty) {
468 JB_LOG(
warning) <<
"trying to execute more shares than are available" 469 <<
", location=" << msgcnt <<
":" << msgoffset
470 <<
", data=" << data <<
", header=" << header
471 <<
", order_reference_number=" << order_reference_number
472 <<
", shares=" << shares;
480 -
static_cast<int>(
qty)};
484 orders_.erase(position);
517 <<
"," << x.
qty <<
"}";
522 <<
"," << x.
qty <<
"}";
528 #endif // jb_itch5_compute_book_hpp void handle_message(time_point recvts, long msgcnt, std::size_t msgoffset, add_order_message const &msg)
Handle a new order message.
callback_type callback_
Store the callback function, this is invoked on each event that changes a book.
std::vector< stock_t > symbols() const
Return the symbols known in the order book.
price4_t px
The price of the order.
bool handle_order_reduced(buy_sell_indicator_t side, price4_t px, int reduced_qty)
Handle an order reduction, which includes executions, cancels and replaces.
Compute the book and call a user-defined callback on each change.
bool operator!=(book_update const &a, book_update const &b)
book_type_config const & cfg_
reference to the order book config
void handle_message(time_point recvts, long msgcnt, std::size_t msgoffset, stock_directory_message const &msg)
Pre-populate the books based on the symbol directory.
std::unordered_map< stock_t, order_book< book_type >, boost::hash< stock_t > > books_by_security
Represent the collection of order books.
void handle_message(time_point recvts, long msgcnt, std::size_t msgoffset, order_replace_message const &msg)
Handle an order replace.
clock_type::time_point time_point
A convenience alias for clock_type::time_point.
Represent an 'Order Executed' message in the ITCH-5.0 protocol.
bool operator==(book_update const &a, book_update const &b)
void handle_message(time_point recvts, long msgcnt, std::size_t msgoffset, order_cancel_message const &msg)
Handle a partial cancel.
void handle_order_reduction(time_point recvts, long msgcnt, std::size_t msgoffset, message_header const &header, std::uint64_t order_reference_number, std::uint32_t shares)
Refactor code to handle order reductions, i.e., cancels and executions.
void handle_message(time_point recvts, long msgcnt, std::size_t msgoffset, order_executed_price_message const &msg)
Handle an order execution with a different price than the order's.
A convenient container for per-order data.
orders_by_id orders_
The live orders indexed by the "order reference number".
void handle_message(time_point, long, std::size_t, message_type const &)
Ignore all other message types.
jb::itch5::time_point time_point
time_point is used as a compute_book<book_type> type in some modules
compute_book(callback_type const &cb, book_type_config const &cfg)
Represent an 'Order Delete' message in the ITCH-5.0 protocol.
void handle_message(time_point recvts, long msgcnt, std::size_t msgoffset, order_executed_message const &msg)
Handle an order execution.
Represent an 'Order Executed with Price' message in the ITCH-5.0 protocol.
typename book_type::config book_type_config
config type is used to construct the order_book
typename orders_by_id::iterator orders_iterator
Represent an 'Add Order with MPID' message in the ITCH-5.0 protocol.
std::chrono::steady_clock clock_type
A convenience alias for clock_type.
int oldqty
How many shares were removed in the old order.
stock_t stock
The symbol for this particular order.
bool cxlreplx
If true, this was a cancel replace and and old order was modified too...
std::function< void(message_header const &header, order_book< book_type > const &updated_book, book_update const &update)> callback_type
Define the callback type.
void handle_message(time_point recvts, long msgcnt, std::size_t msgoffset, add_order_mpid_message const &msg)
Handle a new order with MPID.
std::unordered_map< std::uint64_t, order_data > orders_by_id
Represent the collection of all orders.
#define JB_ASSERT_THROW(PRED)
compute_book(callback_type &&cb, book_type_config const &cfg)
Constructor.
time_point now() const
Return the current timestamp for delay measurements.
buy_sell_indicator_t buy_sell_indicator
What side of the book is being updated.
void handle_unknown(time_point recvts, unknown_message const &msg)
Log any unknown message types.
stock_t stock
The security updated by this order.
A flat struct to represent updates to an order book.
std::ostream & operator<<(std::ostream &os, add_order_message const &x)
Streaming operator for jb::itch5::add_order_message.
int qty
The remaining quantity in the order.
void handle_message(time_point recvts, long msgcnt, std::size_t msgoffset, order_delete_message const &msg)
Handle a full cancel.
Represent an 'Order Replace' message in the ITCH-5.0 protocol.
price4_t oldpx
Old price for the order.
book_update do_reduce(orders_iterator position, order_book< book_type > &book, time_point recvts, long msgcnt, std::size_t msgoffset, message_header const &header, std::uint64_t order_reference_number, std::uint32_t shares)
Refactor code common to handle_order_reduction() and handle_message(order_replace_message).
jb::itch5::clock_type clock_type
clock_type is used as a compute_book<book_type> type in some modules
int qty
How many shares are being added (if positive) or removed (if negative) from the book.
time_point recvts
When was the message that triggered this update received.
Maintain the ITCH-5.0 order book for a single security.
buy_sell_indicator_t buy_sell_indicator
Whether the order is a BUY or SELL.
books_by_security books_
The order books indexed by security.
Represent a 'Stock Directory' message in the ITCH-5.0 protocol.
Represent an 'Add Order' message in the ITCH-5.0 protocol.
price4_t px
What price level is being updated.
The top-level namespace for the JayBeams library.
std::uint32_t count() const
std::uint64_t offset() const
Represent an 'Order Cancel' message in the ITCH-5.0 protocol.