File size: 3,567 Bytes
8f4d2d0
 
 
 
 
 
 
 
 
 
 
 
 
 
44cddac
8f4d2d0
44cddac
8f4d2d0
 
 
 
 
 
5759f0b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8f4d2d0
 
 
 
 
 
 
 
 
5759f0b
 
8f4d2d0
 
5759f0b
8f4d2d0
 
5759f0b
8f4d2d0
 
 
 
 
5759f0b
 
8f4d2d0
 
 
 
 
 
 
 
 
5759f0b
 
 
8f4d2d0
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#pragma once
#include "common/Types.hpp"
#include <vector>
#include <map>
#include <unordered_map>
#include <functional>

namespace eunex {

// ── Trade callback type ────────────────────────────────────────────
using TradeCallback = std::function<void(const Trade&)>;
using ExecCallback  = std::function<void(const ExecutionReport&)>;

// ── Price-Time Priority Order Book ─────────────────────────────────
class Book {
public:
    explicit Book(SymbolIndex_t symbolIdx);

    void newOrder(Order& order, const TradeCallback& onTrade, const ExecCallback& onExec);
    bool cancelOrder(OrderId_t orderId, ExecutionReport& report);
    bool modifyOrder(OrderId_t orderId, Price_t newPrice, Quantity_t newQty,
                     ExecutionReport& report);

    // ── Trading phase ─────────────────────────────────────────────
    void setPhase(TradingPhase phase);
    TradingPhase getPhase() const { return phase_; }

    // Indicative Opening Price β€” computed during PreOpen
    Price_t getIOP() const;

    // Transition PreOpen β†’ Continuous: run uncrossing at IOP
    void uncross(const TradeCallback& onTrade, const ExecCallback& onExec);

    // ── Stop orders ───────────────────────────────────────────────
    void triggerStopOrders(Price_t tradePrice, const TradeCallback& onTrade,
                           const ExecCallback& onExec);
    bool cancelStopOrder(OrderId_t orderId, ExecutionReport& report);

    // ── Queries ────────────────────────────────────────────────────
    struct Level {
        Price_t    price;
        Quantity_t totalQty;
        int        orderCount;
    };

    std::vector<Level> getBids(int depth = 10) const;
    std::vector<Level> getAsks(int depth = 10) const;
    Price_t bestBid() const;
    Price_t bestAsk() const;
    size_t bidCount() const;
    size_t askCount() const;
    size_t stopOrderCount() const { return stopOrders_.size(); }

    SymbolIndex_t symbolIndex() const { return symbolIdx_; }
    Price_t lastTradePrice() const { return lastTradePrice_; }

private:
    SymbolIndex_t symbolIdx_;
    TradeId_t     nextTradeId_ = 1;
    OrderId_t     nextOrderId_ = 1;
    Price_t       lastTradePrice_ = 0;
    TradingPhase  phase_ = TradingPhase::CTS;

    using BidMap = std::map<Price_t, std::vector<Order>, std::greater<Price_t>>;
    using AskMap = std::map<Price_t, std::vector<Order>, std::less<Price_t>>;

    BidMap bids_;
    AskMap asks_;

    std::unordered_map<OrderId_t, std::pair<Side, Price_t>> orderIndex_;

    // Stop orders waiting to be triggered
    std::vector<Order> stopOrders_;

    OrderId_t allocateOrderId() { return nextOrderId_++; }
    TradeId_t allocateTradeId() { return nextTradeId_++; }

    void matchBuy(Order& incoming, const TradeCallback& onTrade, const ExecCallback& onExec);
    void matchSell(Order& incoming, const TradeCallback& onTrade, const ExecCallback& onExec);
    void insertResting(Order& order);
    void removeOrder(OrderId_t orderId, Side side, Price_t price);

    template<typename MapT>
    std::vector<Level> getLevels(const MapT& map, int depth) const;
};

} // namespace eunex