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