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