Program Listing for File OrderBook.hpp

Return to documentation for file (engine/include/OrderBook.hpp)

#pragma once

#include <cstdint>
#include <vector>
#include <ankerl/unordered_dense.h>

#include "Types.hpp"


class OrderBookView;

class OrderBook {
  friend class OrderBookView;
private:
  uint64_t current_tick = 0;
  static constexpr size_t MAX_ORDERS = 100'000;
  static constexpr size_t MAX_LEVELS = 100'000;

  using LevelsVec = std::vector<std::pair<trading::Price, trading::Level*>>;

  // order data is stored contiguous in memory
  std::vector<trading::Order> orders_;
  int32_t next_free_order_;
  ankerl::unordered_dense::map<trading::OrderId, uint32_t> oid_to_idx_;

  // level data is stored in a contiguous pool for pointer stability across insertions
  std::vector<trading::Level> level_pool_;
  int32_t next_free_level_;

  // bid_levels: sorted decreasing, ask_levels: sorted increasing
  LevelsVec bid_levels_;
  LevelsVec ask_levels_;

  // live (non-zero vol) levels linked via Level::prev_level / next_level.
  int32_t bid_head_level_ = -1;
  int32_t ask_head_level_ = -1;

  // count of live (non-zero vol) levels on each side
  int32_t bid_level_count_ = 0;
  int32_t ask_level_count_ = 0;

  trading::Level* alloc_level(trading::Price price, trading::Volume vol);

  void link_level(LevelsVec& levels, LevelsVec::iterator it, int32_t& head_level);
  void unlink_level(trading::Level& lvl, int32_t& head_level);

  void add_order(trading::OrderId orderId, trading::Side side, trading::Price price, trading::Volume volume);
  void modify_order(trading::OrderId orderId, trading::Side side, trading::Price price, trading::Volume volume);
  void cancel_order(trading::OrderId orderId, trading::Volume cancel_vol);
  void clear();

public:
  trading::TimeStamp last_ts = 0;
  trading::Action last_action = trading::Action::None;
  trading::Price last_trade_price = 0;
  trading::Volume last_trade_size = 0;
  trading::Side last_trade_side = trading::Side::None;

  OrderBook();

  void process_event(const trading::Event &e);
};