#include "json.hpp" #include "book.hpp" #include "date/include/date/date.h" #include "protocol.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace json { static std::unordered_map mapTypes; static std::unordered_map mapAnnounce; static std::unordered_map mapOrder; static std::unordered_map mapTrade; static std::unordered_map mapOrderSide; void initialise() { mapTypes = {{"FUTURE", FUTURE_TYPE}, {"SPREAD", SPREAD_TYPE}, {"CALL", CALL_TYPE}, {"PUT", PUT_TYPE}, {"SETTLEMENT", SETTLEMENT}, {"ADDED", ADDED}, {"DELETED", DELETED}, {"TRADE", TRADE}, {"BROKER_REQUEST", BROKER_REQUEST}, {"BROKER_ACK", BROKER_ACK}, {"BROKER_CONFIRM", BROKER_CONFIRM}}; mapAnnounce = {{FUTURE_TYPE, book::FUTURE}, {SPREAD_TYPE, book::SPREAD}, {CALL_TYPE, book::CALL}, {PUT_TYPE, book::PUT}}; mapOrder = {{"BUY", book::Buy}, {"SELL", book::Sell}}; mapTrade = {{"BUY_AGGRESSOR", BUY_AGGRESSOR}, {"SELL_AGGRESSOR", SELL_AGGRESSOR}}; mapOrderSide = {{book::Buy, "BUY"}, {book::Sell, "SELL"}}; } AnnounceMessage* announce(std::string& str); SettleMessage* settle(std::string& str); AddedMessage* added(std::string& str); DeletedMessage* deleted(std::string& str); TradeMessage* trade(std::string& str); BrokerRequest* brokerReq(std::string& str); BrokerAck* brokerAck(std::string& str); BrokerConfirm* brokerCon(std::string& str); std::queue parseMany(std::string& str) { std::queue out; std::size_t startIndex = 0, endIndex = 0; while (true) { startIndex = str.find("{", endIndex); if (startIndex == std::string::npos) break; endIndex = str.find("},", startIndex); std::string substr = str.substr(startIndex, endIndex - startIndex + 1); // std::cout << substr << std::endl; Message* a = parseSingle(substr); out.push(a); } return out; } Message* parseSingle(std::string& str) { if (mapTypes.empty()) { initialise(); } std::size_t startIndex = str.find("\"type\": \"") + 9; std::size_t endIndex = str.find("\"", startIndex + 1); Message* out; switch (mapTypes[str.substr(startIndex, endIndex - startIndex)]) { case FUTURE_TYPE: case SPREAD_TYPE: case CALL_TYPE: case PUT_TYPE: out = announce(str); break; case SETTLEMENT: out = settle(str); break; case ADDED: out = added(str); break; case DELETED: out = deleted(str); break; case TRADE: out = trade(str); break; case BROKER_REQUEST: out = brokerReq(str); break; case BROKER_ACK: out = brokerAck(str); break; case BROKER_CONFIRM: out = brokerCon(str); break; default: out = new Message(NONE, ""); break; } return out; } inline std::pair find_arg(std::string str, std::string a, bool quotes, bool end = false) { std::size_t out[2]; if (quotes) { out[0] = str.find("\"" + a + "\": \"") + 5 + a.size(); if (end) { out[1] = str.find("\"}", out[0] + 1); } else { out[1] = str.find("\",", out[0] + 1); } } else { out[0] = str.find("\"" + a + "\": ") + 4 + a.size(); if (end) { out[1] = str.find("}", out[0] + 1); } else { out[1] = str.find(",", out[0] + 1); } } return std::make_pair(out[0], out[1]); } AnnounceMessage* announce(std::string& str) { std::pair type, product, stationId, stationName, unit, expiry, aggFee, pasFee, broFee, sequence, timestamp; type = find_arg(str, "type", true, false); product = find_arg(str, "product", true, false); stationId = find_arg(str, "stationId", false, false); stationName = find_arg(str, "stationName", true, false); unit = find_arg(str, "unit", true, false); expiry = find_arg(str, "expiry", true, false); aggFee = find_arg(str, "aggressiveFee", false, false); pasFee = find_arg(str, "passiveFee", false, false); broFee = find_arg(str, "brokerFee", false, false); sequence = find_arg(str, "sequence", false, false); timestamp = find_arg(str, "timestamp", false, true); std::stringstream expiryStream( str.substr(expiry.first, expiry.second - expiry.first)); std::chrono::nanoseconds exp_time; expiryStream >> date::parse("%Y-%m-%f %H:%M%z", exp_time); // Parsing is broken return new AnnounceMessage( mapTypes[str.substr(type.first, type.second - type.first)], str.substr(product.first, product.second - product.first), str.substr(stationId.first, stationId.second - stationId.first), str.substr(stationName.first, stationName.second - stationName.first), str.substr(unit.first, unit.second - unit.first), exp_time, std::stod(str.substr(aggFee.first, aggFee.second - aggFee.first)), std::stod(str.substr(pasFee.first, pasFee.second - pasFee.first)), std::stod(str.substr(broFee.first, broFee.second - broFee.first)), std::stoll( str.substr(sequence.first, sequence.second - sequence.first)), std::stod( str.substr(timestamp.first, timestamp.second - timestamp.first))); } SettleMessage* settle(std::string& str) { std::pair type, product, stationName, expiry, price, sequence, timestamp; type = find_arg(str, "type", true, false); product = find_arg(str, "product", true, false); stationName = find_arg(str, "stationName", true, false); expiry = find_arg(str, "expiry", true, false); price = find_arg(str, "price", false, false); sequence = find_arg(str, "sequence", false, false); timestamp = find_arg(str, "timestamp", false, true); std::stringstream expiryStream( str.substr(expiry.first, expiry.second - expiry.first)); std::chrono::nanoseconds exp_time; expiryStream >> date::parse("%Y-%m-%d %H:%M%z", exp_time); return new SettleMessage( mapTypes[str.substr(type.first, type.second - type.first)], str.substr(product.first, product.second - product.first), str.substr(stationName.first, stationName.second - stationName.first), exp_time, std::stod(str.substr(price.first, price.second - price.first)), std::stoll( str.substr(sequence.first, sequence.second - sequence.first)), std::stod( str.substr(timestamp.first, timestamp.second - timestamp.first))); } AddedMessage* added(std::string& str) { std::pair type, product, id, side, price, filled, resting, sequence, timestamp; type = find_arg(str, "type", true, false); product = find_arg(str, "product", true, false); sequence = find_arg(str, "sequence", false, false); timestamp = find_arg(str, "timestamp", false, true); id = find_arg(str, "id", true, false); side = find_arg(str, "side", true, false); price = find_arg(str, "price", false, false); filled = find_arg(str, "filled", false, false); resting = find_arg(str, "resting", false, false); return new AddedMessage( mapTypes[str.substr(type.first, type.second - type.first)], str.substr(product.first, product.second - product.first), str.substr(id.first, id.second - id.first), mapOrder[str.substr(side.first, side.second - side.first)], std::stod(str.substr(price.first, price.second - price.first)), std::stoll(str.substr(filled.first, filled.second - filled.first)), std::stoll(str.substr(resting.first, resting.second - resting.first)), std::stoll( str.substr(sequence.first, sequence.second - sequence.first)), std::stod( str.substr(timestamp.first, timestamp.second - timestamp.first))); } DeletedMessage* deleted(std::string& str) { std::pair type, product, id, side, sequence, timestamp; type = find_arg(str, "type", true, false); product = find_arg(str, "product", true, false); sequence = find_arg(str, "sequence", false, false); timestamp = find_arg(str, "timestamp", false, true); id = find_arg(str, "id", true, false); side = find_arg(str, "side", true, false); return new DeletedMessage( mapTypes[str.substr(type.first, type.second - type.first)], str.substr(product.first, product.second - product.first), str.substr(id.first, id.second - id.first), mapOrder[str.substr(side.first, side.second - side.first)], std::stoll( str.substr(sequence.first, sequence.second - sequence.first)), std::stod( str.substr(timestamp.first, timestamp.second - timestamp.first))); } TradeMessage* trade(std::string& str) { std::pair type, product, price, volume, buyer, seller, tradeType, passiveOrder, passiveOrderRemaining, sequence, timestamp; type = find_arg(str, "type", true, false); product = find_arg(str, "product", true, false); sequence = find_arg(str, "sequence", false, false); timestamp = find_arg(str, "timestamp", false, true); price = find_arg(str, "price", false, false); volume = find_arg(str, "volume", false, false); buyer = find_arg(str, "buyer", true, false); seller = find_arg(str, "seller", true, false); tradeType = find_arg(str, "tradeType", true, false); passiveOrder = find_arg(str, "passiveOrder", true, false); passiveOrderRemaining = find_arg(str, "passiveOrderRemaining", false, false); return new TradeMessage( mapTypes[str.substr(type.first, type.second - type.first)], str.substr(product.first, product.second - product.first), std::stod(str.substr(price.first, price.second - price.first)), std::stoll(str.substr(volume.first, volume.second - volume.first)), str.substr(buyer.first, buyer.second - buyer.first), str.substr(seller.first, seller.second - seller.first), mapTrade[str.substr(tradeType.first, tradeType.second - tradeType.first)], str.substr(passiveOrder.first, passiveOrder.second - passiveOrder.first), std::stoll(str.substr(passiveOrderRemaining.first, passiveOrderRemaining.second - passiveOrderRemaining.first)), std::stoll( str.substr(sequence.first, sequence.second - sequence.first)), std::stod( str.substr(timestamp.first, timestamp.second - timestamp.first))); } BrokerRequest* brokerReq(std::string& str) { std::pair type, product, price, side, volume, counterparty; type = find_arg(str, "type", true, false); product = find_arg(str, "product", true, false); price = find_arg(str, "price", false, false); side = find_arg(str, "side", true, false); volume = find_arg(str, "volume", false, false); counterparty = find_arg(str, "counterparty", true, false); return new BrokerRequest( mapTypes[str.substr(type.first, type.second - type.first)], str.substr(product.first, product.second - product.first), std::stod(str.substr(price.first, price.second - price.first)), mapOrder[str.substr(side.first, side.second - side.first)], std::stoll(str.substr(volume.first, volume.second - volume.first)), str.substr(counterparty.first, counterparty.second - counterparty.first)); } BrokerAck* brokerAck(std::string& str) { std::pair type, product, price, side, volume, counterparty, id, brokerTradeStatus, owner; type = find_arg(str, "type", true, false); product = find_arg(str, "product", true, false); price = find_arg(str, "price", false, false); side = find_arg(str, "side", true, false); volume = find_arg(str, "volume", false, false); counterparty = find_arg(str, "counterparty", true, false); id = find_arg(str, "id", true, false); brokerTradeStatus = find_arg(str, "brokerTradeStatus", true, false); owner = find_arg(str, "owner", true, false); return new BrokerAck( mapTypes[str.substr(type.first, type.second - type.first)], str.substr(product.first, product.second - product.first), std::stod(str.substr(price.first, price.second - price.first)), mapOrder[str.substr(side.first, side.second - side.first)], std::stoll(str.substr(volume.first, volume.second - volume.first)), str.substr(counterparty.first, counterparty.second - counterparty.first), str.substr(id.first, id.second - id.first), str.substr(brokerTradeStatus.first, brokerTradeStatus.second - brokerTradeStatus.first), str.substr(owner.first, owner.second - owner.first)); } BrokerConfirm* brokerCon(std::string& str) { std::pair type, product, price, side, volume, counterparty, id; type = find_arg(str, "type", true, false); product = find_arg(str, "product", true, false); price = find_arg(str, "price", false, false); side = find_arg(str, "side", true, false); volume = find_arg(str, "volume", false, false); counterparty = find_arg(str, "counterparty", true, false); id = find_arg(str, "id", true, false); return new BrokerConfirm( mapTypes[str.substr(type.first, type.second - type.first)], str.substr(product.first, product.second - product.first), std::stod(str.substr(price.first, price.second - price.first)), mapOrder[str.substr(side.first, side.second - side.first)], std::stoll(str.substr(volume.first, volume.second - volume.first)), str.substr(counterparty.first, counterparty.second - counterparty.first), str.substr(id.first, id.second - id.first)); } Message::Message() : type(NONE), product("error") {} Message::Message(MessageTypes types, std::string product) : type(types), product(product) { } FromExchange::FromExchange(MessageTypes type, std::string product, uint64_t sequence, double timestamp) : Message(type, product), sequence(sequence), timestamp(timestamp) { } ToExchange::ToExchange(MessageTypes type, std::string product) : Message(type, product){}; Broker::Broker(MessageTypes type, std::string product, double price, book::OrderSideEnum side, uint64_t volume, std::string counterparty) : Message(type, product), price(price), side(side), volume(volume), counterparty(counterparty) { } AnnounceMessage::AnnounceMessage(MessageTypes type, std::string product, std::string stationId, std::string stationName, std::string unit, std::chrono::nanoseconds expiry, double aggFee, double pasFee, double broFee, uint64_t sequence, double timestamp) : FromExchange(type, product, sequence, timestamp), stationId(stationId), stationName(stationName), unit(unit), expiry(expiry), aggFee(aggFee), pasFee(pasFee), broFee(broFee) { } SettleMessage::SettleMessage(MessageTypes type, std::string product, std::string stationName, std::chrono::nanoseconds expiry, double price, uint64_t sequence, double timestamp) : FromExchange(type, product, sequence, timestamp), stationName(stationName), expiry(expiry), price(price) { } AddMessage::AddMessage(MessageTypes type, std::string product, double price, book::OrderSideEnum side, uint64_t volume) : ToExchange(type, product), price(price), side(side), volume(volume) { } std::string AddMessage::as_string() { if (mapOrderSide.empty()) initialise(); return "{\"type\": \"ADD\", \"product\": \"" + this->product + "\", \"price\": " + std::to_string(this->price) + ", \"side\": \"" + mapOrderSide[this->side] + "\", \"volume\": " + std::to_string(this->volume) + "}"; } 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) : FromExchange(type, product, sequence, timestamp), id(id), side(side), price(price), filled(filled), resting(resting) { } DeleteMessage::DeleteMessage(MessageTypes type, std::string product, std::string id) : ToExchange(type, product), id(id) { } std::string DeleteMessage::as_string() { if (mapOrderSide.empty()) initialise(); return "{\"type\": \"DELETE\", \"product\": \"" + this->product + "\", \"id\": \"" + this->id + "\"}"; } DeletedMessage::DeletedMessage(MessageTypes type, std::string product, std::string id, book::OrderSideEnum side, uint64_t sequence, double timestamp) : FromExchange(type, product, sequence, timestamp), id(id), side(side) { } RejectMessage::RejectMessage(MessageTypes type, std::string product, std::string error, uint64_t sequence, double timestamp) : FromExchange(type, product, sequence, timestamp), error(error) { } TradeMessage::TradeMessage(MessageTypes type, std::string product, double price, uint64_t volume, std::string buyer, std::string seller, TradeTypeEnum tradeType, std::string passiveOrder, uint64_t passiveOrderRemaining, uint64_t sequence, double timestamp) : FromExchange(type, product, sequence, timestamp), price(price), volume(volume), buyer(buyer), seller(seller), tradeType(tradeType), passiveOrder(passiveOrder), passiveOrderRemaining(passiveOrderRemaining) { } 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) { } BrokerAck::BrokerAck(MessageTypes type, std::string product, double price, book::OrderSideEnum side, uint64_t volume, std::string counterparty, std::string id, std::string brokerTradeStatus, std::string owner) : Broker(type, product, price, side, volume, counterparty), id(id), brokerTradeStatus(brokerTradeStatus), owner(owner) { } BrokerConfirm::BrokerConfirm(MessageTypes type, std::string product, double price, book::OrderSideEnum side, uint64_t volume, std::string counterparty, std::string id) : Broker(type, product, price, side, volume, counterparty), id(id) { } } // namespace json