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