Untitled

 avatar
unknown
plain_text
8 months ago
4.7 kB
10
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