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