Joel Grunbaum
2022-01-07 127d5af6f934b162c98a40ce414b98415d899cea
commit | author | age
bb2353 1 #include "book.hpp"
JG 2 #include <chrono>
127d5a 3 #include <cstddef>
bb2353 4 #include <iostream>
JG 5
6 Order::Order(double price, OrderSideEnum side, int volume,
7              std::chrono::nanoseconds timestamp, std::string id)
8     : price{price}, side{side}, remaining_volume{volume},
9       filled_volume(0), timestamp{timestamp}, id{id} {}
10
11 Level::Level(Order &order)
12     : price{order.price}, volume(order.remaining_volume), side{order.side},
13       timestamp{order.timestamp}, id{order.id} {}
14
15 bool operator<(const Level &a, const Level &b) {
16   if (a.price < b.price)
17     return true;
127d5a 18   else if (a.price == b.price && (a.timestamp.count() > b.timestamp.count()))
bb2353 19     return true;
JG 20   else
21     return false;
22 }
23
24 bool operator>(const Level &a, const Level &b) {
25   if (a.price > b.price)
26     return true;
127d5a 27   else if (a.price == b.price && (a.timestamp.count() > b.timestamp.count()))
bb2353 28     return true;
JG 29   else
30     return false;
31 }
32
33 bool operator<=(const Level &a, const Level &b) {
34   if (a.price <= b.price)
35     return true;
127d5a 36   else if (a.price == b.price && (a.timestamp.count() >= b.timestamp.count()))
bb2353 37     return true;
JG 38   else
39     return false;
40 }
41
42 bool operator>=(const Level &a, const Level &b) {
43   if (a.price >= b.price)
44     return true;
127d5a 45   else if (a.price == b.price && (a.timestamp.count() >= b.timestamp.count()))
bb2353 46     return true;
JG 47   else
48     return false;
49 }
50
51 bool operator==(const Level &a, const Level &b) {
127d5a 52     if (a.price == b.price && (a.timestamp.count() == b.timestamp.count()))
bb2353 53     return true;
JG 54   else
55     return false;
127d5a 56 }
JG 57
58 std::ostream& operator<<(std::ostream& out, const Level& a)
59 {
60     return out << "Price: " << a.price << ", volume: " << a.volume << ", time: " << a.timestamp.count() << ", id: " << a.id;
61 }
62
63 template<class T>
64 void Side<T>::deleteLevel(std::string orderId)
65 {
66     for (auto i = this->c.begin(); i != this->c.end();) {
67         if (*i.id == orderId) {
68             this->c.erase(i);
69             std::make_heap(this->c.begin(), this->c.end(), this->comp);
70         }
71     }
72 }
73
74 template<class T>
75 void Side<T>::topRemoveVolume(int volume) { this->c[0].volume -= volume; }
76
77 template<class T>
78 void Side<T>::printTop(std::size_t num)
79 {
80     std::vector<Level> copy(this->c);
81     std::sort(copy.begin(), copy.end(), this->comp);
82     if (copy.size() && copy[0].side == Buy)
83         std::reverse(copy.begin(), copy.end());
84     for (std::size_t i = 0; i < copy.size() &&  i < num; i++) {
85         std::cout << copy[i] << std::endl;
86     }
bb2353 87 }
JG 88
89 Book::Book()
90     : bidSide(), askSide(), productType(TEST), product("a"), stationId("b"),
91       unit("c"), expiry(std::chrono::nanoseconds(0)), aggFee(1), pasFee(-1),
92       broFee(2) {}
93
94 Book::Book(ProductTypeEnum productType, std::string product,
95            std::string stationId, std::string unit,
96            std::chrono::nanoseconds expiry, double aggFee, double pasFee,
97            double broFee)
98     : bidSide{}, askSide{}, productType{productType}, product(product),
99       stationId(stationId), unit(unit), expiry(expiry), aggFee(aggFee),
100       pasFee(pasFee), broFee(broFee) {}
101
102 void Book::ask(Order &order) {
127d5a 103   while (this->bidSide.size() && this->bidSide.top().price >= order.price) {
bb2353 104     if (this->bidSide.top().volume > order.remaining_volume) {
JG 105       int temp = this->bidSide.top().volume;
106       order.filled_volume += temp;
107       this->bidSide.topRemoveVolume(order.remaining_volume);
108       order.remaining_volume -= temp;
127d5a 109       break;
bb2353 110     } else {
JG 111       order.remaining_volume -= this->bidSide.top().volume;
112       order.filled_volume += this->bidSide.top().volume;
113       this->bidSide.pop();
114     }
127d5a 115   }
JG 116   if (order.remaining_volume > 0) {
117     this->askSide.emplace(order);
bb2353 118   }
JG 119 }
120
121 void Book::bid(Order &order) {
127d5a 122   while (this->askSide.size() && this->askSide.top().price <= order.price) {
bb2353 123     if (this->askSide.top().volume > order.remaining_volume) {
JG 124       int temp = this->askSide.top().volume;
125       order.filled_volume += temp;
126       this->askSide.topRemoveVolume(order.remaining_volume);
127       order.remaining_volume -= temp;
127d5a 128       break;
bb2353 129     } else {
JG 130       order.remaining_volume -= this->askSide.top().volume;
131       order.filled_volume += this->askSide.top().volume;
132       this->askSide.pop();
133     }
127d5a 134   }
JG 135   if (order.remaining_volume > 0) {
136     this->bidSide.emplace(order);
bb2353 137   }
JG 138 }
139
127d5a 140 void Book::printBook(std::size_t numOrders) {
JG 141   std::cout << "Sell side: " << this->askSide.size() << std::endl;
142   this->askSide.printTop(numOrders);
143   std::cout << "Buy side: " << this->bidSide.size() << std::endl;
144   this->bidSide.printTop(numOrders);
bb2353 145 }
JG 146
147 Book testBook(int orders, bool printBook) {
148   Book b = Book();
149   std::chrono::nanoseconds time(1);
127d5a 150   for (int i = 1; i < orders; i++) {
bb2353 151     Order t(i, Buy, 10, time++, "a");
JG 152     b.bid(t);
153   }
154   for (int i = orders + 1; i < 2 * orders; i++) {
155     Order t(i, Sell, 10, time++, "b");
156     b.ask(t);
157   }
158   if (printBook)
127d5a 159     b.printBook(orders - 1);
bb2353 160   return b;
JG 161 }