Joel Grunbaum
2022-01-19 0b7aa02704f6ece97d17fbb118519c5cc62caaba
json.cpp
@@ -1,6 +1,5 @@
#include "json.hpp"
#include "book.hpp"
#include "date/include/date/date.h"
#include "protocol.hpp"
#include "rapidjson/include/rapidjson/document.h"
#include "rapidjson/include/rapidjson/rapidjson.h"
@@ -25,6 +24,8 @@
static std::unordered_map<std::string, book::OrderSideEnum> mapOrder;
static std::unordered_map<std::string, TradeTypeEnum> mapTrade;
static std::unordered_map<book::OrderSideEnum, std::string> mapOrderSide;
static std::unordered_map<MessageTypes, std::string> mapAStr;
static std::unordered_map<TradeTypeEnum, std::string> mapTTStr;
void initialise()
{
@@ -48,9 +49,19 @@
   mapOrder = {{"BUY", book::Buy}, {"SELL", book::Sell}};
   mapTrade = {{"BUY_AGGRESSOR", BUY_AGGRESSOR},
               {"SELL_AGGRESSOR", SELL_AGGRESSOR}};
               {"SELL_AGGRESSOR", SELL_AGGRESSOR},
               {"BROKER_TRADE", BROKER_TRADE}};
   mapOrderSide = {{book::Buy, "BUY"}, {book::Sell, "SELL"}};
   mapAStr = {{FUTURE_TYPE, "FUTURE"},
              {SPREAD_TYPE, "SPREAD"},
              {CALL_TYPE, "CALL"},
              {PUT_TYPE, "PUT"}};
   mapTTStr = {{BUY_AGGRESSOR, "BUY_AGGRESSOR"},
               {SELL_AGGRESSOR, "SELL_AGGRESSOR"},
               {BROKER_TRADE, "BROKER_TRADE"}};
}
Message* parseSingle(rapidjson::Value& d);
@@ -58,10 +69,14 @@
SettleMessage* settle(rapidjson::Value& d);
AddedMessage* added(rapidjson::Value& d);
DeletedMessage* deleted(rapidjson::Value& d);
RejectMessage* reject(rapidjson::Value& d);
TradeMessage* trade(rapidjson::Value& d);
BrokerRequest* brokerReq(rapidjson::Value& d);
BrokerAck* brokerAck(rapidjson::Value& d);
BrokerConfirm* brokerCon(rapidjson::Value& d);
ErrorMessage* error(rapidjson::Value& d);
std::chrono::seconds parseTime(std::string& s);
std::queue<Message*> parse(std::string& str)
{
@@ -83,6 +98,7 @@
   if (mapTypes.empty()) {
      initialise();
   }
   if (d.HasMember("error")) return error(d);
   Message* out;
   switch (mapTypes[d["type"].GetString()]) {
   case FUTURE_TYPE:
@@ -99,6 +115,9 @@
      break;
   case DELETED:
      out = deleted(d);
      break;
   case REJECT:
      out = reject(d);
      break;
   case TRADE:
      out = trade(d);
@@ -119,12 +138,21 @@
   return out;
}
std::chrono::seconds parseTime(std::string& s)
{
   return std::chrono::hours{std::stoi(s.substr(0, 4)) * 24 * 30 * 12} +
          std::chrono::hours{std::stoi(s.substr(5, 2)) * 24 * 30} +
          std::chrono::hours{std::stoi(s.substr(8, 2)) * 24} +
          std::chrono::hours{std::stoi(s.substr(11, 2))} +
          std::chrono::minutes{std::stoi(s.substr(14, 2))} +
          std::chrono::hours{std::stoi(s.substr(16, 5))};
}
AnnounceMessage* announce(rapidjson::Value& d)
{
   // std::stringstream expiryStream(d["expiry"].GetString());
   std::string es = d["expiry"].GetString();
   std::chrono::nanoseconds exp_time(0);
   // expiryStream >>
   // date::parse("%Y-%m-%f %H:%M%z", exp_time); // Parsing is broken
   exp_time = parseTime(es);
   return new AnnounceMessage(
      mapTypes[d["type"].GetString()], d["product"].GetString(),
      d["stationId"].GetInt(), d["stationName"].GetString(),
@@ -135,9 +163,9 @@
SettleMessage* settle(rapidjson::Value& d)
{
   // std::stringstream expiryStream(d["expiry"].GetString());
   std::chrono::nanoseconds exp_time(0);
   // expiryStream >> date::parse("%Y-%m-%d %H:%M%z", exp_time);
   std::string es = d["expiry"].GetString();
   exp_time = parseTime(es);
   return new SettleMessage(
      mapTypes[d["type"].GetString()], d["product"].GetString(),
      d["stationName"].GetString(), exp_time, d["price"].GetDouble(),
@@ -146,11 +174,12 @@
AddedMessage* added(rapidjson::Value& d)
{
   return new AddedMessage(
      mapTypes[d["type"].GetString()], d["product"].GetString(),
      d["id"].GetString(), mapOrder[d["side"].GetString()],
      d["price"].GetDouble(), d["filled"].GetInt(), d["resting"].GetInt(),
      d["sequence"].GetInt(), d["timestamp"].GetDouble());
   return new AddedMessage(mapTypes[d["type"].GetString()],
                           d["product"].GetString(), d["id"].GetString(),
                           mapOrder[d["side"].GetString()],
                           d["price"].GetDouble(), d["filled"].GetInt(),
                           d["resting"].GetInt(), d["owner"].GetString(),
                           d["sequence"].GetInt(), d["timestamp"].GetDouble());
}
DeletedMessage* deleted(rapidjson::Value& d)
@@ -159,6 +188,12 @@
      mapTypes[d["type"].GetString()], d["product"].GetString(),
      d["id"].GetString(), mapOrder[d["side"].GetString()],
      d["sequence"].GetInt(), d["timestamp"].GetDouble());
}
RejectMessage* reject(rapidjson::Value& d)
{
   return new RejectMessage(mapTypes[d["type"].GetString()], "",
                            d["error"].GetString(), uint64_t(0), double(0));
}
TradeMessage* trade(rapidjson::Value& d)
@@ -197,11 +232,25 @@
      d["id"].GetString());
}
ErrorMessage* error(rapidjson::Value& d)
{
   return new ErrorMessage(d["error"].GetString());
}
Message::Message() : type(NONE), product("error") {}
Message::Message(MessageTypes types, std::string product)
   : type(types), product(product)
{
}
ErrorMessage::ErrorMessage(std::string message)
   : Message(ERROR, ""), message(message)
{
}
std::string ErrorMessage::as_string()
{
   return "{\"error\": \"" + this->message + "\"}";
}
FromExchange::FromExchange(MessageTypes type, std::string product,
@@ -233,6 +282,20 @@
{
}
std::string AnnounceMessage::as_string()
{
   return "{\"type\": \"" + mapAStr[this->type] =
              "\", \"product\": \"" + this->product +
              "\", \"stationId\": " + std::to_string(this->stationId) +
              "\", \"stationName\": \"" + this->stationName +
              "\", \"unit\": \"" + this->unit +
              "\", \"expiry\": " + std::to_string(this->expiry.count()) +
              ", \"aggressiveFee\": " + std::to_string(this->aggFee) +
              ", \"passiveFee\": " + std::to_string(this->pasFee) +
              ", \"sequence\": " + std::to_string(this->sequence) +
              ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
}
SettleMessage::SettleMessage(MessageTypes type, std::string product,
                             std::string stationName,
                             std::chrono::nanoseconds expiry, double price,
@@ -240,6 +303,17 @@
   : FromExchange(type, product, sequence, timestamp),
     stationName(stationName), expiry(expiry), price(price)
{
}
std::string SettleMessage::as_string()
{
   return "{\"type\": \"" + mapAStr[this->type] =
              "\", \"product\": \"" + this->product +
              "\", \"stationName\": \"" + this->stationName +
              "\", \"expiry\": " + std::to_string(this->expiry.count()) +
              ", \"price\": " + std::to_string(this->price) +
              ", \"sequence\": " + std::to_string(this->sequence) +
              ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
}
AddMessage::AddMessage(MessageTypes type, std::string product, double price,
@@ -260,10 +334,24 @@
AddedMessage::AddedMessage(MessageTypes type, std::string product,
                           std::string id, book::OrderSideEnum side,
                           double price, uint64_t filled, uint64_t resting,
                           uint64_t sequence, double timestamp)
                           std::string owner, uint64_t sequence,
                           double timestamp)
   : FromExchange(type, product, sequence, timestamp), id(id), side(side),
     price(price), filled(filled), resting(resting)
     price(price), filled(filled), resting(resting), owner(owner)
{
}
std::string AddedMessage::as_string()
{
   return "{\"type\": \"ADDED\", \"product\": \"" + this->product +
          "\", \"product\": \"" + this->id + "\", \"side\": \"" +
          mapOrderSide[this->side] +
          "\", \"price\": " + std::to_string(this->price) +
          ", \"filled\": " + std::to_string(this->filled) +
          ", \"resting\": " + std::to_string(this->resting) +
          ", \"owner\": \"" + this->owner +
          "\", \"sequence\": " + std::to_string(this->sequence) +
          ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
}
DeleteMessage::DeleteMessage(MessageTypes type, std::string product,
@@ -286,11 +374,28 @@
{
}
std::string DeletedMessage::as_string()
{
   return "{\"type\": \"DELETED\", \"product\": \"" + this->product +
          "\", \"product\": \"" + this->id + "\", \"side\": \"" +
          mapOrderSide[this->side] +
          ", \"sequence\": " + std::to_string(this->sequence) +
          ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
}
RejectMessage::RejectMessage(MessageTypes type, std::string product,
                             std::string error, uint64_t sequence,
                             double timestamp)
   : FromExchange(type, product, sequence, timestamp), error(error)
{
}
std::string RejectMessage::as_string()
{
   return "{\"type\": \"REJECT\", \"product\": \"" + this->product =
              "\", \"error\": \"" + this->error +
              "\", \"sequence\": " + std::to_string(this->sequence) +
              ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
}
TradeMessage::TradeMessage(MessageTypes type, std::string product, double price,
@@ -305,11 +410,35 @@
{
}
std::string TradeMessage::as_string()
{
   return "{\"type\": \"TRADE\", \"product\": \"" + this->product +
          "\", \"price\": " + std::to_string(this->price) +
          ", \"volume\": " + std::to_string(this->volume) + ", \"buyer\": \"" +
          this->buyer + "\", \"seller\": \"" + this->seller +
          "\", \"tradeType\": \"" + mapTTStr[this->tradeType] +
          "\", \"passiveOrder\": \"" + this->passiveOrder +
          "\", \"passoveOrderRemaining\": " +
          std::to_string(this->passiveOrderRemaining) +
          "\", \"sequence\": " + std::to_string(this->sequence) +
          ", \"timestamp\": " + std::to_string(this->timestamp) + "}";
}
BrokerRequest::BrokerRequest(MessageTypes type, std::string product,
                             double price, book::OrderSideEnum side,
                             uint64_t volume, std::string counterparty)
   : Broker(type, product, price, side, volume, counterparty)
{
}
std::string BrokerRequest::as_string()
{
   return "{\"type\": \"" + mapAStr[this->type] =
              "\", \"product\": \"" + this->product +
              "\", \"price\": " + std::to_string(this->price) +
              ", \"side\": " + mapOrderSide[this->side] +
              ", \"volume\": " + std::to_string(this->volume) +
              ", \"counterparty\": \"" + this->counterparty + "\"}";
}
BrokerAck::BrokerAck(MessageTypes type, std::string product, double price,
@@ -321,6 +450,19 @@
{
}
std::string BrokerAck::as_string()
{
   return "{\"type\": \"" + mapAStr[this->type] =
              "\", \"product\": \"" + this->product +
              "\", \"price\": " + std::to_string(this->price) +
              ", \"side\": " + mapOrderSide[this->side] +
              ", \"volume\": " + std::to_string(this->volume) +
              ", \"counterparty\": \"" + this->counterparty + +"\", \"id\"" +
              this->id +
              "\", \"brokerTradeStatus\": " + this->brokerTradeStatus +
              "\", \"owner\": \"" + this->owner + "\"}";
}
BrokerConfirm::BrokerConfirm(MessageTypes type, std::string product,
                             double price, book::OrderSideEnum side,
                             uint64_t volume, std::string counterparty,
@@ -328,4 +470,16 @@
   : Broker(type, product, price, side, volume, counterparty), id(id)
{
}
std::string BrokerConfirm::as_string()
{
   return "{\"type\": \"" + mapAStr[this->type] =
              "\", \"product\": \"" + this->product +
              "\", \"price\": " + std::to_string(this->price) +
              ", \"side\": " + mapOrderSide[this->side] +
              ", \"volume\": " + std::to_string(this->volume) +
              ", \"counterparty\": \"" + this->counterparty +
              "\", \"id\": " + this->id + "\"}";
}
} // namespace json