Skip to content

Commit

Permalink
feat: add draft for rest query for trades, candlesticks, and market d…
Browse files Browse the repository at this point in the history
…epth - bybit
  • Loading branch information
cryptochassis committed Oct 6, 2023
1 parent a4c4d8e commit 8a68969
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 22 deletions.
2 changes: 1 addition & 1 deletion app/src/single_order_execution/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ int main(int argc, char** argv) {
eventHandler.promisePtr = promisePtr;
#ifndef CCAPI_APP_IS_BACKTEST
SessionOptions sessionOptions;
sessionOptions.httpConnectionPoolIdleTimeoutMilliSeconds = 1;
sessionOptions.httpConnectionPoolIdleTimeoutMilliseconds = 1;
sessionOptions.httpMaxNumRetry = 0;
sessionOptions.httpMaxNumRedirect = 0;
SessionConfigs sessionConfigs;
Expand Down
83 changes: 81 additions & 2 deletions include/ccapi_cpp/service/ccapi_market_data_service_bybit.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
}
#endif
this->getRecentTradesTarget = "/spot/v3/public/quote/trades";
this->getHistoricalTradesTarget = "/spot/v3/public/quote/trades";
this->getRecentCandlesticksTarget = "/spot/v3/public/quote/kline";
this->getHistoricalCandlesticksTarget = "/spot/v3/public/quote/kline";
this->getMarketDepthTarget = "/spot/v3/public/quote/depth";
this->getInstrumentsTarget = "/spot/v3/public/symbols";
}
virtual ~MarketDataServiceBybit() {}
Expand Down Expand Up @@ -232,7 +236,8 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
case Request::Operation::GENERIC_PUBLIC_REQUEST: {
MarketDataService::convertRequestForRestGenericPublicRequest(req, request, now, symbolId, credential);
} break;
case Request::Operation::GET_RECENT_TRADES: {
case Request::Operation::GET_RECENT_TRADES:
case Request::Operation::GET_HISTORICAL_TRADES: {
req.method(http::verb::get);
auto target = this->getRecentTradesTarget;
std::string queryString;
Expand All @@ -244,6 +249,44 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
this->appendSymbolId(queryString, symbolId, "symbol");
req.target(target + "?" + queryString);
} break;
case Request::Operation::GET_RECENT_CANDLESTICKS:
case Request::Operation::GET_HISTORICAL_CANDLESTICKS: {
req.method(http::verb::get);
auto target = this->getRecentCandlesticksTarget;
std::string queryString;
const std::map<std::string, std::string> param = request.getFirstParamWithDefault();
this->appendParam(queryString, param,
{
{CCAPI_CANDLESTICK_INTERVAL_SECONDS, "interval"},
{CCAPI_LIMIT, "limit"},
{CCAPI_START_TIME_SECONDS, "startTime"},
{CCAPI_END_TIME_SECONDS, "endTime"},
},
{
{CCAPI_CANDLESTICK_INTERVAL_SECONDS,
[that = shared_from_base<MarketDataServiceBybit>()](const std::string& input) {
return that->convertCandlestickIntervalSecondsToInterval(std::stoi(input), "", "m", "h", "d", "w");
}},
{CCAPI_START_TIME_SECONDS, [that = shared_from_base<MarketDataServiceBybit>()](
const std::string& input) { return that->convertParamTimeSecondsToTimeMilliseconds(input); }},
{CCAPI_END_TIME_SECONDS, [that = shared_from_base<MarketDataServiceBybit>()](
const std::string& input) { return that->convertParamTimeSecondsToTimeMilliseconds(input); }},
});
this->appendSymbolId(queryString, symbolId, "symbol");
req.target(target + "?" + queryString);
} break;
case Request::Operation::GET_MARKET_DEPTH: {
req.method(http::verb::get);
auto target = this->getMarketDepthTarget;
std::string queryString;
const std::map<std::string, std::string> param = request.getFirstParamWithDefault();
this->appendParam(queryString, param,
{
{CCAPI_LIMIT, "limit"},
});
this->appendSymbolId(queryString, symbolId, "symbol");
req.target(target + "?" + queryString);
} break;
case Request::Operation::GET_INSTRUMENT: {
req.method(http::verb::get);
auto target = this->getInstrumentsTarget;
Expand Down Expand Up @@ -272,7 +315,8 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
rj::Document document;
document.Parse<rj::kParseNumbersAsStringsFlag>(textMessage.c_str());
switch (request.getOperation()) {
case Request::Operation::GET_RECENT_TRADES: {
case Request::Operation::GET_RECENT_TRADES:
case Request::Operation::GET_HISTORICAL_TRADES: {
for (const auto& x : document["result"]["list"].GetArray()) {
MarketDataMessage marketDataMessage;
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_TRADE;
Expand All @@ -285,6 +329,41 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
marketDataMessageList.emplace_back(std::move(marketDataMessage));
}
} break;
case Request::Operation::GET_RECENT_CANDLESTICKS:
case Request::Operation::GET_HISTORICAL_CANDLESTICKS: {
for (const auto& x : document["result"]["list"].GetArray()) {
MarketDataMessage marketDataMessage;
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_CANDLESTICK;
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(x["t"].GetString()));
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::OPEN_PRICE, x["o"].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::HIGH_PRICE, x["h"].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::LOW_PRICE, x["l"].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::CLOSE_PRICE, x["c"].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::VOLUME, x["v"].GetString()});
marketDataMessage.data[MarketDataMessage::DataType::CANDLESTICK].emplace_back(std::move(dataPoint));
marketDataMessageList.emplace_back(std::move(marketDataMessage));
}
} break;
case Request::Operation::GET_MARKET_DEPTH: {
MarketDataMessage marketDataMessage;
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_MARKET_DEPTH;
const rj::Value& result = document["result"];
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(result["time"].GetString()));
for (const auto& x : result["bids"].GetArray()) {
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, x[0].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, x[1].GetString()});
marketDataMessage.data[MarketDataMessage::DataType::BID].emplace_back(std::move(dataPoint));
}
for (const auto& x : result["asks"].GetArray()) {
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, x[0].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, x[1].GetString()});
marketDataMessage.data[MarketDataMessage::DataType::ASK].emplace_back(std::move(dataPoint));
}
marketDataMessageList.emplace_back(std::move(marketDataMessage));
} break;
case Request::Operation::GET_INSTRUMENT: {
Message message;
message.setTimeReceived(timeReceived);
Expand Down
113 changes: 103 additions & 10 deletions include/ccapi_cpp/service/ccapi_market_data_service_bybit_derivatives.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class MarketDataServiceBybitDerivatives : public MarketDataServiceBybitBase {
}
#endif
this->getRecentTradesTarget = "/derivatives/v3/public/recent-trade";
this->getHistoricalTradesTarget = "/derivatives/v3/public/recent-trade";
this->getRecentCandlesticksTarget = "/derivatives/v3/public/kline";
this->getHistoricalCandlesticksTarget = "/derivatives/v3/public/kline";
this->getMarketDepthTarget = "/derivatives/v3/public/order-book/L2";
this->getInstrumentTarget = "/derivatives/v3/public/instruments-info";
this->getInstrumentsTarget = "/derivatives/v3/public/instruments-info";
}
Expand All @@ -51,6 +55,17 @@ class MarketDataServiceBybitDerivatives : public MarketDataServiceBybitBase {
url.replace(url.find(toReplace), toReplace.length(), instrumentTypeSubstitute);
return url;
}
std::string convertCandlestickIntervalSecondsToInterval(int intervalSeconds) {
std::string interval;
if (intervalSeconds < 86400) {
interval = std::to_string(intervalSeconds / 60);
} else if (intervalSeconds == 86400) {
interval = "D";
} else {
interval = "W";
}
return interval;
}
void prepareSubscriptionDetail(std::string& channelId, std::string& symbolId, const std::string& field, const WsConnection& wsConnection,
const Subscription& subscription, const std::map<std::string, std::string> optionMap) override {
const auto& marketDepthRequested = std::stoi(optionMap.at(CCAPI_MARKET_DEPTH_MAX));
Expand All @@ -67,15 +82,8 @@ class MarketDataServiceBybitDerivatives : public MarketDataServiceBybitBase {
channelId += std::string("?") + CCAPI_MARKET_DEPTH_SUBSCRIBED_TO_EXCHANGE + "=" + std::to_string(marketDepthSubscribedToExchange);
this->marketDepthSubscribedToExchangeByConnectionIdChannelIdSymbolIdMap[wsConnection.id][channelId][symbolId] = marketDepthSubscribedToExchange;
} else if (field == CCAPI_CANDLESTICK) {
std::string interval;
int intervalSeconds = std::stoi(optionMap.at(CCAPI_CANDLESTICK_INTERVAL_SECONDS));
if (intervalSeconds < 86400) {
interval = std::to_string(intervalSeconds / 60);
} else if (intervalSeconds == 86400) {
interval = "D";
} else {
interval = "W";
}
std::string interval = this->convertCandlestickIntervalSecondsToInterval(intervalSeconds);
std::string toReplace = "{interval}";
channelId.replace(channelId.find(toReplace), toReplace.length(), interval);
}
Expand Down Expand Up @@ -241,7 +249,8 @@ class MarketDataServiceBybitDerivatives : public MarketDataServiceBybitBase {
case Request::Operation::GENERIC_PUBLIC_REQUEST: {
MarketDataService::convertRequestForRestGenericPublicRequest(req, request, now, symbolId, credential);
} break;
case Request::Operation::GET_RECENT_TRADES: {
case Request::Operation::GET_RECENT_TRADES:
case Request::Operation::GET_HISTORICAL_TRADES: {
req.method(http::verb::get);
auto target = this->getRecentTradesTarget;
std::string queryString;
Expand All @@ -253,6 +262,44 @@ class MarketDataServiceBybitDerivatives : public MarketDataServiceBybitBase {
this->appendSymbolId(queryString, symbolId, "symbol");
req.target(target + "?" + queryString);
} break;
case Request::Operation::GET_RECENT_CANDLESTICKS:
case Request::Operation::GET_HISTORICAL_CANDLESTICKS: {
req.method(http::verb::get);
auto target = this->getRecentCandlesticksTarget;
std::string queryString;
const std::map<std::string, std::string> param = request.getFirstParamWithDefault();
this->appendParam(queryString, param,
{
{CCAPI_CANDLESTICK_INTERVAL_SECONDS, "interval"},
{CCAPI_LIMIT, "limit"},
{CCAPI_START_TIME_SECONDS, "start"},
{CCAPI_END_TIME_SECONDS, "end"},
},
{
{CCAPI_CANDLESTICK_INTERVAL_SECONDS,
[that = shared_from_base<MarketDataServiceBybitDerivatives>()](const std::string& input) {
return that->convertCandlestickIntervalSecondsToInterval(std::stoi(input));
}},
{CCAPI_START_TIME_SECONDS, [that = shared_from_base<MarketDataServiceBybitDerivatives>()](
const std::string& input) { return that->convertParamTimeSecondsToTimeMilliseconds(input); }},
{CCAPI_END_TIME_SECONDS, [that = shared_from_base<MarketDataServiceBybitDerivatives>()](
const std::string& input) { return that->convertParamTimeSecondsToTimeMilliseconds(input); }},
});
this->appendSymbolId(queryString, symbolId, "symbol");
req.target(target + "?" + queryString);
} break;
case Request::Operation::GET_MARKET_DEPTH: {
req.method(http::verb::get);
auto target = this->getMarketDepthTarget;
std::string queryString;
const std::map<std::string, std::string> param = request.getFirstParamWithDefault();
this->appendParam(queryString, param,
{
{CCAPI_LIMIT, "limit"},
});
this->appendSymbolId(queryString, symbolId, "symbol");
req.target(target + "?" + queryString);
} break;
case Request::Operation::GET_INSTRUMENT: {
req.method(http::verb::get);
auto target = this->getInstrumentTarget;
Expand Down Expand Up @@ -299,7 +346,8 @@ class MarketDataServiceBybitDerivatives : public MarketDataServiceBybitBase {
rj::Document document;
document.Parse<rj::kParseNumbersAsStringsFlag>(textMessage.c_str());
switch (request.getOperation()) {
case Request::Operation::GET_RECENT_TRADES: {
case Request::Operation::GET_RECENT_TRADES:
case Request::Operation::GET_HISTORICAL_TRADES: {
for (const auto& x : document["result"]["list"].GetArray()) {
MarketDataMessage marketDataMessage;
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_TRADE;
Expand All @@ -313,6 +361,51 @@ class MarketDataServiceBybitDerivatives : public MarketDataServiceBybitBase {
marketDataMessageList.emplace_back(std::move(marketDataMessage));
}
} break;
case Request::Operation::GET_RECENT_CANDLESTICKS:
case Request::Operation::GET_HISTORICAL_CANDLESTICKS: {
for (const auto& x : document["result"]["list"].GetArray()) {
MarketDataMessage marketDataMessage;
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_CANDLESTICK;
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(x[0].GetString()));
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::OPEN_PRICE, x[1].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::HIGH_PRICE, x[2].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::LOW_PRICE, x[3].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::CLOSE_PRICE, x[4].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::VOLUME, x[5].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::QUOTE_VOLUME, x[6].GetString()});
marketDataMessage.data[MarketDataMessage::DataType::CANDLESTICK].emplace_back(std::move(dataPoint));
marketDataMessageList.emplace_back(std::move(marketDataMessage));
}
} break;
case Request::Operation::GET_MARKET_DEPTH: {
MarketDataMessage marketDataMessage;
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_MARKET_DEPTH;
CCAPI_LOGGER_TRACE("");
const rj::Value& result = document["result"];
CCAPI_LOGGER_TRACE("");
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(result["ts"].GetString()));
CCAPI_LOGGER_TRACE("");
for (const auto& x : result["b"].GetArray()) {
CCAPI_LOGGER_TRACE("");
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, x[0].GetString()});
CCAPI_LOGGER_TRACE("");
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, x[1].GetString()});
CCAPI_LOGGER_TRACE("");
marketDataMessage.data[MarketDataMessage::DataType::BID].emplace_back(std::move(dataPoint));
}
for (const auto& x : result["a"].GetArray()) {
CCAPI_LOGGER_TRACE("");
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, x[0].GetString()});
CCAPI_LOGGER_TRACE("");
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, x[1].GetString()});
CCAPI_LOGGER_TRACE("");
marketDataMessage.data[MarketDataMessage::DataType::ASK].emplace_back(std::move(dataPoint));
}
marketDataMessageList.emplace_back(std::move(marketDataMessage));
} break;
case Request::Operation::GET_INSTRUMENT: {
Message message;
message.setTimeReceived(timeReceived);
Expand Down
9 changes: 0 additions & 9 deletions include/ccapi_cpp/service/ccapi_market_data_service_okx.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,27 +446,18 @@ class MarketDataServiceOkx : public MarketDataService {
case Request::Operation::GET_MARKET_DEPTH: {
MarketDataMessage marketDataMessage;
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_MARKET_DEPTH;
CCAPI_LOGGER_DEBUG("");
const rj::Value& data = document["data"][0];
CCAPI_LOGGER_DEBUG("");
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(data["ts"].GetString()));
CCAPI_LOGGER_DEBUG("");
for (const auto& x : data["bids"].GetArray()) {
CCAPI_LOGGER_DEBUG("");
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, x[0].GetString()});
CCAPI_LOGGER_DEBUG("");
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, x[1].GetString()});
CCAPI_LOGGER_DEBUG("");
marketDataMessage.data[MarketDataMessage::DataType::BID].emplace_back(std::move(dataPoint));
}
for (const auto& x : data["asks"].GetArray()) {
CCAPI_LOGGER_DEBUG("");
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, x[0].GetString()});
CCAPI_LOGGER_DEBUG("");
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, x[1].GetString()});
CCAPI_LOGGER_DEBUG("");
marketDataMessage.data[MarketDataMessage::DataType::ASK].emplace_back(std::move(dataPoint));
}
marketDataMessageList.emplace_back(std::move(marketDataMessage));
Expand Down

0 comments on commit 8a68969

Please sign in to comment.