1 #ifndef jb_itch5_array_based_order_book_hpp 2 #define jb_itch5_array_based_order_book_hpp 52 if (qty > 0 and px >=
price4_t(0) and
53 px < max_price_field_value<price4_t>()) {
73 std::string
const& msg, std::size_t tk_begin_top, std::size_t tk_inside,
77 template <
typename compare_t>
102 void validate()
const override;
127 template <
typename compare_t>
135 , tk_inside_(tk_empty_quote)
136 , tk_begin_top_(tk_inside_)
137 , tk_end_top_(tk_inside_) {
143 if (tk_inside_ == tk_empty_quote) {
147 auto px_inside = level_to_price<price4_t>(tk_inside_);
148 return half_quote(px_inside, top_levels_.at(rel_px));
156 if (tk_inside_ == tk_empty_quote) {
159 if (not bottom_levels_.empty()) {
161 auto i = bottom_levels_.rbegin();
162 auto px_worst = level_to_price<price4_t>(i->first);
166 auto rel_worst = relative_worst_top_level();
169 auto px_worst = level_to_price<price4_t>(tk_worst);
170 return half_quote(px_worst, top_levels_.at(rel_worst));
176 return bottom_levels_.size() + top_levels_count();
199 auto emp_tup = bottom_levels_.emplace(tk_px, 0);
200 emp_tup.first->second += qty;
210 move_top_to_bottom(std::get<0>(limits));
212 tk_begin_top_ = std::get<0>(limits);
213 tk_end_top_ = std::get<1>(limits);
216 if (tk_inside_ != tk_px) {
222 top_levels_[rel_px] += qty;
228 top_levels_[rel_px] += qty;
255 auto price_it = bottom_levels_.find(tk_px);
256 if (price_it == bottom_levels_.end()) {
258 "array_based_book_side::reduce_order." 259 " Trying to reduce non-existing bottom_levels_price.",
260 tk_begin_top_, tk_inside_, px, 0, qty);
263 price_it->second -= qty;
264 if (price_it->second < 0) {
270 if (price_it->second <= 0) {
271 bottom_levels_.erase(price_it);
279 "array_based_book_side::reduce_order." 280 " Trying to reduce a non-existing top_levels_ price" 281 " (better px_inside).",
282 tk_begin_top_, tk_inside_, px, 0, qty);
286 if (top_levels_[rel_px] == 0) {
288 "array_based_book_side::reduce_order." 289 " Trying to reduce a non-existing top_levels_ price" 290 " (top_levels_[rel_px] == 0).",
291 tk_begin_top_, tk_inside_, px, 0, qty);
295 top_levels_[rel_px] -= qty;
296 if (top_levels_[rel_px] < 0) {
300 top_levels_[rel_px] = 0;
303 if (tk_px != tk_inside_) {
307 if (top_levels_[rel_px] == 0) {
309 tk_inside_ = next_best_price_level();
310 if (tk_inside_ == tk_empty_quote) {
313 if (not bottom_levels_.empty()) {
314 tk_inside_ = bottom_levels_.begin()->first;
319 tk_begin_top_ = std::get<0>(limits);
320 tk_end_top_ = std::get<1>(limits);
322 move_bottom_to_top();
361 return std::distance(
363 std::find_if(top_levels_.begin(), top_levels_.end(), [](
auto x) {
371 if (tk_inside_ == tk_empty_quote) {
376 for (std::size_t i = 0; i != rel_px + 1; ++i) {
377 if (top_levels_[i] != 0) {
402 move_top_to_bottom_ranged(rel_inside + 1);
408 move_top_to_bottom_ranged(rel_tk_max);
415 for (std::size_t i = rel_tk_max; i <= rel_tk_inside; ++i, ++j) {
416 if (top_levels_[i] != 0) {
417 top_levels_[j] = top_levels_[i];
434 for (std::size_t i = 0; i != N; ++i) {
435 auto qty = top_levels_[i];
451 bottom_levels_.emplace_hint(bottom_levels_.begin(), tk_i, qty);
456 std::fill(top_levels_.begin(), top_levels_.begin() + N, 0);
465 if (bottom_levels_.empty()) {
469 auto le = bottom_levels_.begin();
470 for (; le != bottom_levels_.end(); ++le) {
471 auto tk_le = le->first;
475 top_levels_[rel_px] = le->second;
482 bottom_levels_.erase(bottom_levels_.begin(), le);
493 if (rel_inside == 0) {
494 return tk_empty_quote;
498 if (top_levels_[rel_inside] != 0) {
502 }
while (rel_inside != 0);
503 return tk_empty_quote;
509 static auto get_limits(std::size_t
const tk_px, std::size_t
const rel) {
510 if (tk_px == tk_empty_quote) {
511 return std::make_pair(tk_empty_quote, tk_empty_quote);
515 auto tk_low = tk_px <= rel ? 0 : tk_px - rel;
516 auto tk_low_base = tk_low + rel >= level_max ? level_max : tk_low + rel;
518 tk_low_base + rel >= level_max ? level_max : tk_low_base + rel;
519 auto tk_high_base = tk_high <= rel ? 0 : tk_high - rel;
521 if (tk_low_base != tk_high_base) {
522 tk_low = tk_high_base <= rel ? 0 : tk_high_base - rel;
524 return std::make_pair(tk_low, tk_high);
529 template <
typename ordering,
class DUMMY =
void>
531 static bool constexpr ascending =
false;
544 static bool better_level(std::size_t
const tk1, std::size_t
const tk2) {
551 auto lim = get_limits(tk_px, rel);
552 return std::make_pair(std::get<1>(lim), std::get<0>(lim));
566 return tk_ini - tk_px;
571 template <
class DUMMY>
572 struct side<
std::greater<std::size_t>, DUMMY> {
573 static bool constexpr ascending =
true;
586 static bool better_level(std::size_t
const tk1, std::size_t
const tk2) {
593 return get_limits(tk_px, rel);
607 return tk_px - tk_ini;
631 template <
typename compare_t>
638 #endif // jb_itch5_array_based_order_book_hpp array_based_book_side(array_based_order_book::config const &cfg)
Constructor, initialize a book side from its configuration.
static bool better_level(std::size_t const tk1, std::size_t const tk2)
static std::size_t const tk_empty_quote
Cache the number of levels for the empty quote.
std::map< std::size_t, int, compare_t > bottom_levels_
the worst (tail) price level and quantity
half_quote empty_bid()
The value used to represent an empty bid.
void raise_invalid_reduce(std::string const &msg, std::size_t tk_begin_top, std::size_t tk_inside, price4_t px, int book_qty, int qty)
Raise an exception describing a invalid reduce operation.
Base class for all configuration objects.
static std::size_t price_levels_empty_quote()
Return the number of price levels for the empty quote.
bool is_ascending() const
Testing hook.
static auto empty_quote_price()
void move_top_to_bottom_ranged(std::size_t N)
Move the bottom N levels from the top vector to the bottom map.
Define the types of buy and sell side classes.
std::size_t tk_begin_top_
worst price level on the top_levels_ range
static auto relative_to_level(std::size_t const tk_ini, std::size_t const rel)
returns@ price level rel positions greater than tk_ini.
static auto relative_to_level(std::size_t const tk_ini, std::size_t const rel)
returns@ price level rel positions less than tk_ini
void move_bottom_to_top()
Move relative prices from best price to tk_begin_top* (included) out of bottom_levels_ to top_levels_...
static bool better_level(std::size_t const tk1, std::size_t const tk2)
std::size_t max_size_
top_levels_ max size
static auto level_to_relative(std::size_t const tk_ini, std::size_t const tk_px)
Represent one side of the book.
void validate_operation_params(char const *operation, int qty, price4_t px)
Validate the input parameters for all array_order_book operations.
static auto limit_top_prices(std::size_t const tk_px, std::size_t const rel)
void raise_invalid_operation_parameters(char const *operation, int qty, price4_t px)
Raise the right exception when we detect invalid parameters for add_order() or reduce_order() ...
std::pair< price4_t, int > half_quote
A simple representation for price + quantity.
static auto level_to_relative(std::size_t const tk_ini, std::size_t const tk_px)
#define config_object_constructors(NAME)
Helper class to easily define configuration attributes.
static auto empty_quote_price()
jb::config_attribute< config, int > max_size
Configure an array_based_order_book config object.
#define JB_ASSERT_THROW(PRED)
price4_t empty_offer_price()
convenient value to represent an empty offer limit price
bool reduce_order(price4_t px, int qty)
Reduce the quantity for a given price.
std::size_t next_best_price_level() const
static half_quote empty_quote()
static auto limit_top_prices(std::size_t const tk_px, std::size_t const rel)
std::size_t tk_end_top_
one price level past-the-best price in top_levels_ range
half_quote empty_offer()
The value used to represent an empty offer.
template specialization struct to handle differences between BUY and SELL version SELL side...
half_quote best_quote() const
static half_quote empty_quote()
bool add_order(price4_t px, int qty)
Add a price and quantity to the side order book.
std::vector< int > top_levels_
the best relative prices and quantity
std::size_t tk_inside_
price level the inside
price4_t empty_bid_price()
convenient value to represent an empty bid limit price
std::size_t price_levels(price_field_t lo, price_field_t hi)
Compute the number of price levels between two prices.
std::size_t top_levels_count() const
price_field< std::uint32_t, 10000 > price4_t
Convenience definition for Price(4) fields.
static auto get_limits(std::size_t const tk_px, std::size_t const rel)
void move_top_to_bottom(std::size_t const tk_max)
Move prices from tk_begin_top_ to tk_max (excluded) out of top_levels_ to bottom_levels_.
half_quote worst_quote() const
std::size_t count() const
The top-level namespace for the JayBeams library.
std::size_t relative_worst_top_level() const