File size: 2,387 Bytes
f86fb3b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#pragma once

#include <cstdint>
#include <functional>
#include <memory>
#include <vector>
#include "../core/types.hpp"
#include "../protocol/binary_protocol.hpp"
#include "order_book.hpp"

namespace quant::order_book {

class alignas(core::CACHELINE_SIZE) MatchingEngine {
public:
    using ExecutionCallback = std::function<void(const protocol::ExecutionReportPayload&)>;

    explicit MatchingEngine(core::Symbol symbol, ExecutionCallback on_exec = nullptr);
    ~MatchingEngine() = default;

    MatchingEngine(const MatchingEngine&) = delete;
    MatchingEngine& operator=(const MatchingEngine&) = delete;

    void set_execution_callback(ExecutionCallback cb) noexcept {
        on_exec_ = std::move(cb);
    }

    /**
     * Submit and match a new incoming order.
     */
    void process_new_order(
        core::ClientId client_id,
        core::ClientOrderId client_order_id,
        core::Side side,
        core::OrderType type,
        core::Price price,
        core::Quantity qty,
        core::TimestampNs timestamp_ns
    );

    /**
     * Cancel an existing order by client order ID or engine order ID.
     */
    bool cancel_order(
        core::ClientId client_id,
        core::ClientOrderId client_order_id,
        core::OrderId engine_order_id,
        core::TimestampNs timestamp_ns
    );

    /**
     * Invariant check:
     * - Best bid price must be strictly strictly lower than best ask price (No crossed/locked book).
     */
    [[nodiscard]] bool check_invariants() const noexcept;

    [[nodiscard]] const OrderBook& book() const noexcept { return book_; }
    [[nodiscard]] OrderBook& book() noexcept { return book_; }

    [[nodiscard]] uint64_t total_trades() const noexcept { return total_trades_; }
    [[nodiscard]] uint64_t total_volume() const noexcept { return total_volume_; }

private:
    void emit_report(
        core::ClientId client_id,
        core::ClientOrderId client_order_id,
        core::OrderId engine_order_id,
        core::ExecType exec_type,
        core::Price fill_price,
        core::Quantity fill_qty,
        core::Quantity leaves_qty,
        core::RejectReason reason
    ) noexcept;

    OrderBook book_;
    ExecutionCallback on_exec_;
    core::OrderId next_engine_order_id_{1};
    uint64_t next_exec_id_{1};
    uint64_t total_trades_{0};
    uint64_t total_volume_{0};
};

} // namespace quant::order_book