#include "protocol.hpp"
|
|
#include "book.hpp"
|
#include "cpp-httplib/httplib.h"
|
#include "json.hpp"
|
#include "secrets.hpp"
|
|
#include <chrono>
|
#include <iostream>
|
#include <queue>
|
#include <sstream>
|
#include <string>
|
#include <unordered_map>
|
|
namespace protocol
|
{
|
static std::unordered_map<json::MessageTypes, book::ProductTypeEnum>
|
mapAnnounce;
|
std::string server = std::string(HOST) + ":" + std::string(PORT);
|
httplib::Client cli("http://" + server);
|
|
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<std::string, book::Book> recoverBook()
|
{
|
std::unordered_map<std::string, book::Book> 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<json::Message*> a(json::parse(l));
|
while (!a.empty()) {
|
protocol::handleMessage(bs, a.front());
|
delete a.front();
|
a.pop();
|
}
|
return bs;
|
}
|
|
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<std::string, book::Book>& bs,
|
json::Message* message)
|
{
|
if (mapAnnounce.empty()) initialise();
|
switch (message->type) {
|
case json::FUTURE_TYPE:
|
case json::SPREAD_TYPE:
|
case json::CALL_TYPE:
|
case json::PUT_TYPE:
|
announce(bs, dynamic_cast<json::AnnounceMessage*>(message));
|
break;
|
case json::SETTLEMENT:
|
settle(bs, dynamic_cast<json::SettleMessage*>(message));
|
break;
|
case json::ADDED:
|
addedOrder(bs, dynamic_cast<json::AddedMessage*>(message));
|
break;
|
case json::DELETED:
|
deletedOrder(bs, dynamic_cast<json::DeletedMessage*>(message));
|
break;
|
case json::TRADE:
|
tradeOrder(bs, dynamic_cast<json::TradeMessage*>(message));
|
break;
|
case json::BROKER_REQUEST:
|
case json::BROKER_ACK:
|
case json::BROKER_CONFIRM:
|
broker(bs, dynamic_cast<json::Broker*>(message));
|
break;
|
default:;
|
}
|
}
|
|
void announce(std::unordered_map<std::string, book::Book>& 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<std::string, book::Book>& bs,
|
json::SettleMessage* message)
|
{
|
bs.erase(message->product);
|
}
|
void addedOrder(std::unordered_map<std::string, book::Book>& bs,
|
json::AddedMessage* message)
|
{
|
if (message->side == book::Buy) {
|
book::Order t(message->price, book::Buy, message->resting,
|
message->timestamp, message->id);
|
bs[message->product].bid(t);
|
} else {
|
book::Order t(message->price, book::Sell, message->resting,
|
message->timestamp, message->id);
|
bs[message->product].ask(t);
|
}
|
}
|
void deletedOrder(std::unordered_map<std::string, book::Book>& bs,
|
json::DeletedMessage* message)
|
{
|
if (message->side == book::Buy) {
|
for (std::size_t i = 0; i < bs[message->product].bidSide.size(); i++) {
|
if (bs[message->product].bidSide[i].id == message->id) {
|
bs[message->product].bidSide[i] =
|
bs[message->product].bidSide.back();
|
bs[message->product].bidSide.pop_back();
|
std::make_heap(bs[message->product].bidSide.begin(),
|
bs[message->product].bidSide.end(),
|
std::less<book::Level>());
|
}
|
}
|
} else {
|
for (std::size_t i = 0; i < bs[message->product].askSide.size(); i++) {
|
if (bs[message->product].askSide[i].id == message->id) {
|
bs[message->product].askSide[i] =
|
bs[message->product].askSide.back();
|
bs[message->product].askSide.pop_back();
|
std::make_heap(bs[message->product].askSide.begin(),
|
bs[message->product].askSide.end(),
|
std::greater<book::Level>());
|
}
|
}
|
}
|
}
|
void tradeOrder(std::unordered_map<std::string, book::Book>& bs,
|
json::TradeMessage* message)
|
{
|
if (message->tradeType == json::BUY_AGGRESSOR) {
|
book::Order t(message->price, book::Buy, message->volume,
|
message->timestamp, message->passiveOrder);
|
bs[message->product].bid(t);
|
} else {
|
book::Order t(message->price, book::Sell, message->volume,
|
message->timestamp, message->passiveOrder);
|
bs[message->product].ask(t);
|
}
|
}
|
void broker(std::unordered_map<std::string, book::Book>& 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<json::Message*> c = json::parse(b);
|
return c.front();
|
}
|
|
} // namespace protocol
|