Skip to content

Commit da349f2

Browse files
Merge pull request #468 from obergaba/develop
Updated REST APIs for Bybit spot market services from v3 to v5
2 parents a43bae1 + 491f0cb commit da349f2

File tree

1 file changed

+54
-34
lines changed

1 file changed

+54
-34
lines changed

include/ccapi_cpp/service/ccapi_market_data_service_bybit.h

+54-34
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,29 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
2727
// CCAPI_LOGGER_FATAL(std::string("e.what() = ") + e.what());
2828
// }
2929
// #endif
30-
this->getRecentTradesTarget = "/spot/v3/public/quote/trades";
31-
this->getHistoricalTradesTarget = "/spot/v3/public/quote/trades";
32-
this->getRecentCandlesticksTarget = "/spot/v3/public/quote/kline";
33-
this->getHistoricalCandlesticksTarget = "/spot/v3/public/quote/kline";
34-
this->getMarketDepthTarget = "/spot/v3/public/quote/depth";
35-
this->getInstrumentsTarget = "/spot/v3/public/symbols";
30+
this->getRecentTradesTarget = "/v5/market/recent-trade";
31+
// this->getHistoricalTradesTarget = "/spot/v3/public/quote/trades";
32+
this->getRecentCandlesticksTarget = "/v5/market/kline";
33+
// this->getHistoricalCandlesticksTarget = "/spot/v3/public/quote/kline";
34+
this->getMarketDepthTarget = "/v5/market/orderbook";
35+
this->getInstrumentsTarget = "/v5/market/instruments-info";
3636
}
3737
virtual ~MarketDataServiceBybit() {}
3838
#ifndef CCAPI_EXPOSE_INTERNAL
3939

