Joel Grunbaum
2022-01-19 0b7aa02704f6ece97d17fbb118519c5cc62caaba
commit | author | age
16b655 1 #include "protocol.hpp"
JG 2
3 #include "book.hpp"
4 #include "cpp-httplib/httplib.h"
4fdb65 5 #include "easywsclient/easywsclient.hpp"
16b655 6 #include "json.hpp"
JG 7 #include "secrets.hpp"
8
9 #include <chrono>
4fdb65 10 #include <cstddef>
16b655 11 #include <iostream>
4fdb65 12 #include <memory>
16b655 13 #include <queue>
JG 14 #include <sstream>
4fdb65 15 #include <stdexcept>
16b655 16 #include <string>
JG 17 #include <unordered_map>
18
19 namespace protocol
20 {
21 static std::unordered_map<json::MessageTypes, book::ProductTypeEnum>
2c515f 22     mapAnnounce;
16b655 23 std::string server = std::string(HOST) + ":" + std::string(PORT);
JG 24 httplib::Client cli("http://" + server);
0b7aa0 25 std::unique_ptr<easywsclient::WebSocket> ws;
4fdb65 26
JG 27 double lastime = 0;
16b655 28
JG 29 void initialise()
30 {
2c515f 31     mapAnnounce = {{json::FUTURE_TYPE, book::FUTURE},
JG 32                    {json::SPREAD_TYPE, book::SPREAD},
33                    {json::CALL_TYPE, book::CALL},
34                    {json::PUT_TYPE, book::PUT}};
16b655 35 }
JG 36
37 std::unordered_map<std::string, book::Book> recoverBook()
38 {
2c515f 39     std::unordered_map<std::string, book::Book> bs;
JG 40     // std::ifstream sampleFile("../data.test");
41     // std::stringstream ss;
42     // ss << sampleFile.rdbuf();
43     httplib::Client cli("http://" + server);
44     auto res = cli.Get("/recover");
45     std::string l;
46     // l = ss.str();
47     l = res->body;
48     std::queue<json::Message*> a(json::parse(l));
49     while (!a.empty()) {
4fdb65 50         if (static_cast<json::FromExchange*>(a.front()) != nullptr ||
JG 51             static_cast<json::FromExchange*>(a.front())->timestamp > lastime) {
52             lastime = static_cast<json::FromExchange*>(a.front())->timestamp;
53             protocol::handleMessage(bs, a.front());
54         }
2c515f 55         delete a.front();
JG 56         a.pop();
57     }
58     return bs;
4fdb65 59 }
JG 60
0b7aa0 61 void createWebSocket()
4fdb65 62 {
0b7aa0 63     ws = std::unique_ptr<easywsclient::WebSocket>(
JG 64         easywsclient::WebSocket::pointer(easywsclient::WebSocket::from_url(
65             "ws://" + server + "/information")));
4fdb65 66     ws->poll();
0b7aa0 67 }
JG 68
69 std::deque<json::Message*>
70 catchUp(std::unordered_map<std::string, book::Book>& bs)
71 {
72     std::string feed;
73     bool gotMessage;
74     std::deque<json::Message*> out;
75     do {
76         gotMessage = false;
77         ws->poll();
78         ws->dispatch([gotMessageOut = &gotMessage, messageOut = &feed,
79                       ws = ws.get()](const std::string& message) {
80             *gotMessageOut = true;
81             *messageOut = message;
82         });
83         if (gotMessage) {
84             std::queue<json::Message*> a(json::parse(feed));
85             while (!a.empty()) {
86                 if (static_cast<json::FromExchange*>(a.front()) != nullptr ||
87                     static_cast<json::FromExchange*>(a.front())->timestamp >
88                         lastime) {
89                     lastime =
90                         static_cast<json::FromExchange*>(a.front())->timestamp;
91                 }
92                 protocol::handleMessage(bs, a.front());
93                 out.push_back(a.front());
94                 a.pop();
4fdb65 95             }
JG 96         }
0b7aa0 97     } while (gotMessage);
JG 98     return out;
16b655 99 }
JG 100
6926be 101 json::Message* addOrder(json::AddMessage& order)
16b655 102 {
6bdd28 103     std::string message = order.as_string();
2c515f 104     return send(message);
16b655 105 }
JG 106
6926be 107 json::Message* deleteOrder(json::DeleteMessage& order)
16b655 108 {
6bdd28 109     std::string message = order.as_string();
2c515f 110     return send(message);
16b655 111 }
JG 112
113 void handleMessage(std::unordered_map<std::string, book::Book>& bs,
114                    json::Message* message)
115 {
2c515f 116     if (mapAnnounce.empty()) initialise();
4fdb65 117     if (dynamic_cast<json::FromExchange*>(message) != nullptr) {
JG 118         lastime = dynamic_cast<json::FromExchange*>(message)->timestamp;
119     }
2c515f 120     switch (message->type) {
JG 121     case json::FUTURE_TYPE:
122     case json::SPREAD_TYPE:
123     case json::CALL_TYPE:
124     case json::PUT_TYPE:
611ad7 125         announce(bs, static_cast<json::AnnounceMessage*>(message));
2c515f 126         break;
JG 127     case json::SETTLEMENT:
611ad7 128         settle(bs, static_cast<json::SettleMessage*>(message));
2c515f 129         break;
JG 130     case json::ADDED:
611ad7 131         addedOrder(bs, static_cast<json::AddedMessage*>(message));
2c515f 132         break;
JG 133     case json::DELETED:
611ad7 134         deletedOrder(bs, static_cast<json::DeletedMessage*>(message));
2c515f 135         break;
JG 136     case json::TRADE:
611ad7 137         tradeOrder(bs, static_cast<json::TradeMessage*>(message));
2c515f 138         break;
JG 139     case json::BROKER_REQUEST:
140     case json::BROKER_ACK:
141     case json::BROKER_CONFIRM:
611ad7 142         broker(bs, static_cast<json::Broker*>(message));
2c515f 143         break;
JG 144     default:;
145     }
16b655 146 }
JG 147
148 void announce(std::unordered_map<std::string, book::Book>& bs,
149               json::AnnounceMessage* message)
150 {
2c515f 151     bs[message->product] =
JG 152         book::Book(mapAnnounce[message->type], message->product,
153                    message->stationId, message->unit, message->expiry,
154                    message->aggFee, message->pasFee, message->broFee);
16b655 155 }
JG 156 void settle(std::unordered_map<std::string, book::Book>& bs,
157             json::SettleMessage* message)
158 {
2c515f 159     bs.erase(message->product);
16b655 160 }
JG 161 void addedOrder(std::unordered_map<std::string, book::Book>& bs,
162                 json::AddedMessage* message)
163 {
4fdb65 164     if (message->side == book::Buy && message->resting) {
2c515f 165         book::Order t(message->price, book::Buy, message->resting,
JG 166                       message->timestamp, message->id);
167         bs[message->product].bid(t);
4fdb65 168     } else if (message->side == book::Sell && message->resting) {
2c515f 169         book::Order t(message->price, book::Sell, message->resting,
JG 170                       message->timestamp, message->id);
171         bs[message->product].ask(t);
172     }
16b655 173 }
JG 174 void deletedOrder(std::unordered_map<std::string, book::Book>& bs,
175                   json::DeletedMessage* message)
176 {
2c515f 177     if (message->side == book::Buy) {
4fdb65 178         bs[message->product].bidSide.erase(message->id);
2c515f 179     } else {
4fdb65 180         bs[message->product].askSide.erase(message->id);
16b655 181     }
JG 182 }
183 void tradeOrder(std::unordered_map<std::string, book::Book>& bs,
184                 json::TradeMessage* message)
185 {
83c048 186     if (bs.find(message->passiveOrder) != bs.end()) {
4fdb65 187         if (message->tradeType == json::BUY_AGGRESSOR) {
JG 188             if (message->passiveOrderRemaining > 0) {
189                 bs[message->product].askSide.at(message->passiveOrder).volume =
190                     message->passiveOrderRemaining;
191             } else {
192                 bs[message->product].askSide.erase(message->passiveOrder);
193             }
194         } else if (message->tradeType == json::SELL_AGGRESSOR) {
195             if (message->passiveOrderRemaining > 0) {
196                 bs[message->product].bidSide.at(message->passiveOrder).volume =
197                     message->passiveOrderRemaining;
198             } else {
199                 bs[message->product].bidSide.erase(message->passiveOrder);
200             }
201         }
2c515f 202     }
16b655 203 }
4fdb65 204
16b655 205 void broker(std::unordered_map<std::string, book::Book>& bs,
JG 206             json::Broker* message)
207 {
208 }
209
6926be 210 json::Message* send(std::string& message)
16b655 211 {
4fdb65 212     httplib::MultipartFormDataItems a = {{"message", message, "", ""},
JG 213                                          {"username", USER, "", ""},
214                                          {"password", PASS, "", ""}};
6bdd28 215     auto res = cli.Post("/execution", a);
JG 216     std::string b = res->body;
217     std::queue<json::Message*> c = json::parse(b);
218     return c.front();
16b655 219 }
JG 220
221 } // namespace protocol