1#pragma once
2#include <map>
3#include <deque>
4#include <cstdint>
5
6namespace trading {
7
8using Price = int64_t; // fixed-point, ticks
9using Quantity = int64_t;
10using OrderId = uint64_t;
11
12enum class Side { Buy, Sell };
13
14struct Order {
15 OrderId id;
16 Side side;
17 Price price;
18 Quantity quantity;
19 uint64_t timestamp;
20};
21
22struct Fill {
23 OrderId taker_id;
24 OrderId maker_id;
25 Price price;
26 Quantity quantity;
27};
28
29class OrderBook {
30 public:
31 explicit OrderBook(Price tick_size) noexcept;
32
33 // Inserts a new resting order into the book.
34 void addOrder(const Order& order);
35
36 // Cancels a resting order by id.
37 bool cancelOrder(OrderId id) noexcept;
38
39 // Matches an incoming order against the book.
40 std::vector<Fill> match(const Order& incoming);
41
42 Price bestBid() const noexcept;
43 Price bestAsk() const noexcept;
44
45 private:
46 Price tick_size_;
47 std::map<Price, std::deque<Order>, std::greater<>> bids_;
48 std::map<Price, std::deque<Order>> asks_;
49};
50
51} // namespace trading
// ---- matching_engine.cpp ----
1#include "matching_engine.hpp"
2#include "risk_manager.hpp"
3
4namespace trading {
5
6MatchingEngine::MatchingEngine(RiskManager& risk)
7 : risk_(risk), book_(/*tick_size=*/1) {}
8
9std::vector<Fill> MatchingEngine::submit(const Order& order) {
10 if (!risk_.checkLimits(order)) {
11 throw std::runtime_error("order rejected: risk limit");
12 }
13
14 auto fills = book_.match(order);
15
16 for (const auto& fill : fills) {
17 risk_.recordFill(fill);
18 onFill(fill);
19 }
20
21 if (order.quantity > 0) {
22 book_.addOrder(order);
23 }
24
25 return fills;
26}
27
28void MatchingEngine::onFill(const Fill& fill) {
29 // update positions and notify subscribers
30 positions_[fill.maker_id] += fill.quantity;
31 positions_[fill.taker_id] -= fill.quantity;
32}
33
34bool MatchingEngine::cancel(OrderId id) noexcept {
35 return book_.cancelOrder(id);
36}
37
38} // namespace trading
1#pragma once
2#include <map>
3#include <deque>
4#include <cstdint>
5
6namespace trading {
7
8using Price = int64_t; // fixed-point, ticks
9using Quantity = int64_t;
10using OrderId = uint64_t;
11
12enum class Side { Buy, Sell };
13
14struct Order {
15 OrderId id;
16 Side side;
17 Price price;
18 Quantity quantity;
19 uint64_t timestamp;
20};
21
22struct Fill {
23 OrderId taker_id;
24 OrderId maker_id;
25 Price price;
26 Quantity quantity;
27};
28
29class OrderBook {
30 public:
31 explicit OrderBook(Price tick_size) noexcept;
32
33 // Inserts a new resting order into the book.
34 void addOrder(const Order& order);
35
36 // Cancels a resting order by id.
37 bool cancelOrder(OrderId id) noexcept;
38
39 // Matches an incoming order against the book.
40 std::vector<Fill> match(const Order& incoming);
41
42 Price bestBid() const noexcept;
43 Price bestAsk() const noexcept;
44
45 private:
46 Price tick_size_;
47 std::map<Price, std::deque<Order>, std::greater<>> bids_;
48 std::map<Price, std::deque<Order>> asks_;
49};
50
51} // namespace trading
// ---- matching_engine.cpp ----
1#include "matching_engine.hpp"
2#include "risk_manager.hpp"
3
4namespace trading {
5
6MatchingEngine::MatchingEngine(RiskManager& risk)
7 : risk_(risk), book_(/*tick_size=*/1) {}
8
9std::vector<Fill> MatchingEngine::submit(const Order& order) {
10 if (!risk_.checkLimits(order)) {
11 throw std::runtime_error("order rejected: risk limit");
12 }
13
14 auto fills = book_.match(order);
15
16 for (const auto& fill : fills) {
17 risk_.recordFill(fill);
18 onFill(fill);
19 }
20
21 if (order.quantity > 0) {
22 book_.addOrder(order);
23 }
24
25 return fills;
26}
27
28void MatchingEngine::onFill(const Fill& fill) {
29 // update positions and notify subscribers
30 positions_[fill.maker_id] += fill.quantity;
31 positions_[fill.taker_id] -= fill.quantity;
32}
33
34bool MatchingEngine::cancel(OrderId id) noexcept {
35 return book_.cancelOrder(id);
36}
37
38} // namespace trading