Joel Grunbaum
2022-01-13 d2cfd3eeeb8b6af3b7ccda01e6c1ac581a2df398
commit | author | age
16b655 1 #include "json.hpp"
JG 2 #include "book.hpp"
3 #include "date/include/date/date.h"
4 #include "protocol.hpp"
b4cf0a 5 #include "rapidjson/include/rapidjson/document.h"
JG 6 #include "rapidjson/include/rapidjson/rapidjson.h"
16b655 7 #include <chrono>
JG 8 #include <cstddef>
9 #include <cstdint>
10 #include <cstring>
11 #include <deque>
12 #include <iomanip>
13 #include <netdb.h>
14 #include <numeric>
15 #include <queue>
16 #include <sstream>
17 #include <string>
18 #include <unordered_map>
19 #include <utility>
20
21 namespace json
22 {
23 static std::unordered_map<std::string, MessageTypes> mapTypes;
24 static std::unordered_map<MessageTypes, book::ProductTypeEnum> mapAnnounce;
25 static std::unordered_map<std::string, book::OrderSideEnum> mapOrder;
26 static std::unordered_map<std::string, TradeTypeEnum> mapTrade;
27 static std::unordered_map<book::OrderSideEnum, std::string> mapOrderSide;
28
29 void initialise()
30 {
2c515f 31     mapTypes = {{"FUTURE", FUTURE_TYPE},
JG 32                 {"SPREAD", SPREAD_TYPE},
33                 {"CALL", CALL_TYPE},
34                 {"PUT", PUT_TYPE},
35                 {"SETTLEMENT", SETTLEMENT},
36                 {"ADDED", ADDED},
37                 {"DELETED", DELETED},
38                 {"TRADE", TRADE},
39                 {"BROKER_REQUEST", BROKER_REQUEST},
40                 {"BROKER_ACK", BROKER_ACK},
41                 {"BROKER_CONFIRM", BROKER_CONFIRM}};
16b655 42
2c515f 43     mapAnnounce = {{FUTURE_TYPE, book::FUTURE},
JG 44                    {SPREAD_TYPE, book::SPREAD},
45                    {CALL_TYPE, book::CALL},
46                    {PUT_TYPE, book::PUT}};
16b655 47
2c515f 48     mapOrder = {{"BUY", book::Buy}, {"SELL", book::Sell}};
16b655 49
2c515f 50     mapTrade = {{"BUY_AGGRESSOR", BUY_AGGRESSOR},
4fdb65 51                 {"SELL_AGGRESSOR", SELL_AGGRESSOR},
e8c910 52                 {"BROKER_TRADE", BROKER_TRADE}};
16b655 53
2c515f 54     mapOrderSide = {{book::Buy, "BUY"}, {book::Sell, "SELL"}};
16b655 55 }
JG 56
b4cf0a 57 Message* parseSingle(rapidjson::Value& d);
JG 58 AnnounceMessage* announce(rapidjson::Value& d);
59 SettleMessage* settle(rapidjson::Value& d);
60 AddedMessage* added(rapidjson::Value& d);
61 DeletedMessage* deleted(rapidjson::Value& d);
6bdd28 62 RejectMessage* reject(rapidjson::Value& d);
b4cf0a 63 TradeMessage* trade(rapidjson::Value& d);
JG 64 BrokerRequest* brokerReq(rapidjson::Value& d);
65 BrokerAck* brokerAck(rapidjson::Value& d);
66 BrokerConfirm* brokerCon(rapidjson::Value& d);
6bdd28 67 ErrorMessage* error(rapidjson::Value& d);
16b655 68
d2cfd3 69 std::chrono::seconds parseTime(std::string& s);
JG 70
b4cf0a 71 std::queue<Message*> parse(std::string& str)
16b655 72 {
2c515f 73     std::queue<Message*> out;
JG 74     rapidjson::Document d;
75     d.Parse(str.c_str());
76     if (d.IsArray()) {
77         for (rapidjson::SizeType i = 0; i < d.Size(); i++) {
78             out.push(parseSingle(d[i]));
79         }
80     } else {
81         out.push(parseSingle(d));
b4cf0a 82     }
2c515f 83     return out;
16b655 84 }
JG 85
b4cf0a 86 Message* parseSingle(rapidjson::Value& d)
16b655 87 {
2c515f 88     if (mapTypes.empty()) {
JG 89         initialise();
90     }
6bdd28 91     if (d.HasMember("error")) return error(d);
2c515f 92     Message* out;
JG 93     switch (mapTypes[d["type"].GetString()]) {
94     case FUTURE_TYPE:
95     case SPREAD_TYPE:
96     case CALL_TYPE:
97     case PUT_TYPE:
98         out = announce(d);
99         break;
100     case SETTLEMENT:
101         out = settle(d);
102         break;
103     case ADDED:
104         out = added(d);
105         break;
106     case DELETED:
107         out = deleted(d);
6bdd28 108         break;
JG 109     case REJECT:
110         out = reject(d);
2c515f 111         break;
JG 112     case TRADE:
113         out = trade(d);
114         break;
115     case BROKER_REQUEST:
116         out = brokerReq(d);
117         break;
118     case BROKER_ACK:
119         out = brokerAck(d);
120         break;
121     case BROKER_CONFIRM:
122         out = brokerCon(d);
123         break;
124     default:
125         out = new Message(NONE, "");
126         break;
127     }
128     return out;
16b655 129 }
JG 130
d2cfd3 131 std::chrono::seconds parseTime(std::string& s)
JG 132 {
133     return std::chrono::hours{std::stoi(s.substr(0, 4)) * 24 * 30 * 12} +
134            std::chrono::hours{std::stoi(s.substr(5, 2)) * 24 * 30} +
135            std::chrono::hours{std::stoi(s.substr(8, 2)) * 24} +
136            std::chrono::hours{std::stoi(s.substr(11, 2))} +
137            std::chrono::minutes{std::stoi(s.substr(14, 2))} +
138            std::chrono::hours{std::stoi(s.substr(16, 5))};
139 }
140
b4cf0a 141 AnnounceMessage* announce(rapidjson::Value& d)
16b655 142 {
d2cfd3 143     std::string es = d["expiry"].GetString();
2c515f 144     std::chrono::nanoseconds exp_time(0);
d2cfd3 145     exp_time = parseTime(es);
2c515f 146     return new AnnounceMessage(
JG 147         mapTypes[d["type"].GetString()], d["product"].GetString(),
148         d["stationId"].GetInt(), d["stationName"].GetString(),
149         d["unit"].GetString(), exp_time, d["aggressiveFee"].GetDouble(),
150         d["passiveFee"].GetDouble(), d["brokerFee"].GetDouble(),
151         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 152 }
JG 153
b4cf0a 154 SettleMessage* settle(rapidjson::Value& d)
16b655 155 {
2c515f 156     std::chrono::nanoseconds exp_time(0);
d2cfd3 157     std::string es = d["expiry"].GetString();
JG 158     exp_time = parseTime(es);
2c515f 159     return new SettleMessage(
JG 160         mapTypes[d["type"].GetString()], d["product"].GetString(),
161         d["stationName"].GetString(), exp_time, d["price"].GetDouble(),
162         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 163 }
JG 164
b4cf0a 165 AddedMessage* added(rapidjson::Value& d)
16b655 166 {
2c515f 167     return new AddedMessage(
JG 168         mapTypes[d["type"].GetString()], d["product"].GetString(),
169         d["id"].GetString(), mapOrder[d["side"].GetString()],
170         d["price"].GetDouble(), d["filled"].GetInt(), d["resting"].GetInt(),
171         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 172 }
JG 173
b4cf0a 174 DeletedMessage* deleted(rapidjson::Value& d)
16b655 175 {
2c515f 176     return new DeletedMessage(
JG 177         mapTypes[d["type"].GetString()], d["product"].GetString(),
178         d["id"].GetString(), mapOrder[d["side"].GetString()],
179         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 180 }
JG 181
6bdd28 182 RejectMessage* reject(rapidjson::Value& d)
JG 183 {
184     return new RejectMessage(mapTypes[d["type"].GetString()], "",
185                              d["error"].GetString(), uint64_t(0), double(0));
186 }
187
b4cf0a 188 TradeMessage* trade(rapidjson::Value& d)
16b655 189 {
2c515f 190     return new TradeMessage(
JG 191         mapTypes[d["type"].GetString()], d["product"].GetString(),
192         d["price"].GetDouble(), d["volume"].GetInt(), d["buyer"].GetString(),
193         d["seller"].GetString(), mapTrade[d["tradeType"].GetString()],
194         d["passiveOrder"].GetString(), d["passiveOrderRemaining"].GetInt(),
195         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 196 }
JG 197
b4cf0a 198 BrokerRequest* brokerReq(rapidjson::Value& d)
16b655 199 {
2c515f 200     return new BrokerRequest(
JG 201         mapTypes[d["type"].GetString()], d["product"].GetString(),
202         d["price"].GetDouble(), mapOrder[d["side"].GetString()],
203         d["volume"].GetInt(), d["counterparty"].GetString());
16b655 204 }
JG 205
b4cf0a 206 BrokerAck* brokerAck(rapidjson::Value& d)
16b655 207 {
2c515f 208     return new BrokerAck(mapTypes[d["type"].GetString()],
JG 209                          d["product"].GetString(), d["price"].GetDouble(),
210                          mapOrder[d["side"].GetString()], d["volume"].GetInt(),
211                          d["counterparty"].GetString(), d["id"].GetString(),
212                          d["brokerTradeStatus"].GetString(),
213                          d["owner"].GetString());
16b655 214 }
b4cf0a 215 BrokerConfirm* brokerCon(rapidjson::Value& d)
16b655 216 {
2c515f 217     return new BrokerConfirm(
JG 218         mapTypes[d["type"].GetString()], d["product"].GetString(),
219         d["price"].GetDouble(), mapOrder[d["side"].GetString()],
220         d["volume"].GetInt(), d["counterparty"].GetString(),
221         d["id"].GetString());
16b655 222 }
JG 223
6bdd28 224 ErrorMessage* error(rapidjson::Value& d)
JG 225 {
226     return new ErrorMessage(d["error"].GetString());
227 }
228
16b655 229 Message::Message() : type(NONE), product("error") {}
JG 230
231 Message::Message(MessageTypes types, std::string product)
2c515f 232     : type(types), product(product)
16b655 233 {
6bdd28 234 }
JG 235
236 ErrorMessage::ErrorMessage(std::string message)
237     : Message(ERROR, ""), message(message)
238 {
239 }
240 std::string ErrorMessage::as_string()
241 {
242     return "{\"error\": \"" + this->message + "\"}";
16b655 243 }
JG 244
245 FromExchange::FromExchange(MessageTypes type, std::string product,
246                            uint64_t sequence, double timestamp)
2c515f 247     : Message(type, product), sequence(sequence), timestamp(timestamp)
16b655 248 {
JG 249 }
250
251 ToExchange::ToExchange(MessageTypes type, std::string product)
2c515f 252     : Message(type, product){};
16b655 253
JG 254 Broker::Broker(MessageTypes type, std::string product, double price,
255                book::OrderSideEnum side, uint64_t volume,
256                std::string counterparty)
2c515f 257     : Message(type, product), price(price), side(side), volume(volume),
JG 258       counterparty(counterparty)
16b655 259 {
JG 260 }
261
262 AnnounceMessage::AnnounceMessage(MessageTypes type, std::string product,
b4cf0a 263                                  int stationId, std::string stationName,
16b655 264                                  std::string unit,
JG 265                                  std::chrono::nanoseconds expiry, double aggFee,
266                                  double pasFee, double broFee,
267                                  uint64_t sequence, double timestamp)
2c515f 268     : FromExchange(type, product, sequence, timestamp), stationId(stationId),
JG 269       stationName(stationName), unit(unit), expiry(expiry), aggFee(aggFee),
270       pasFee(pasFee), broFee(broFee)
16b655 271 {
JG 272 }
273
274 SettleMessage::SettleMessage(MessageTypes type, std::string product,
275                              std::string stationName,
276                              std::chrono::nanoseconds expiry, double price,
277                              uint64_t sequence, double timestamp)
2c515f 278     : FromExchange(type, product, sequence, timestamp),
JG 279       stationName(stationName), expiry(expiry), price(price)
16b655 280 {
JG 281 }
282
283 AddMessage::AddMessage(MessageTypes type, std::string product, double price,
284                        book::OrderSideEnum side, uint64_t volume)
2c515f 285     : ToExchange(type, product), price(price), side(side), volume(volume)
16b655 286 {
JG 287 }
288
289 std::string AddMessage::as_string()
290 {
2c515f 291     if (mapOrderSide.empty()) initialise();
JG 292     return "{\"type\": \"ADD\", \"product\": \"" + this->product +
d2cfd3 293            "\", \"price\": " + std::to_string(this->price) + ", \"side\": \"" +
JG 294            mapOrderSide[this->side] +
295            "\", \"volume\": " + std::to_string(this->volume) + "}";
16b655 296 }
JG 297
298 AddedMessage::AddedMessage(MessageTypes type, std::string product,
299                            std::string id, book::OrderSideEnum side,
300                            double price, uint64_t filled, uint64_t resting,
301                            uint64_t sequence, double timestamp)
2c515f 302     : FromExchange(type, product, sequence, timestamp), id(id), side(side),
JG 303       price(price), filled(filled), resting(resting)
16b655 304 {
JG 305 }
306
6bdd28 307 std::string AddedMessage::as_string()
JG 308 {
309     return "{\"type\": \"ADDED\", \"product\": \"" + this->product +
d2cfd3 310            "\", \"product\": \"" + this->id + "\" \"side\": \"" +
JG 311            mapOrderSide[this->side] +
312            "\", \"price\": " + std::to_string(this->price) +
313            "\"filled\": " + std::to_string(this->filled) +
314            ", \"resting\": " + std::to_string(this->resting) +
315            ", \"sequence\": " + std::to_string(this->sequence) +
316            ", \"timestamp\":" + std::to_string(this->timestamp) + "}";
6bdd28 317 }
JG 318
16b655 319 DeleteMessage::DeleteMessage(MessageTypes type, std::string product,
JG 320                              std::string id)
2c515f 321     : ToExchange(type, product), id(id)
16b655 322 {
JG 323 }
324
325 std::string DeleteMessage::as_string()
326 {
2c515f 327     if (mapOrderSide.empty()) initialise();
JG 328     return "{\"type\": \"DELETE\", \"product\": \"" + this->product +
d2cfd3 329            "\", \"id\": \"" + this->id + "\"}";
16b655 330 }
JG 331
332 DeletedMessage::DeletedMessage(MessageTypes type, std::string product,
333                                std::string id, book::OrderSideEnum side,
334                                uint64_t sequence, double timestamp)
2c515f 335     : FromExchange(type, product, sequence, timestamp), id(id), side(side)
16b655 336 {
JG 337 }
338
6bdd28 339 std::string DeletedMessage::as_string()
JG 340 {
341     return "{\"type\": \"DELETED\", \"product\": \"" + this->product +
d2cfd3 342            "\", \"product\": \"" + this->id + "\" \"side\": \"" +
JG 343            mapOrderSide[this->side] +
344            ", \"sequence\": " + std::to_string(this->sequence) +
345            ", \"timestamp\":" + std::to_string(this->timestamp) + "}";
6bdd28 346 }
JG 347
16b655 348 RejectMessage::RejectMessage(MessageTypes type, std::string product,
JG 349                              std::string error, uint64_t sequence,
350                              double timestamp)
2c515f 351     : FromExchange(type, product, sequence, timestamp), error(error)
16b655 352 {
JG 353 }
354
6bdd28 355 std::string RejectMessage::as_string()
JG 356 {
357     return "{\"type\": \"REJECT\", \"product\": \"" + this->product =
d2cfd3 358                "\", \"error\": \"" + this->error +
JG 359                "\", \"sequence\": " + std::to_string(this->sequence) +
360                ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
6bdd28 361 }
JG 362
16b655 363 TradeMessage::TradeMessage(MessageTypes type, std::string product, double price,
JG 364                            uint64_t volume, std::string buyer,
365                            std::string seller, TradeTypeEnum tradeType,
366                            std::string passiveOrder,
367                            uint64_t passiveOrderRemaining, uint64_t sequence,
368                            double timestamp)
2c515f 369     : FromExchange(type, product, sequence, timestamp), price(price),
JG 370       volume(volume), buyer(buyer), seller(seller), tradeType(tradeType),
371       passiveOrder(passiveOrder), passiveOrderRemaining(passiveOrderRemaining)
16b655 372 {
JG 373 }
374
375 BrokerRequest::BrokerRequest(MessageTypes type, std::string product,
376                              double price, book::OrderSideEnum side,
377                              uint64_t volume, std::string counterparty)
2c515f 378     : Broker(type, product, price, side, volume, counterparty)
16b655 379 {
JG 380 }
381
382 BrokerAck::BrokerAck(MessageTypes type, std::string product, double price,
383                      book::OrderSideEnum side, uint64_t volume,
384                      std::string counterparty, std::string id,
385                      std::string brokerTradeStatus, std::string owner)
2c515f 386     : Broker(type, product, price, side, volume, counterparty), id(id),
JG 387       brokerTradeStatus(brokerTradeStatus), owner(owner)
16b655 388 {
JG 389 }
390
391 BrokerConfirm::BrokerConfirm(MessageTypes type, std::string product,
392                              double price, book::OrderSideEnum side,
393                              uint64_t volume, std::string counterparty,
394                              std::string id)
2c515f 395     : Broker(type, product, price, side, volume, counterparty), id(id)
16b655 396 {
JG 397 }
398 } // namespace json