4040
protected:
4141
#endif
42+
std::string convertCandlestickIntervalSecondsToInterval(int intervalSeconds) {
43+
std::string interval;
44+
if (intervalSeconds < 86400) {
45+
interval = std::to_string(intervalSeconds / 60);
46+
} else if (intervalSeconds == 86400) {
47+
interval = "D";
48+
} else {
49+
interval = "W";
50+
}
51+
return interval;
52+
}
4253
void prepareSubscriptionDetail(std::string& channelId, std::string& symbolId, const std::string& field, const WsConnection& wsConnection,
4354
const Subscription& subscription, const std::map<std::string, std::string> optionMap) override {
4455
auto marketDepthRequested = std::stoi(optionMap.at(CCAPI_MARKET_DEPTH_MAX));
@@ -49,8 +60,8 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
4960
channelId = CCAPI_WEBSOCKET_BYBIT_CHANNEL_DEPTH;
5061
}
5162
} else if (field == CCAPI_CANDLESTICK) {
52-
std::string interval =
53-
this->convertCandlestickIntervalSecondsToInterval(std::stoi(optionMap.at(CCAPI_CANDLESTICK_INTERVAL_SECONDS)), "s", "m", "h", "d", "w");
63+
int intervalSeconds = std::stoi(optionMap.at(CCAPI_CANDLESTICK_INTERVAL_SECONDS));
64+
std::string interval = this->convertCandlestickIntervalSecondsToInterval(intervalSeconds);
5465
std::string toReplace = "{interval}";
5566
channelId.replace(channelId.find(toReplace), toReplace.length(), interval);
5667
}
@@ -245,6 +256,7 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
245256
this->appendParam(queryString, param,
246257
{
247258
{CCAPI_LIMIT, "limit"},
259+
{CCAPI_INSTRUMENT_TYPE, "category"},
248260
});
249261
this->appendSymbolId(queryString, symbolId, "symbol");
250262
req.target(target + "?" + queryString);
@@ -259,13 +271,14 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
259271
{
260272
{CCAPI_CANDLESTICK_INTERVAL_SECONDS, "interval"},
261273
{CCAPI_LIMIT, "limit"},
262-
{CCAPI_START_TIME_SECONDS, "startTime"},
263-
{CCAPI_END_TIME_SECONDS, "endTime"},
274+
{CCAPI_START_TIME_SECONDS, "start"},
275+
{CCAPI_END_TIME_SECONDS, "end"},
276+
{CCAPI_INSTRUMENT_TYPE, "category"},
264277
},
265278
{
266279
{CCAPI_CANDLESTICK_INTERVAL_SECONDS,
267280
[that = shared_from_base<MarketDataServiceBybit>()](const std::string& input) {
268-
return that->convertCandlestickIntervalSecondsToInterval(std::stoi(input), "", "m", "h", "d", "w");
281+
return that->convertCandlestickIntervalSecondsToInterval(std::stoi(input));
269282
}},
270283
{CCAPI_START_TIME_SECONDS, [that = shared_from_base<MarketDataServiceBybit>()](
271284
const std::string& input) { return that->convertParamTimeSecondsToTimeMilliseconds(input); }},
@@ -283,32 +296,37 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
283296
this->appendParam(queryString, param,
284297
{
285298
{CCAPI_LIMIT, "limit"},
299+
{CCAPI_INSTRUMENT_TYPE, "category"},
286300
});
287301
this->appendSymbolId(queryString, symbolId, "symbol");
288302
req.target(target + "?" + queryString);
289303
} break;
290-
case Request::Operation::GET_INSTRUMENT: {
291-
req.method(http::verb::get);
292-
auto target = this->getInstrumentsTarget;
293-
req.target(target);
294-
} break;
304+
case Request::Operation::GET_INSTRUMENT:
295305
case Request::Operation::GET_INSTRUMENTS: {
296306
req.method(http::verb::get);
297307
auto target = this->getInstrumentsTarget;
298-
req.target(target);
308+
std::string queryString;
309+
const std::map<std::string, std::string> param = request.getFirstParamWithDefault();
310+
this->appendParam(queryString, param,
311+
{
312+
{CCAPI_LIMIT, "limit"},
313+
{CCAPI_INSTRUMENT_TYPE, "category"},
314+
});
315+
this->appendSymbolId(queryString, symbolId, "symbol");
316+
req.target(target + "?" + queryString);
299317
} break;
300318
default:
301319
this->convertRequestForRestCustom(req, request, now, symbolId, credential);
302320
}
303321
}
304322
void extractInstrumentInfo(Element& element, const rj::Value& x) {
305-
element.insert(CCAPI_INSTRUMENT, x["name"].GetString());
323+
element.insert(CCAPI_INSTRUMENT, x["symbol"].GetString());
306324
element.insert(CCAPI_BASE_ASSET, x["baseCoin"].GetString());
307325
element.insert(CCAPI_QUOTE_ASSET, x["quoteCoin"].GetString());
308-
element.insert(CCAPI_ORDER_PRICE_INCREMENT, x["minPricePrecision"].GetString());
309-
element.insert(CCAPI_ORDER_QUANTITY_INCREMENT, x["basePrecision"].GetString());
310-
element.insert(CCAPI_ORDER_QUANTITY_MIN, x["minTradeQty"].GetString());
311-
element.insert(CCAPI_ORDER_PRICE_TIMES_QUANTITY_MIN, x["minTradeAmt"].GetString());
326+
element.insert(CCAPI_ORDER_PRICE_INCREMENT, x["priceFilter"]["tickSize"].GetString());
327+
element.insert(CCAPI_ORDER_QUANTITY_INCREMENT, x["lotSizeFilter"]["basePrecision"].GetString());
328+
element.insert(CCAPI_ORDER_QUANTITY_MIN, x["lotSizeFilter"]["minOrderQty"].GetString());
329+
element.insert(CCAPI_ORDER_PRICE_TIMES_QUANTITY_MIN, x["lotSizeFilter"]["minOrderAmt"].GetString());
312330
}
313331
void convertTextMessageToMarketDataMessage(const Request& request, const std::string& textMessage, const TimePoint& timeReceived, Event& event,
314332
std::vector<MarketDataMessage>& marketDataMessageList) override {
@@ -323,8 +341,9 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
323341
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(x["time"].GetString()));
324342
MarketDataMessage::TypeForDataPoint dataPoint;
325343
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalString(std::string(x["price"].GetString()))});
326-
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString(std::string(x["qty"].GetString()))});
327-
dataPoint.insert({MarketDataMessage::DataFieldType::IS_BUYER_MAKER, x["isBuyerMaker"].GetString() ? "0" : "1"});
344+
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString(std::string(x["size"].GetString()))});
345+
dataPoint.insert({MarketDataMessage::DataFieldType::TRADE_ID, std::string(x["execId"].GetString())});
346+
dataPoint.insert({MarketDataMessage::DataFieldType::IS_BUYER_MAKER, std::string(x["side"].GetString()) == "buy" ? "1" : "0"});
328347
marketDataMessage.data[MarketDataMessage::DataType::TRADE].emplace_back(std::move(dataPoint));
329348
marketDataMessageList.emplace_back(std::move(marketDataMessage));
330349
}
@@ -334,13 +353,14 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
334353
for (const auto& x : document["result"]["list"].GetArray()) {
335354
MarketDataMessage marketDataMessage;
336355
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_CANDLESTICK;
337-
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(x["t"].GetString()));
356+
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(x[0].GetString()));
338357
MarketDataMessage::TypeForDataPoint dataPoint;
339-
dataPoint.insert({MarketDataMessage::DataFieldType::OPEN_PRICE, x["o"].GetString()});
340-
dataPoint.insert({MarketDataMessage::DataFieldType::HIGH_PRICE, x["h"].GetString()});
341-
dataPoint.insert({MarketDataMessage::DataFieldType::LOW_PRICE, x["l"].GetString()});
342-
dataPoint.insert({MarketDataMessage::DataFieldType::CLOSE_PRICE, x["c"].GetString()});
343-
dataPoint.insert({MarketDataMessage::DataFieldType::VOLUME, x["v"].GetString()});
358+
dataPoint.insert({MarketDataMessage::DataFieldType::OPEN_PRICE, x[1].GetString()});
359+
dataPoint.insert({MarketDataMessage::DataFieldType::HIGH_PRICE, x[2].GetString()});
360+
dataPoint.insert({MarketDataMessage::DataFieldType::LOW_PRICE, x[3].GetString()});
361+
dataPoint.insert({MarketDataMessage::DataFieldType::CLOSE_PRICE, x[4].GetString()});
362+
dataPoint.insert({MarketDataMessage::DataFieldType::VOLUME, x[5].GetString()});
363+
dataPoint.insert({MarketDataMessage::DataFieldType::QUOTE_VOLUME, x[6].GetString()});
344364
marketDataMessage.data[MarketDataMessage::DataType::CANDLESTICK].emplace_back(std::move(dataPoint));
345365
marketDataMessageList.emplace_back(std::move(marketDataMessage));
346366
}
@@ -349,14 +369,14 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
349369
MarketDataMessage marketDataMessage;
350370
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_MARKET_DEPTH;
351371
const rj::Value& result = document["result"];
352-
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(result["time"].GetString()));
353-
for (const auto& x : result["bids"].GetArray()) {
372+
marketDataMessage.tp = UtilTime::makeTimePointFromMilliseconds(std::stoll(result["ts"].GetString()));
373+
for (const auto& x : result["b"].GetArray()) {
354374
MarketDataMessage::TypeForDataPoint dataPoint;
355375
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, x[0].GetString()});
356376
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, x[1].GetString()});
357377
marketDataMessage.data[MarketDataMessage::DataType::BID].emplace_back(std::move(dataPoint));
358378
}
359-
for (const auto& x : result["asks"].GetArray()) {
379+
for (const auto& x : result["a"].GetArray()) {
360380
MarketDataMessage::TypeForDataPoint dataPoint;
361381
dataPoint.insert({MarketDataMessage::DataFieldType::PRICE, x[0].GetString()});
362382
dataPoint.insert({MarketDataMessage::DataFieldType::SIZE, x[1].GetString()});
@@ -369,7 +389,7 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
369389
message.setTimeReceived(timeReceived);
370390
message.setType(this->requestOperationToMessageTypeMap.at(request.getOperation()));
371391
for (const auto& x : document["result"]["list"].GetArray()) {
372-
if (std::string(x["name"].GetString()) == request.getInstrument()) {
392+
if (std::string(x["symbol"].GetString()) == request.getInstrument()) {
373393
Element element;
374394
this->extractInstrumentInfo(element, x);
375395
message.setElementList({element});

0 commit comments

Comments
 (0)