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