Joel Grunbaum
2022-01-11 83c048d1295b9df59d90a7513953c99a267eb1f5
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},
JG 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
b4cf0a 69 std::queue<Message*> parse(std::string& str)
16b655 70 {
2c515f 71     std::queue<Message*> out;
JG 72     rapidjson::Document d;
73     d.Parse(str.c_str());
74     if (d.IsArray()) {
75         for (rapidjson::SizeType i = 0; i < d.Size(); i++) {
76             out.push(parseSingle(d[i]));
77         }
78     } else {
79         out.push(parseSingle(d));
b4cf0a 80     }
2c515f 81     return out;
16b655 82 }
JG 83
b4cf0a 84 Message* parseSingle(rapidjson::Value& d)
16b655 85 {
2c515f 86     if (mapTypes.empty()) {
JG 87         initialise();
88     }
6bdd28 89     if (d.HasMember("error")) return error(d);
2c515f 90     Message* out;
JG 91     switch (mapTypes[d["type"].GetString()]) {
92     case FUTURE_TYPE:
93     case SPREAD_TYPE:
94     case CALL_TYPE:
95     case PUT_TYPE:
96         out = announce(d);
97         break;
98     case SETTLEMENT:
99         out = settle(d);
100         break;
101     case ADDED:
102         out = added(d);
103         break;
104     case DELETED:
105         out = deleted(d);
6bdd28 106         break;
JG 107     case REJECT:
108         out = reject(d);
2c515f 109         break;
JG 110     case TRADE:
111         out = trade(d);
112         break;
113     case BROKER_REQUEST:
114         out = brokerReq(d);
115         break;
116     case BROKER_ACK:
117         out = brokerAck(d);
118         break;
119     case BROKER_CONFIRM:
120         out = brokerCon(d);
121         break;
122     default:
123         out = new Message(NONE, "");
124         break;
125     }
126     return out;
16b655 127 }
JG 128
b4cf0a 129 AnnounceMessage* announce(rapidjson::Value& d)
16b655 130 {
2c515f 131     // std::stringstream expiryStream(d["expiry"].GetString());
JG 132     std::chrono::nanoseconds exp_time(0);
133     // expiryStream >>
134     // date::parse("%Y-%m-%f %H:%M%z", exp_time); // Parsing is broken
135     return new AnnounceMessage(
136         mapTypes[d["type"].GetString()], d["product"].GetString(),
137         d["stationId"].GetInt(), d["stationName"].GetString(),
138         d["unit"].GetString(), exp_time, d["aggressiveFee"].GetDouble(),
139         d["passiveFee"].GetDouble(), d["brokerFee"].GetDouble(),
140         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 141 }
JG 142
b4cf0a 143 SettleMessage* settle(rapidjson::Value& d)
16b655 144 {
2c515f 145     // std::stringstream expiryStream(d["expiry"].GetString());
JG 146     std::chrono::nanoseconds exp_time(0);
147     // expiryStream >> date::parse("%Y-%m-%d %H:%M%z", exp_time);
148     return new SettleMessage(
149         mapTypes[d["type"].GetString()], d["product"].GetString(),
150         d["stationName"].GetString(), exp_time, d["price"].GetDouble(),
151         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 152 }
JG 153
b4cf0a 154 AddedMessage* added(rapidjson::Value& d)
16b655 155 {
2c515f 156     return new AddedMessage(
JG 157         mapTypes[d["type"].GetString()], d["product"].GetString(),
158         d["id"].GetString(), mapOrder[d["side"].GetString()],
159         d["price"].GetDouble(), d["filled"].GetInt(), d["resting"].GetInt(),
160         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 161 }
JG 162
b4cf0a 163 DeletedMessage* deleted(rapidjson::Value& d)
16b655 164 {
2c515f 165     return new DeletedMessage(
JG 166         mapTypes[d["type"].GetString()], d["product"].GetString(),
167         d["id"].GetString(), mapOrder[d["side"].GetString()],
168         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 169 }
JG 170
6bdd28 171 RejectMessage* reject(rapidjson::Value& d)
JG 172 {
173     return new RejectMessage(mapTypes[d["type"].GetString()], "",
174                              d["error"].GetString(), uint64_t(0), double(0));
175 }
176
b4cf0a 177 TradeMessage* trade(rapidjson::Value& d)
16b655 178 {
2c515f 179     return new TradeMessage(
JG 180         mapTypes[d["type"].GetString()], d["product"].GetString(),
181         d["price"].GetDouble(), d["volume"].GetInt(), d["buyer"].GetString(),
182         d["seller"].GetString(), mapTrade[d["tradeType"].GetString()],
183         d["passiveOrder"].GetString(), d["passiveOrderRemaining"].GetInt(),
184         d["sequence"].GetInt(), d["timestamp"].GetDouble());
16b655 185 }
JG 186
b4cf0a 187 BrokerRequest* brokerReq(rapidjson::Value& d)
16b655 188 {
2c515f 189     return new BrokerRequest(
JG 190         mapTypes[d["type"].GetString()], d["product"].GetString(),
191         d["price"].GetDouble(), mapOrder[d["side"].GetString()],
192         d["volume"].GetInt(), d["counterparty"].GetString());
16b655 193 }
JG 194
b4cf0a 195 BrokerAck* brokerAck(rapidjson::Value& d)
16b655 196 {
2c515f 197     return new BrokerAck(mapTypes[d["type"].GetString()],
JG 198                          d["product"].GetString(), d["price"].GetDouble(),
199                          mapOrder[d["side"].GetString()], d["volume"].GetInt(),
200                          d["counterparty"].GetString(), d["id"].GetString(),
201                          d["brokerTradeStatus"].GetString(),
202                          d["owner"].GetString());
16b655 203 }
b4cf0a 204 BrokerConfirm* brokerCon(rapidjson::Value& d)
16b655 205 {
2c515f 206     return new BrokerConfirm(
JG 207         mapTypes[d["type"].GetString()], d["product"].GetString(),
208         d["price"].GetDouble(), mapOrder[d["side"].GetString()],
209         d["volume"].GetInt(), d["counterparty"].GetString(),
210         d["id"].GetString());
16b655 211 }
JG 212
6bdd28 213 ErrorMessage* error(rapidjson::Value& d)
JG 214 {
215     return new ErrorMessage(d["error"].GetString());
216 }
217
16b655 218 Message::Message() : type(NONE), product("error") {}
JG 219
220 Message::Message(MessageTypes types, std::string product)
2c515f 221     : type(types), product(product)
16b655 222 {
6bdd28 223 }
JG 224
225 ErrorMessage::ErrorMessage(std::string message)
226     : Message(ERROR, ""), message(message)
227 {
228 }
229 std::string ErrorMessage::as_string()
230 {
231     return "{\"error\": \"" + this->message + "\"}";
16b655 232 }
JG 233
234 FromExchange::FromExchange(MessageTypes type, std::string product,
235                            uint64_t sequence, double timestamp)
2c515f 236     : Message(type, product), sequence(sequence), timestamp(timestamp)
16b655 237 {
JG 238 }
239
240 ToExchange::ToExchange(MessageTypes type, std::string product)
2c515f 241     : Message(type, product){};
16b655 242
JG 243 Broker::Broker(MessageTypes type, std::string product, double price,
244                book::OrderSideEnum side, uint64_t volume,
245                std::string counterparty)
2c515f 246     : Message(type, product), price(price), side(side), volume(volume),
JG 247       counterparty(counterparty)
16b655 248 {
JG 249 }
250
251 AnnounceMessage::AnnounceMessage(MessageTypes type, std::string product,
b4cf0a 252                                  int stationId, std::string stationName,
16b655 253                                  std::string unit,
JG 254                                  std::chrono::nanoseconds expiry, double aggFee,
255                                  double pasFee, double broFee,
256                                  uint64_t sequence, double timestamp)
2c515f 257     : FromExchange(type, product, sequence, timestamp), stationId(stationId),
JG 258       stationName(stationName), unit(unit), expiry(expiry), aggFee(aggFee),
259       pasFee(pasFee), broFee(broFee)
16b655 260 {
JG 261 }
262
263 SettleMessage::SettleMessage(MessageTypes type, std::string product,
264                              std::string stationName,
265                              std::chrono::nanoseconds expiry, double price,
266                              uint64_t sequence, double timestamp)
2c515f 267     : FromExchange(type, product, sequence, timestamp),
JG 268       stationName(stationName), expiry(expiry), price(price)
16b655 269 {
JG 270 }
271
272 AddMessage::AddMessage(MessageTypes type, std::string product, double price,
273                        book::OrderSideEnum side, uint64_t volume)
2c515f 274     : ToExchange(type, product), price(price), side(side), volume(volume)
16b655 275 {
JG 276 }
277
278 std::string AddMessage::as_string()
279 {
2c515f 280     if (mapOrderSide.empty()) initialise();
JG 281     return "{\"type\": \"ADD\", \"product\": \"" + this->product +
282            "\", \"price\": " + std::to_string(this->price) + ", \"side\": \"" +
283            mapOrderSide[this->side] +
284            "\", \"volume\": " + std::to_string(this->volume) + "}";
16b655 285 }
JG 286
287 AddedMessage::AddedMessage(MessageTypes type, std::string product,
288                            std::string id, book::OrderSideEnum side,
289                            double price, uint64_t filled, uint64_t resting,
290                            uint64_t sequence, double timestamp)
2c515f 291     : FromExchange(type, product, sequence, timestamp), id(id), side(side),
JG 292       price(price), filled(filled), resting(resting)
16b655 293 {
JG 294 }
295
6bdd28 296 std::string AddedMessage::as_string()
JG 297 {
298     return "{\"type\": \"ADDED\", \"product\": \"" + this->product +
299            "\", \"product\": \"" + this->id + "\" \"side\": \"" +
300            mapOrderSide[this->side] +
301            "\", \"price\": " + std::to_string(this->price) +
302            "\"filled\": " + std::to_string(this->filled) +
303            ", \"resting\": " + std::to_string(this->resting) +
304            ", \"sequence\": " + std::to_string(this->sequence) +
305            ", \"timestamp\":" + std::to_string(this->timestamp) + "}";
306 }
307
16b655 308 DeleteMessage::DeleteMessage(MessageTypes type, std::string product,
JG 309                              std::string id)
2c515f 310     : ToExchange(type, product), id(id)
16b655 311 {
JG 312 }
313
314 std::string DeleteMessage::as_string()
315 {
2c515f 316     if (mapOrderSide.empty()) initialise();
JG 317     return "{\"type\": \"DELETE\", \"product\": \"" + this->product +
318            "\", \"id\": \"" + this->id + "\"}";
16b655 319 }
JG 320
321 DeletedMessage::DeletedMessage(MessageTypes type, std::string product,
322                                std::string id, book::OrderSideEnum side,
323                                uint64_t sequence, double timestamp)
2c515f 324     : FromExchange(type, product, sequence, timestamp), id(id), side(side)
16b655 325 {
JG 326 }
327
6bdd28 328 std::string DeletedMessage::as_string()
JG 329 {
330     return "{\"type\": \"DELETED\", \"product\": \"" + this->product +
331            "\", \"product\": \"" + this->id + "\" \"side\": \"" +
332            mapOrderSide[this->side] +
333            ", \"sequence\": " + std::to_string(this->sequence) +
334            ", \"timestamp\":" + std::to_string(this->timestamp) + "}";
335 }
336
16b655 337 RejectMessage::RejectMessage(MessageTypes type, std::string product,
JG 338                              std::string error, uint64_t sequence,
339                              double timestamp)
2c515f 340     : FromExchange(type, product, sequence, timestamp), error(error)
16b655 341 {
JG 342 }
343
6bdd28 344 std::string RejectMessage::as_string()
JG 345 {
346     return "{\"type\": \"REJECT\", \"product\": \"" + this->product =
347                "\", \"error\": \"" + this->error +
348                "\", \"sequence\": " + std::to_string(this->sequence) +
349                ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
350 }
351
16b655 352 TradeMessage::TradeMessage(MessageTypes type, std::string product, double price,
JG 353                            uint64_t volume, std::string buyer,
354                            std::string seller, TradeTypeEnum tradeType,
355                            std::string passiveOrder,
356                            uint64_t passiveOrderRemaining, uint64_t sequence,
357                            double timestamp)
2c515f 358     : FromExchange(type, product, sequence, timestamp), price(price),
JG 359       volume(volume), buyer(buyer), seller(seller), tradeType(tradeType),
360       passiveOrder(passiveOrder), passiveOrderRemaining(passiveOrderRemaining)
16b655 361 {
JG 362 }
363
364 BrokerRequest::BrokerRequest(MessageTypes type, std::string product,
365                              double price, book::OrderSideEnum side,
366                              uint64_t volume, std::string counterparty)
2c515f 367     : Broker(type, product, price, side, volume, counterparty)
16b655 368 {
JG 369 }
370
371 BrokerAck::BrokerAck(MessageTypes type, std::string product, double price,
372                      book::OrderSideEnum side, uint64_t volume,
373                      std::string counterparty, std::string id,
374                      std::string brokerTradeStatus, std::string owner)
2c515f 375     : Broker(type, product, price, side, volume, counterparty), id(id),
JG 376       brokerTradeStatus(brokerTradeStatus), owner(owner)
16b655 377 {
JG 378 }
379
380 BrokerConfirm::BrokerConfirm(MessageTypes type, std::string product,
381                              double price, book::OrderSideEnum side,
382                              uint64_t volume, std::string counterparty,
383                              std::string id)
2c515f 384     : Broker(type, product, price, side, volume, counterparty), id(id)
16b655 385 {
JG 386 }
387 } // namespace json