NOT-OMEGA commited on
Commit
3e567ab
·
verified ·
1 Parent(s): 540ea09

Delete benchmark

Browse files
Files changed (1) hide show
  1. benchmark/bench_matching_engine.cpp +0 -303
benchmark/bench_matching_engine.cpp DELETED
@@ -1,303 +0,0 @@
1
- // benchmark/bench_matching_engine.cpp
2
- // Performance benchmark — measures throughput and latency under load
3
- // Build: cmake --build build --target hft_bench && ./build/hft_bench
4
-
5
- #include "core/order_book.hpp"
6
- #include "core/simulator.hpp"
7
- #include "core/types.hpp"
8
- #include "journal/journal.hpp"
9
- #include <iostream>
10
- #include <vector>
11
- #include <chrono>
12
- #include <random>
13
- #include <algorithm>
14
- #include <iomanip>
15
- #include <cmath>
16
- #include <numeric>
17
-
18
- using namespace hft;
19
- using Clock = std::chrono::high_resolution_clock;
20
-
21
- struct BenchResult {
22
- std::string name;
23
- int64_t ops;
24
- double total_us;
25
- double ops_per_sec;
26
- double p50_ns;
27
- double p99_ns;
28
- double p999_ns;
29
- double avg_ns;
30
- };
31
-
32
- static BenchResult run_bench(const std::string& name, int64_t ops,
33
- std::vector<int64_t>& latencies) {
34
- std::sort(latencies.begin(), latencies.end());
35
- double total_ns = 0;
36
- for (auto l : latencies) total_ns += l;
37
-
38
- BenchResult r;
39
- r.name = name;
40
- r.ops = ops;
41
- r.total_us = total_ns / 1000.0;
42
- r.ops_per_sec = ops / (total_ns / 1e9);
43
- r.avg_ns = total_ns / ops;
44
- r.p50_ns = latencies[latencies.size() * 50 / 100];
45
- r.p99_ns = latencies[latencies.size() * 99 / 100];
46
- r.p999_ns = latencies[latencies.size() * 999 / 1000];
47
- return r;
48
- }
49
-
50
- static void print_result(const BenchResult& r) {
51
- std::cout << std::left << std::setw(35) << r.name
52
- << std::right
53
- << " ops: " << std::setw(8) << r.ops
54
- << " throughput: " << std::setw(10) << std::fixed << std::setprecision(0) << r.ops_per_sec << " ops/s"
55
- << " avg: " << std::setw(8) << std::setprecision(1) << r.avg_ns << " ns"
56
- << " p50: " << std::setw(8) << r.p50_ns << " ns"
57
- << " p99: " << std::setw(8) << r.p99_ns << " ns"
58
- << " p999: " << std::setw(8) << r.p999_ns << " ns"
59
- << "\n";
60
- }
61
-
62
- // ─── Benchmark 1: Order Insert (no match) ───────────────────────────────────
63
-
64
- static BenchResult bench_insert_no_match(int n) {
65
- OrderBook book("BENCH");
66
- std::mt19937 rng(42);
67
- std::uniform_int_distribution<int> price_dist(1000, 2000); // spread out
68
- std::uniform_int_distribution<int> qty_dist(100, 1000);
69
- std::vector<int64_t> latencies;
70
- latencies.reserve(n);
71
-
72
- for (int i = 0; i < n; ++i) {
73
- Order o;
74
- o.id = i + 1;
75
- o.symbol = "BENCH";
76
- o.side = (i % 2 == 0) ? Side::BUY : Side::SELL;
77
- o.type = OrderType::LIMIT;
78
- // Spread prices so no matching occurs (buys low, sells high)
79
- o.price = (o.side == Side::BUY) ? to_price(100.0 + price_dist(rng) * 0.01)
80
- : to_price(200.0 + price_dist(rng) * 0.01);
81
- o.qty = qty_dist(rng);
82
-
83
- auto t0 = Clock::now();
84
- book.add_order(o);
85
- auto t1 = Clock::now();
86
- latencies.push_back(std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count());
87
- }
88
-
89
- return run_bench("Insert (no match)", n, latencies);
90
- }
91
-
92
- // ─── Benchmark 2: Order Match (aggressive orders) ───────────────────────────
93
-
94
- static BenchResult bench_match(int n) {
95
- OrderBook book("BENCH");
96
- std::mt19937 rng(123);
97
- std::uniform_int_distribution<int> qty_dist(50, 200);
98
- std::vector<int64_t> latencies;
99
- latencies.reserve(n);
100
-
101
- // Pre-populate the book with resting orders
102
- for (int i = 0; i < n; ++i) {
103
- Order o;
104
- o.id = i + 1;
105
- o.symbol = "BENCH";
106
- o.side = Side::SELL;
107
- o.type = OrderType::LIMIT;
108
- o.price = to_price(100.0 + (i % 50) * 0.01); // 50 price levels
109
- o.qty = qty_dist(rng);
110
- book.add_order(o);
111
- }
112
-
113
- // Now send aggressive buy orders that match
114
- for (int i = 0; i < n; ++i) {
115
- Order o;
116
- o.id = n + i + 1;
117
- o.symbol = "BENCH";
118
- o.side = Side::BUY;
119
- o.type = OrderType::MARKET;
120
- o.price = 0;
121
- o.qty = 1; // small qty to match single order partially
122
-
123
- auto t0 = Clock::now();
124
- book.add_order(o);
125
- auto t1 = Clock::now();
126
- latencies.push_back(std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count());
127
- }
128
-
129
- return run_bench("Match (market order)", n, latencies);
130
- }
131
-
132
- // ─── Benchmark 3: Cancel Order ──────────────────────────────────────────────
133
-
134
- static BenchResult bench_cancel(int n) {
135
- OrderBook book("BENCH");
136
- std::mt19937 rng(456);
137
- std::uniform_int_distribution<int> price_dist(1, 1000);
138
- std::vector<int64_t> latencies;
139
- latencies.reserve(n);
140
-
141
- // Insert orders
142
- for (int i = 0; i < n; ++i) {
143
- Order o;
144
- o.id = i + 1;
145
- o.symbol = "BENCH";
146
- o.side = Side::BUY;
147
- o.type = OrderType::LIMIT;
148
- o.price = to_price(100.0 + price_dist(rng) * 0.01);
149
- o.qty = 100;
150
- book.add_order(o);
151
- }
152
-
153
- // Cancel in random order
154
- std::vector<int> ids(n);
155
- std::iota(ids.begin(), ids.end(), 1);
156
- std::shuffle(ids.begin(), ids.end(), rng);
157
-
158
- for (int id : ids) {
159
- auto t0 = Clock::now();
160
- book.cancel_order(id);
161
- auto t1 = Clock::now();
162
- latencies.push_back(std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count());
163
- }
164
-
165
- return run_bench("Cancel (random)", n, latencies);
166
- }
167
-
168
- // ─── Benchmark 4: Snapshot ──────────────────────────────────────────────────
169
-
170
- static BenchResult bench_snapshot(int n) {
171
- OrderBook book("BENCH");
172
-
173
- // Build a book with many levels
174
- for (int i = 0; i < 500; ++i) {
175
- Order buy, sell;
176
- buy.id = i * 2 + 1; buy.symbol = "BENCH"; buy.side = Side::BUY;
177
- buy.type = OrderType::LIMIT; buy.price = to_price(100.0 - i * 0.01); buy.qty = 100;
178
-
179
- sell.id = i * 2 + 2; sell.symbol = "BENCH"; sell.side = Side::SELL;
180
- sell.type = OrderType::LIMIT; sell.price = to_price(101.0 + i * 0.01); sell.qty = 100;
181
-
182
- book.add_order(buy);
183
- book.add_order(sell);
184
- }
185
-
186
- std::vector<int64_t> latencies;
187
- latencies.reserve(n);
188
-
189
- for (int i = 0; i < n; ++i) {
190
- auto t0 = Clock::now();
191
- auto snap = book.snapshot(10);
192
- auto t1 = Clock::now();
193
- latencies.push_back(std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count());
194
- (void)snap;
195
- }
196
-
197
- return run_bench("Snapshot (10 levels)", n, latencies);
198
- }
199
-
200
- // ─── Benchmark 5: Full Pipeline (submit_order via ExchangeSimulator) ────────
201
-
202
- static BenchResult bench_full_pipeline(int n) {
203
- RiskLimits limits;
204
- limits.max_order_qty = 100000;
205
- limits.max_position = 10000000;
206
- limits.max_notional_usd = 1e12;
207
- limits.max_orders_per_sec = 1000000;
208
-
209
- ExchangeSimulator sim(limits);
210
- sim.add_symbol("BENCH");
211
-
212
- std::mt19937 rng(789);
213
- std::uniform_int_distribution<int> price_dist(9900, 10100);
214
- std::uniform_int_distribution<int> qty_dist(1, 10);
215
- std::vector<int64_t> latencies;
216
- latencies.reserve(n);
217
-
218
- for (int i = 0; i < n; ++i) {
219
- Order o;
220
- o.id = sim.next_order_id();
221
- o.symbol = "BENCH";
222
- o.side = (i % 2 == 0) ? Side::BUY : Side::SELL;
223
- o.type = OrderType::LIMIT;
224
- o.price = to_price(price_dist(rng) * 0.01); // ~99.00 - 101.00
225
- o.qty = qty_dist(rng);
226
-
227
- auto t0 = Clock::now();
228
- sim.submit_order(o);
229
- auto t1 = Clock::now();
230
- latencies.push_back(std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0).count());
231
- }
232
-
233
- return run_bench("Full pipeline (risk+match)", n, latencies);
234
- }
235
-
236
- // ─── Benchmark 6: Backtest Throughput ────────────────────────────────────────
237
-
238
- static void bench_backtest_throughput() {
239
- std::cout << "\n--- Backtest Throughput ---\n";
240
-
241
- int ticks = 50000;
242
- MarketDataParser::Config cfg;
243
- cfg.symbol = "BENCH"; cfg.start_price = 100.0;
244
- cfg.ticks = ticks; cfg.volatility = 0.001; cfg.seed = 42;
245
- auto tick_data = MarketDataParser::generate_synthetic(cfg);
246
-
247
- RiskLimits rl;
248
- rl.max_order_qty = 10000;
249
- rl.max_position = 1000000;
250
- rl.max_notional_usd = 1e12;
251
- rl.max_orders_per_sec = 100000;
252
-
253
- auto t0 = Clock::now();
254
-
255
- Backtester bt(rl);
256
- bt.add_symbol("BENCH");
257
- bt.set_strategy(std::make_unique<MarketMakingStrategy>(5.0, 100));
258
- auto result = bt.run(tick_data, false);
259
-
260
- auto t1 = Clock::now();
261
- double elapsed_s = std::chrono::duration<double>(t1 - t0).count();
262
- double throughput = ticks / elapsed_s;
263
-
264
- std::cout << " Ticks: " << ticks << "\n";
265
- std::cout << " Elapsed: " << std::fixed << std::setprecision(3) << elapsed_s << " s\n";
266
- std::cout << " Throughput: " << std::setprecision(0) << throughput << " ticks/s\n";
267
- std::cout << " Orders: " << result.orders_submitted << "\n";
268
- std::cout << " Fills: " << result.orders_filled << "\n";
269
- std::cout << " Trades: " << result.trades_count << "\n";
270
- std::cout << " PnL: " << std::setprecision(2) << result.total_pnl << "\n";
271
- }
272
-
273
- // ─── Main ────────────────────────────────────────────────────────────────────
274
-
275
- int main() {
276
- std::cout << "\n";
277
- std::cout << "╔════════════════════════════════════════════════════���══════════════════════════════════════════════════════════════╗\n";
278
- std::cout << "║ Orderflow Replay Engine — Performance Benchmark ║\n";
279
- std::cout << "╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝\n\n";
280
-
281
- const int N = 100000;
282
-
283
- std::vector<BenchResult> results;
284
- results.push_back(bench_insert_no_match(N));
285
- results.push_back(bench_match(N));
286
- results.push_back(bench_cancel(N));
287
- results.push_back(bench_snapshot(N));
288
- results.push_back(bench_full_pipeline(N));
289
-
290
- std::cout << "--- Latency Results (N = " << N << " ops each) ---\n\n";
291
- for (auto& r : results) print_result(r);
292
-
293
- bench_backtest_throughput();
294
-
295
- std::cout << "\n--- Memory ---\n";
296
- std::cout << " sizeof(Order): " << sizeof(Order) << " bytes\n";
297
- std::cout << " sizeof(Trade): " << sizeof(Trade) << " bytes\n";
298
- std::cout << " sizeof(PriceLevel): " << sizeof(PriceLevel) << " bytes\n";
299
- std::cout << " sizeof(MarketDataTick): " << sizeof(MarketDataTick) << " bytes\n";
300
-
301
- std::cout << "\nDone.\n\n";
302
- return 0;
303
- }