From b4cf0a2e71ad2c204925b33f9600dc720e25b827 Mon Sep 17 00:00:00 2001 From: Joel Grunbaum <joelgrun@gmail.com> Date: Sun, 09 Jan 2022 23:22:58 +0000 Subject: [PATCH] Initial shift to rapidjson --- rapidjson | 1 .gitmodules | 3 book.cpp | 4 json.hpp | 7 book.hpp | 4 json.cpp | 316 ++++++++++++--------------------------------------- protocol.cpp | 5 CMakeLists.txt | 6 8 files changed, 96 insertions(+), 250 deletions(-) diff --git a/.gitmodules b/.gitmodules index d553919..c935847 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "date"] path = date url = https://github.com/HowardHinnant/date.git +[submodule "rapidjson"] + path = rapidjson + url = https://github.com/Tencent/rapidjson.git diff --git a/CMakeLists.txt b/CMakeLists.txt index c086558..94cf3a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,8 +8,12 @@ add_compile_options(-g -Wall) add_subdirectory(date) +# add_subdirectory(rapidjson) -add_library(MAIN json.cpp date protocol.cpp book.cpp) +add_library(JSON json.cpp) + +add_library(MAIN date protocol.cpp book.cpp) +target_link_libraries(MAIN PUBLIC JSON) add_executable(test test.cpp strat.cpp) add_executable(bot bot.cpp strat.cpp) diff --git a/book.cpp b/book.cpp index ee014ed..381a7a2 100644 --- a/book.cpp +++ b/book.cpp @@ -74,14 +74,14 @@ } Book::Book() - : bidSide(), askSide(), productType(TEST), product("a"), stationId("b"), + : bidSide(), askSide(), productType(TEST), product("a"), stationId(7), unit("c"), expiry(std::chrono::nanoseconds(0)), aggFee(1), pasFee(-1), broFee(2) { } Book::Book(ProductTypeEnum productType, std::string product, - std::string stationId, std::string unit, + int stationId, std::string unit, std::chrono::nanoseconds expiry, double aggFee, double pasFee, double broFee) : bidSide{}, askSide{}, productType{productType}, product(product), diff --git a/book.hpp b/book.hpp index 2240290..455506b 100644 --- a/book.hpp +++ b/book.hpp @@ -46,7 +46,7 @@ std::vector<Level> askSide; ProductTypeEnum productType; std::string product; - std::string stationId; + int stationId; std::string unit; std::chrono::nanoseconds expiry; double aggFee; @@ -55,7 +55,7 @@ Book(); Book(ProductTypeEnum productType, std::string product, - std::string stationId, std::string unit, + int stationId, std::string unit, std::chrono::nanoseconds expiry, double aggFee, double pasFee, double broFee); void ask(Order& order); diff --git a/json.cpp b/json.cpp index 11a97fa..5fbc996 100644 --- a/json.cpp +++ b/json.cpp @@ -2,6 +2,8 @@ #include "book.hpp" #include "date/include/date/date.h" #include "protocol.hpp" +#include "rapidjson/include/rapidjson/document.h" +#include "rapidjson/include/rapidjson/rapidjson.h" #include <chrono> #include <cstddef> #include <cstdint> @@ -51,66 +53,64 @@ 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); +Message* parseSingle(rapidjson::Value& d); +AnnounceMessage* announce(rapidjson::Value& d); +SettleMessage* settle(rapidjson::Value& d); +AddedMessage* added(rapidjson::Value& d); +DeletedMessage* deleted(rapidjson::Value& d); +TradeMessage* trade(rapidjson::Value& d); +BrokerRequest* brokerReq(rapidjson::Value& d); +BrokerAck* brokerAck(rapidjson::Value& d); +BrokerConfirm* brokerCon(rapidjson::Value& d); -std::queue<Message*> parseMany(std::string& str) +std::queue<Message*> parse(std::string& str) { std::queue<Message*> 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); + rapidjson::Document d; + d.Parse(str.c_str()); + if (d.IsArray()) { + for (rapidjson::SizeType i = 0; i < d.Size(); i++) { + out.push(parseSingle(d[i])); + } + } else { + out.push(parseSingle(d)); } return out; } -Message* parseSingle(std::string& str) +Message* parseSingle(rapidjson::Value& d) { 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)]) { + switch (mapTypes[d["type"].GetString()]) { case FUTURE_TYPE: case SPREAD_TYPE: case CALL_TYPE: case PUT_TYPE: - out = announce(str); + out = announce(d); break; case SETTLEMENT: - out = settle(str); + out = settle(d); break; case ADDED: - out = added(str); + out = added(d); break; case DELETED: - out = deleted(str); + out = deleted(d); break; case TRADE: - out = trade(str); + out = trade(d); break; case BROKER_REQUEST: - out = brokerReq(str); + out = brokerReq(d); break; case BROKER_ACK: - out = brokerAck(str); + out = brokerAck(d); break; case BROKER_CONFIRM: - out = brokerCon(str); + out = brokerCon(d); break; default: out = new Message(NONE, ""); @@ -119,244 +119,82 @@ return out; } -inline std::pair<std::size_t, std::size_t> -find_arg(std::string str, std::string a, bool quotes, bool end = false) +AnnounceMessage* announce(rapidjson::Value& d) { - 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<std::size_t, std::size_t> 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::stringstream expiryStream(d["expiry"].GetString()); std::chrono::nanoseconds exp_time(0); // expiryStream >> - // date::parse("%Y-%m-%f %H:%M%z", exp_time); // Parsing is broken + // 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))); + mapTypes[d["type"].GetString()], d["product"].GetString(), + d["stationId"].GetInt(), d["stationName"].GetString(), + d["unit"].GetString(), exp_time, d["aggressiveFee"].GetDouble(), + d["passiveFee"].GetDouble(), d["brokerFee"].GetDouble(), + d["sequence"].GetInt(), d["timestamp"].GetDouble()); } -SettleMessage* settle(std::string& str) +SettleMessage* settle(rapidjson::Value& d) { - std::pair<std::size_t, std::size_t> 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); + // std::stringstream expiryStream(d["expiry"].GetString()); + std::chrono::nanoseconds exp_time(0); + // 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))); + mapTypes[d["type"].GetString()], d["product"].GetString(), + d["stationName"].GetString(), exp_time, d["price"].GetDouble(), + d["sequence"].GetInt(), d["timestamp"].GetDouble()); } -AddedMessage* added(std::string& str) +AddedMessage* added(rapidjson::Value& d) { - std::pair<std::size_t, std::size_t> 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))); + 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()); } -DeletedMessage* deleted(std::string& str) +DeletedMessage* deleted(rapidjson::Value& d) { - std::pair<std::size_t, std::size_t> 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))); + mapTypes[d["type"].GetString()], d["product"].GetString(), + d["id"].GetString(), mapOrder[d["side"].GetString()], + d["sequence"].GetInt(), d["timestamp"].GetDouble()); } -TradeMessage* trade(std::string& str) +TradeMessage* trade(rapidjson::Value& d) { - std::pair<std::size_t, std::size_t> 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))); + mapTypes[d["type"].GetString()], d["product"].GetString(), + d["price"].GetDouble(), d["volume"].GetInt(), d["buyer"].GetString(), + d["seller"].GetString(), mapTrade[d["tradeType"].GetString()], + d["passiveOrder"].GetString(), d["passiveOrderRemaining"].GetInt(), + d["sequence"].GetInt(), d["timestamp"].GetDouble()); } -BrokerRequest* brokerReq(std::string& str) +BrokerRequest* brokerReq(rapidjson::Value& d) { - std::pair<std::size_t, std::size_t> 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)); + mapTypes[d["type"].GetString()], d["product"].GetString(), + d["price"].GetDouble(), mapOrder[d["side"].GetString()], + d["volume"].GetInt(), d["counterparty"].GetString()); } -BrokerAck* brokerAck(std::string& str) +BrokerAck* brokerAck(rapidjson::Value& d) { - std::pair<std::size_t, std::size_t> 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)); + return new BrokerAck(mapTypes[d["type"].GetString()], + d["product"].GetString(), d["price"].GetDouble(), + mapOrder[d["side"].GetString()], d["volume"].GetInt(), + d["counterparty"].GetString(), d["id"].GetString(), + d["brokerTradeStatus"].GetString(), + d["owner"].GetString()); } -BrokerConfirm* brokerCon(std::string& str) +BrokerConfirm* brokerCon(rapidjson::Value& d) { - std::pair<std::size_t, std::size_t> 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)); + mapTypes[d["type"].GetString()], d["product"].GetString(), + d["price"].GetDouble(), mapOrder[d["side"].GetString()], + d["volume"].GetInt(), d["counterparty"].GetString(), + d["id"].GetString()); } Message::Message() : type(NONE), product("error") {} @@ -384,7 +222,7 @@ } AnnounceMessage::AnnounceMessage(MessageTypes type, std::string product, - std::string stationId, std::string stationName, + int stationId, std::string stationName, std::string unit, std::chrono::nanoseconds expiry, double aggFee, double pasFee, double broFee, diff --git a/json.hpp b/json.hpp index 5d1fc2b..19a4b68 100644 --- a/json.hpp +++ b/json.hpp @@ -62,7 +62,7 @@ }; struct AnnounceMessage : public FromExchange { - std::string stationId; + int stationId; std::string stationName; std::string unit; std::chrono::nanoseconds expiry; @@ -71,7 +71,7 @@ double broFee; AnnounceMessage(MessageTypes type, std::string product, - std::string stationId, std::string stationName, + int stationId, std::string stationName, std::string unit, std::chrono::nanoseconds expiry, double aggFee, double pasFee, double broFee, uint64_t sequence, double timestamp); @@ -164,6 +164,5 @@ std::string counterparty, std::string id); }; -Message* parseSingle(std::string& str); -std::queue<Message*> parseMany(std::string& str); +std::queue<Message*> parse(std::string& str); } // namespace json diff --git a/protocol.cpp b/protocol.cpp index a129985..604c725 100644 --- a/protocol.cpp +++ b/protocol.cpp @@ -37,7 +37,7 @@ // auto res = cli.Get("/recover"); std::string l; l = ss.str(); - std::queue<json::Message*> a(json::parseMany(l)); + std::queue<json::Message*> a(json::parse(l)); while (!a.empty()) { protocol::handleMessage(bs, a.front()); delete a.front(); @@ -166,7 +166,8 @@ json::Message* send(std::string& message) { auto res = cli.Post("/execution", message, "text/plain"); - return json::parseSingle(res->body); + std::queue<json::Message*> a = json::parse(res->body); + return a.front(); } } // namespace protocol diff --git a/rapidjson b/rapidjson new file mode 160000 index 0000000..fd3dc29 --- /dev/null +++ b/rapidjson @@ -0,0 +1 @@ +Subproject commit fd3dc29a5c2852df569e1ea81dbde2c412ac5051 -- Gitblit v1.9.3