#include "protocol.hpp" #include "book.hpp" #include "cpp-httplib/httplib.h" #include "easywsclient/easywsclient.hpp" #include "json.hpp" #include "secrets.hpp" #include #include #include #include #include #include #include #include #include namespace protocol { static std::unordered_map mapAnnounce; std::string server = std::string(HOST) + ":" + std::string(PORT); httplib::Client cli("http://" + server); std::unique_ptr ws; double lastime = 0; void initialise() { mapAnnounce = {{json::FUTURE_TYPE, book::FUTURE}, {json::SPREAD_TYPE, book::SPREAD}, {json::CALL_TYPE, book::CALL}, {json::PUT_TYPE, book::PUT}}; } std::unordered_map recoverBook() { std::unordered_map bs; // std::ifstream sampleFile("../data.test"); // std::stringstream ss; // ss << sampleFile.rdbuf(); httplib::Client cli("http://" + server); auto res = cli.Get("/recover"); std::string l; // l = ss.str(); l = res->body; std::queue a(json::parse(l)); while (!a.empty()) { if (static_cast(a.front()) != nullptr || static_cast(a.front())->timestamp > lastime) { lastime = static_cast(a.front())->timestamp; protocol::handleMessage(bs, a.front()); } delete a.front(); a.pop(); } return bs; } void createWebSocket() { ws = std::unique_ptr( easywsclient::WebSocket::pointer(easywsclient::WebSocket::from_url( "ws://" + server + "/information"))); ws->poll(); } std::deque catchUp(std::unordered_map& bs) { std::string feed; bool gotMessage; std::deque out; do { gotMessage = false; ws->poll(); ws->dispatch([gotMessageOut = &gotMessage, messageOut = &feed, ws = ws.get()](const std::string& message) { *gotMessageOut = true; *messageOut = message; }); if (gotMessage) { std::queue a(json::parse(feed)); while (!a.empty()) { if (static_cast(a.front()) != nullptr || static_cast(a.front())->timestamp > lastime) { lastime = static_cast(a.front())->timestamp; } protocol::handleMessage(bs, a.front()); out.push_back(a.front()); a.pop(); } } } while (gotMessage); return out; } json::Message* addOrder(json::AddMessage& order) { std::string message = order.as_string(); return send(message); } json::Message* deleteOrder(json::DeleteMessage& order) { std::string message = order.as_string(); return send(message); } void handleMessage(std::unordered_map& bs, json::Message* message) { if (mapAnnounce.empty()) initialise(); if (dynamic_cast(message) != nullptr) { lastime = dynamic_cast(message)->timestamp; } switch (message->type) { case json::FUTURE_TYPE: case json::SPREAD_TYPE: case json::CALL_TYPE: case json::PUT_TYPE: announce(bs, static_cast(message)); break; case json::SETTLEMENT: settle(bs, static_cast(message)); break; case json::ADDED: addedOrder(bs, static_cast(message)); break; case json::DELETED: deletedOrder(bs, static_cast(message)); break; case json::TRADE: tradeOrder(bs, static_cast(message)); break; case json::BROKER_REQUEST: case json::BROKER_ACK: case json::BROKER_CONFIRM: broker(bs, static_cast(message)); break; default:; } } void announce(std::unordered_map& bs, json::AnnounceMessage* message) { bs[message->product] = book::Book(mapAnnounce[message->type], message->product, message->stationId, message->unit, message->expiry, message->aggFee, message->pasFee, message->broFee); } void settle(std::unordered_map& bs, json::SettleMessage* message) { bs.erase(message->product); } void addedOrder(std::unordered_map& bs, json::AddedMessage* message) { if (message->side == book::Buy && message->resting) { book::Order t(message->price, book::Buy, message->resting, message->timestamp, message->id); bs[message->product].bid(t); } else if (message->side == book::Sell && message->resting) { book::Order t(message->price, book::Sell, message->resting, message->timestamp, message->id); bs[message->product].ask(t); } } void deletedOrder(std::unordered_map& bs, json::DeletedMessage* message) { if (message->side == book::Buy) { for (auto i = bs[message->product].bidSide.begin(); i != bs[message->product].bidSide.end(); i++) { if (i->id == message->id) { bs[message->product].bidSide.erase(i); break; } } } else { for (auto i = bs[message->product].askSide.begin(); i != bs[message->product].askSide.end(); i++) { if (i->id == message->id) { bs[message->product].askSide.erase(i); break; } } } } void tradeOrder(std::unordered_map& bs, json::TradeMessage* message) { if (message->tradeType == json::BUY_AGGRESSOR) { if (message->passiveOrderRemaining > 0) { for (auto& i : bs[message->product].askSide) { if (i.id == message->passiveOrder) { i.volume = message->passiveOrderRemaining; break; } } } else { for (auto i = bs[message->product].askSide.begin(); i != bs[message->product].askSide.end(); i++) { if (i->id == message->passiveOrder) { bs[message->product].askSide.erase(i); break; } } } } else if (message->tradeType == json::SELL_AGGRESSOR) { if (message->passiveOrderRemaining > 0) { for (auto& i : bs[message->product].bidSide) { if (i.id == message->passiveOrder) { i.volume = message->passiveOrderRemaining; break; } } } else { for (auto i = bs[message->product].bidSide.begin(); i != bs[message->product].bidSide.end(); i++) { if (i->id == message->passiveOrder) { bs[message->product].bidSide.erase(i); break; } } } } } void broker(std::unordered_map& bs, json::Broker* message) { } json::Message* send(std::string& message) { httplib::MultipartFormDataItems a = {{"message", message, "", ""}, {"username", USER, "", ""}, {"password", PASS, "", ""}}; auto res = cli.Post("/execution", a); std::string b = res->body; std::queue c = json::parse(b); return c.front(); } } // namespace protocol