Joel Grunbaum
2022-01-09 b4cf0a2e71ad2c204925b33f9600dc720e25b827
Initial shift to rapidjson
1 files added
7 files modified
346 ■■■■ changed files
.gitmodules 3 ●●●●● patch | view | raw | blame | history
CMakeLists.txt 6 ●●●● patch | view | raw | blame | history
book.cpp 4 ●●●● patch | view | raw | blame | history
book.hpp 4 ●●●● patch | view | raw | blame | history
json.cpp 316 ●●●● patch | view | raw | blame | history
json.hpp 7 ●●●●● patch | view | raw | blame | history
protocol.cpp 5 ●●●●● patch | view | raw | blame | history
rapidjson @ fd3dc2 1 ●●●● patch | view | raw | blame | history
.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
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)
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),
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);
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,
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
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
rapidjson
New file
@@ -0,0 +1 @@
Subproject commit fd3dc29a5c2852df569e1ea81dbde2c412ac5051