Joel Grunbaum
2022-01-20 441abf1e6a15a39f1ef7bf5e4ee2a4a43bff327b
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) {
0bef19 178         for (auto i = bs[message->product].bidSide.begin();
JG 179              i != bs[message->product].bidSide.end(); i++) {
180             if (i->id == message->id) {
181                 bs[message->product].bidSide.erase(i);
182                 break;
183             }
184         }
2c515f 185     } else {
0bef19 186         for (auto i = bs[message->product].askSide.begin();
JG 187              i != bs[message->product].askSide.end(); i++) {
188             if (i->id == message->id) {
189                 bs[message->product].askSide.erase(i);
190                 break;
191             }
192         }
16b655 193     }
JG 194 }
195 void tradeOrder(std::unordered_map<std::string, book::Book>& bs,
196                 json::TradeMessage* message)
197 {
0bef19 198     if (message->tradeType == json::BUY_AGGRESSOR) {
JG 199         if (message->passiveOrderRemaining > 0) {
200             for (auto& i : bs[message->product].askSide) {
201                 if (i.id == message->passiveOrder) {
202                     i.volume = message->passiveOrderRemaining;
203                     break;
204                 }
205             }
206         } else {
207             for (auto i = bs[message->product].askSide.begin();
208                  i != bs[message->product].askSide.end(); i++) {
209                 if (i->id == message->passiveOrder) {
210                     bs[message->product].askSide.erase(i);
211                     break;
212                 }
213             }
214         }
215     } else if (message->tradeType == json::SELL_AGGRESSOR) {
216         if (message->passiveOrderRemaining > 0) {
217             for (auto& i : bs[message->product].bidSide) {
218                 if (i.id == message->passiveOrder) {
219                     i.volume = message->passiveOrderRemaining;
220                     break;
221                 }
222             }
223         } else {
224             for (auto i = bs[message->product].bidSide.begin();
225                  i != bs[message->product].bidSide.end(); i++) {
226                 if (i->id == message->passiveOrder) {
227                     bs[message->product].bidSide.erase(i);
228                     break;
229                 }
230             }
231         }
232     }
16b655 233 }
4fdb65 234
16b655 235 void broker(std::unordered_map<std::string, book::Book>& bs,
JG 236             json::Broker* message)
237 {
238 }
239
6926be 240 json::Message* send(std::string& message)
16b655 241 {
4fdb65 242     httplib::MultipartFormDataItems a = {{"message", message, "", ""},
JG 243                                          {"username", USER, "", ""},
244                                          {"password", PASS, "", ""}};
0bef19 245     auto res = cli.Post("/execution",
JG 246                         "message=" + message + "&username=" + USER +
247                             "&password=" + PASS,
248                         "application/x-www-form-urlencoded");
6bdd28 249     std::string b = res->body;
JG 250     std::queue<json::Message*> c = json::parse(b);
251     return c.front();
16b655 252 }
JG 253
254 } // namespace protocol