-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
137 lines (114 loc) · 5.51 KB
/
main.cpp
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <algorithm>
#include <chrono>
#include <iomanip>
#include <iostream>
#include <locale>
#include <random>
#include <sstream>
#include <string>
#include <thread>
#include <vector>
#include "include/orderbook.hpp"
#include "include/types.hpp"
using orderbook::Decimal;
using orderbook::Flag;
using orderbook::MsgType;
using orderbook::OrderBook;
using orderbook::OrderID;
using orderbook::OrderStatus;
using orderbook::Side;
using orderbook::Type;
// Helper function to parse command-line arguments and provide default values.
std::string getCmdOption(char **begin, char **end, const std::string &option, const std::string &default_value = "") {
char **itr = std::find(begin, end, option);
if (itr != end && ++itr != end) {
return *itr;
}
return default_value;
}
bool cmdOptionExists(char **begin, char **end, const std::string &option) { return std::find(begin, end, option) != end; }
std::tuple<orderbook::Decimal, orderbook::Decimal, orderbook::Decimal, orderbook::Decimal> getInitialVars(const orderbook::Decimal &lowerBound,
const orderbook::Decimal &upperBound,
const orderbook::Decimal &minSpread) {
orderbook::Decimal bid = (lowerBound + upperBound) / orderbook::Decimal(2, 0);
orderbook::Decimal ask = bid - minSpread;
orderbook::Decimal bidQty(10, 0);
orderbook::Decimal askQty(10, 0);
return {bid, ask, bidQty, askQty};
}
std::pair<orderbook::Decimal, orderbook::Decimal> getPrice(orderbook::Decimal bid, orderbook::Decimal ask, const orderbook::Decimal &diff, bool dec) {
if (dec) {
bid = bid - diff;
ask = ask - diff;
} else {
bid = bid + diff;
ask = ask + diff;
}
return {bid, ask};
}
void latency(int64_t seed, int duration, int pd, orderbook::Decimal lowerBound, orderbook::Decimal upperBound, orderbook::Decimal minSpread, bool sched) {
std::cout << "Latency function running...\n";
// Implement the latency benchmark logic.
}
void throughput(int64_t seed, int duration, orderbook::Decimal lowerBound, orderbook::Decimal upperBound, orderbook::Decimal minSpread) {
std::cout << "starting throughput benchmark...\n";
// Implement the throughput benchmark logic.
auto n = orderbook::EmptyNotification();
auto ob = std::make_unique<orderbook::OrderBook<orderbook::EmptyNotification>>(n);
orderbook::Decimal bid, ask, bidQty, askQty;
std::tie(bid, ask, bidQty, askQty) = getInitialVars(lowerBound, upperBound, minSpread);
uint64_t tok = 0, buyID = 0, sellID = 0, operations = 0;
auto end = std::chrono::steady_clock::now() + std::chrono::seconds(duration);
std::default_random_engine generator(seed);
std::uniform_int_distribution<int> distribution(0, 9);
auto start = std::chrono::steady_clock::now();
while (std::chrono::steady_clock::now() < end) {
int r = distribution(generator);
bool decrease = r < 5;
std::tie(bid, ask) = getPrice(bid, ask, minSpread, decrease);
if (bid < lowerBound) {
std::tie(bid, ask) = getPrice(bid, ask, minSpread, false);
} else if (ask > upperBound) {
std::tie(bid, ask) = getPrice(bid, ask, minSpread, true);
}
ob->cancelOrder(++tok, buyID);
ob->cancelOrder(++tok, sellID);
buyID = ++tok;
sellID = ++tok;
ob->addOrder(buyID, buyID, Type::Limit, Side::Buy, bidQty, bid, Decimal(0, 0), Flag::None);
ob->addOrder(sellID, sellID, Type::Limit, Side::Sell, askQty, ask, Decimal(0, 0), Flag::None);
operations += 4; // 2 cancels + 2 adds
}
auto finish = std::chrono::steady_clock::now();
std::chrono::duration<double, std::nano> elapsed = finish - start;
double throughput = operations / (elapsed.count() / 1e9);
double nanosecPerOp = elapsed.count() / operations;
std::cout.imbue(std::locale("en_US.UTF-8"));
std::cout << std::fixed << std::setprecision(2);
std::cout << "Total Ops: " << operations << " ops" << std::endl;
std::cout << "Throughput: " << throughput << " ops/sec" << std::endl;
std::cout << "Avg latency: " << nanosecPerOp << " ns/op" << std::endl;
}
void run(int64_t seed, int duration, int pd, const std::string &lb, const std::string &ub, const std::string &ms, const std::string &n, bool sched) {
orderbook::Decimal lowerBound(lb);
orderbook::Decimal upperBound(ub);
orderbook::Decimal minSpread(ms);
if (n == "latency") {
latency(seed, duration, pd, lowerBound, upperBound, minSpread, sched);
} else if (n == "throughput") {
throughput(seed, duration, lowerBound, upperBound, minSpread);
}
}
int main(int argc, char *argv[]) {
int64_t seed = std::stoll(getCmdOption(argv, argv + argc, "-seed", std::to_string(std::chrono::system_clock::now().time_since_epoch().count())));
int duration = std::stoi(getCmdOption(argv, argv + argc, "-duration", "0"));
std::string lb = getCmdOption(argv, argv + argc, "-l", "50.0");
std::string ub = getCmdOption(argv, argv + argc, "-u", "100.0");
std::string ms = getCmdOption(argv, argv + argc, "-m", "0.25");
int pd = std::stoi(getCmdOption(argv, argv + argc, "-p", "10"));
bool sched = cmdOptionExists(argv, argv + argc, "-sched");
std::string n = getCmdOption(argv, argv + argc, "-n", "latency");
std::cout << "PID: " << getpid() << std::endl;
run(seed, duration, pd, lb, ub, ms, n, sched);
return 0;
}