Untitled
unknown
plain_text
9 months ago
4.7 kB
12
Indexable
#include "ankerl.hpp"
#include <algorithm>
#include <cstdint>
#include <functional>
#include <iterator>
#include <print>
#include <vector>
void TERMINATE(std::string_view msg) // gereksiz
{
std::println("Error: {}", msg);
std::terminate();
}
struct Order {
std::size_t qty;
int32_t price;
bool is_implied;
};
struct Level {
std::size_t quantity;
int32_t price;
uint32_t implied_count;
};
using ItchOrderIdType = std::size_t;
template <typename Comparator>
class SideBook {
ankerl::unordered_dense::map<ItchOrderIdType, Order> orders_;
std::vector<Level> levels_;
public:
void add_order(ItchOrderIdType id, int32_t price, std::size_t qty, bool implied = false)
{
if (not orders_.contains(id)) [[likely]] { // gereksiz
orders_.emplace(id, Order{ qty, price, implied });
const auto it = std::ranges::find_if(
levels_.rbegin(), levels_.crend(),
[&price](const auto& level_price) noexcept {
return Comparator{}(level_price, price);
},
&Level::price);
if (it != levels_.crend() and it->price == price) {
auto& lvl = *it;
lvl.quantity += qty;
if (implied)
lvl.implied_count += 1;
}
else {
levels_.insert(it.base(), Level{ qty, price, implied ? 1u : 0u });
}
}
else { // gereksiz
TERMINATE("Duplicate ID");
}
}
void delete_order(ItchOrderIdType id)
{
if (auto found = orders_.find(id); found != orders_.end()) { // gereksiz
const auto& ord = found->second;
// UNSAFE FIND
const auto it = std::ranges::find(levels_.rbegin(), std::unreachable_sentinel, ord.price, &Level::price);
auto& lvl = *it;
if (ord.is_implied && lvl.implied_count)
lvl.implied_count -= 1;
if (lvl.quantity == 0 && lvl.implied_count == 0)
levels_.erase(it.base());
orders_.erase(found);
}
else { // gereksiz
TERMINATE("Unknown ID");
}
}
void execute_order(ItchOrderIdType id, std::size_t exec_qty)
{
auto found = orders_.find(id);
if (found == orders_.cend()) // gereksiz
TERMINATE("Unknown ID");
auto& ord = found->second;
auto found_level = std::ranges::find_if(levels_.rbegin(), levels_.crend(), [&](const auto& lvl) noexcept {
return lvl.price == ord.price;
});
if (found_level->quantity < exec_qty) [[unlikely]]
TERMINATE("qty too large");
if (ord.qty < exec_qty) [[unlikely]]
TERMINATE("order qty underflow");
found_level->quantity -= exec_qty;
ord.qty -= exec_qty;
// Implied counteri ancak emir tamamen fill oldugunda azalt
const bool fully_executed = (ord.qty == 0uz);
if (ord.is_implied && fully_executed && found_level->implied_count > 0uz)
found_level->implied_count -= 1;
// Level boşaldıysa sil
if (found_level->quantity == 0uz && found_level->implied_count == 0uz)
levels_.erase(found_level.base());
// Emir tamamen fill olunca map’ten sil
if (fully_executed)
orders_.erase(found);
}
std::optional<Level> best_level() const
{
if (levels_.empty()) [[unlikely]]
return std::nullopt;
return levels_.back();
}
};
class Orderbook {
enum class Side : uint8_t {
Buy,
Sell
};
SideBook<std::ranges::greater_equal> ask_book_; // descending, best = back()
SideBook<std::ranges::less_equal> bid_book_; // ascending, best = back()
public:
void add_order(ItchOrderIdType id, Side side, int32_t price, std::size_t qty, bool implied = false)
{
if (side == Side::Buy)
bid_book_.add_order(id, price, qty);
else
ask_book_.add_order(id, price, qty);
}
void delete_order(ItchOrderIdType id, Side side)
{
if (side == Side::Buy)
bid_book_.delete_order(id);
else
ask_book_.delete_order(id);
}
void execute_order(ItchOrderIdType id, Side side, std::size_t exec_qty)
{
if (side == Side::Buy)
bid_book_.execute_order(id, exec_qty);
else
ask_book_.execute_order(id, exec_qty);
}
};Editor is loading...
Leave a Comment