@@ -10,7 +10,7 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
10
10
ServiceContext* serviceContextPtr)
11
11
: MarketDataServiceBybitBase(eventHandler, sessionOptions, sessionConfigs, serviceContextPtr) {
12
12
this ->exchangeName = CCAPI_EXCHANGE_NAME_BYBIT;
13
- this ->baseUrlWs = sessionConfigs.getUrlWebsocketBase ().at (this ->exchangeName ) + " /spot /public/v3 " ;
13
+ this ->baseUrlWs = sessionConfigs.getUrlWebsocketBase ().at (this ->exchangeName ) + " /v5 /public/spot " ;
14
14
this ->baseUrlRest = sessionConfigs.getUrlRestBase ().at (this ->exchangeName );
15
15
this ->setHostRestFromUrlRest (this ->baseUrlRest );
16
16
this ->setHostWsFromUrlWs (this ->baseUrlWs );
@@ -54,11 +54,13 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
54
54
const Subscription& subscription, const std::map<std::string, std::string> optionMap) override {
55
55
auto marketDepthRequested = std::stoi (optionMap.at (CCAPI_MARKET_DEPTH_MAX));
56
56
if (field == CCAPI_MARKET_DEPTH) {
57
- if (marketDepthRequested == 1 ) {
58
- channelId = CCAPI_WEBSOCKET_BYBIT_CHANNEL_BOOK_TICKER;
59
- } else {
60
57
channelId = CCAPI_WEBSOCKET_BYBIT_CHANNEL_DEPTH;
61
- }
58
+ std::vector<int > depths = {1 , 50 , 200 };
59
+ int marketDepthSubscribedToExchange = 1 ;
60
+ marketDepthSubscribedToExchange = this ->calculateMarketDepthAllowedByExchange (marketDepthRequested, depths);
61
+ channelId += std::string (" ?" ) + CCAPI_MARKET_DEPTH_SUBSCRIBED_TO_EXCHANGE + " =" + std::to_string (marketDepthSubscribedToExchange);
62
+ this ->marketDepthSubscribedToExchangeByConnectionIdChannelIdSymbolIdMap [wsConnection.id ][channelId][symbolId] = marketDepthSubscribedToExchange;
63
+
62
64
} else if (field == CCAPI_CANDLESTICK) {
63
65
int intervalSeconds = std::stoi (optionMap.at (CCAPI_CANDLESTICK_INTERVAL_SECONDS));
64
66
std::string interval = this ->convertCandlestickIntervalSecondsToInterval (intervalSeconds);
@@ -79,8 +81,15 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
79
81
for (const auto & subscriptionListByInstrument : subscriptionListByChannelIdSymbolId.second ) {
80
82
auto symbolId = subscriptionListByInstrument.first ;
81
83
auto exchangeSubscriptionId = channelId;
82
- if (channelId == CCAPI_WEBSOCKET_BYBIT_CHANNEL_BOOK_TICKER || channelId == CCAPI_WEBSOCKET_BYBIT_CHANNEL_DEPTH) {
84
+ if (channelId.rfind (CCAPI_WEBSOCKET_BYBIT_CHANNEL_DEPTH, 0 ) == 0 ) {
85
+ int marketDepthSubscribedToExchange =
86
+ this ->marketDepthSubscribedToExchangeByConnectionIdChannelIdSymbolIdMap .at (wsConnection.id ).at (channelId).at (symbolId);
83
87
this ->l2UpdateIsReplaceByConnectionIdChannelIdSymbolIdMap [wsConnection.id ][channelId][symbolId] = true ;
88
+ exchangeSubscriptionId = CCAPI_WEBSOCKET_BYBIT_CHANNEL_DEPTH;
89
+ std::string toReplace = " {depth}" ;
90
+ exchangeSubscriptionId.replace (exchangeSubscriptionId.find (toReplace), toReplace.length (), std::to_string (marketDepthSubscribedToExchange));
91
+ }
92
+ if (channelId == CCAPI_WEBSOCKET_BYBIT_CHANNEL_DEPTH) {
84
93
}
85
94
std::string toReplace = " {symbol}" ;
86
95
exchangeSubscriptionId.replace (exchangeSubscriptionId.find (toReplace), toReplace.length (), symbolId);
@@ -162,80 +171,50 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
162
171
std::string channelId = this ->channelIdSymbolIdByConnectionIdExchangeSubscriptionIdMap [wsConnection.id ][exchangeSubscriptionId][CCAPI_CHANNEL_ID];
163
172
std::string symbolId = this ->channelIdSymbolIdByConnectionIdExchangeSubscriptionIdMap [wsConnection.id ][exchangeSubscriptionId][CCAPI_SYMBOL_ID];
164
173
auto optionMap = this ->optionMapByConnectionIdChannelIdSymbolIdMap [wsConnection.id ][channelId][symbolId];
165
- const rj::Value& data = document[" data" ];
166
- marketDataMessage.tp = TimePoint (std::chrono::milliseconds (std::stoll (data[" t" ].GetString ())));
174
+ marketDataMessage.tp = TimePoint (std::chrono::milliseconds (std::stoll (document[" ts" ].GetString ())));
167
175
marketDataMessage.exchangeSubscriptionId = exchangeSubscriptionId;
168
- if (channelId == CCAPI_WEBSOCKET_BYBIT_CHANNEL_BOOK_TICKER) {
176
+ if (channelId.rfind (CCAPI_WEBSOCKET_BYBIT_CHANNEL_DEPTH, 0 ) == 0 ) {
177
+ const rj::Value& data = document[" data" ];
169
178
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_MARKET_DEPTH;
170
- marketDataMessage.recapType = this ->processedInitialSnapshotByConnectionIdChannelIdSymbolIdMap [wsConnection.id ][channelId][symbolId]
171
- ? MarketDataMessage::RecapType::NONE
172
- : MarketDataMessage::RecapType::SOLICITED;
173
- {
174
- MarketDataMessage::TypeForDataPoint dataPoint;
175
- dataPoint.insert ({MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalString (data[" bp" ].GetString ())});
176
- dataPoint.insert ({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString (data[" bq" ].GetString ())});
177
- marketDataMessage.data [MarketDataMessage::DataType::BID].emplace_back (std::move (dataPoint));
178
- }
179
- {
180
- MarketDataMessage::TypeForDataPoint dataPoint;
181
- dataPoint.insert ({MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalString (data[" ap" ].GetString ())});
182
- dataPoint.insert ({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString (data[" aq" ].GetString ())});
183
- marketDataMessage.data [MarketDataMessage::DataType::ASK].emplace_back (std::move (dataPoint));
184
- }
185
- marketDataMessageList.emplace_back (std::move (marketDataMessage));
186
- } else if (channelId == CCAPI_WEBSOCKET_BYBIT_CHANNEL_DEPTH) {
187
- marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_MARKET_DEPTH;
188
- marketDataMessage.recapType = this ->processedInitialSnapshotByConnectionIdChannelIdSymbolIdMap [wsConnection.id ][channelId][symbolId]
189
- ? MarketDataMessage::RecapType::NONE
190
- : MarketDataMessage::RecapType::SOLICITED;
191
- const char * bidsName = " b" ;
192
- int bidIndex = 0 ;
193
- int maxMarketDepth = std::stoi (optionMap.at (CCAPI_MARKET_DEPTH_MAX));
194
- for (const auto & x : data[bidsName].GetArray ()) {
195
- if (bidIndex >= maxMarketDepth) {
196
- break ;
197
- }
179
+ std::string type = document[" type" ].GetString ();
180
+ marketDataMessage.recapType = type == " snapshot" ? MarketDataMessage::RecapType::SOLICITED : MarketDataMessage::RecapType::NONE;
181
+ for (const auto & x : data[" b" ].GetArray ()) {
198
182
MarketDataMessage::TypeForDataPoint dataPoint;
199
183
dataPoint.insert ({MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalString (x[0 ].GetString ())});
200
184
dataPoint.insert ({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString (x[1 ].GetString ())});
201
185
marketDataMessage.data [MarketDataMessage::DataType::BID].emplace_back (std::move (dataPoint));
202
- ++bidIndex;
203
186
}
204
- const char * asksName = " a" ;
205
- int askIndex = 0 ;
206
- for (const auto & x : data[asksName].GetArray ()) {
207
- if (askIndex >= maxMarketDepth) {
208
- break ;
209
- }
187
+ for (const auto & x : data[" a" ].GetArray ()) {
210
188
MarketDataMessage::TypeForDataPoint dataPoint;
211
189
dataPoint.insert ({MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalString (x[0 ].GetString ())});
212
190
dataPoint.insert ({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString (x[1 ].GetString ())});
213
191
marketDataMessage.data [MarketDataMessage::DataType::ASK].emplace_back (std::move (dataPoint));
214
- ++askIndex;
215
192
}
216
193
marketDataMessageList.emplace_back (std::move (marketDataMessage));
217
194
} else if (channelId == CCAPI_WEBSOCKET_BYBIT_CHANNEL_TRADE) {
195
+ const rj::Value& data = document[" data" ][0 ];
218
196
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_TRADE;
219
197
marketDataMessage.recapType = MarketDataMessage::RecapType::NONE;
220
198
MarketDataMessage::TypeForDataPoint dataPoint;
221
199
dataPoint.insert ({MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalString (std::string (data[" p" ].GetString ()))});
222
- dataPoint.insert ({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString (std::string (data[" q " ].GetString ()))});
223
- dataPoint.insert ({MarketDataMessage::DataFieldType::TRADE_ID, std::string (data[" v " ].GetString ())});
224
- dataPoint.insert ({MarketDataMessage::DataFieldType::IS_BUYER_MAKER, data[" m " ].GetBool () ? " 0 " : " 1 " });
200
+ dataPoint.insert ({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString (std::string (data[" v " ].GetString ()))});
201
+ dataPoint.insert ({MarketDataMessage::DataFieldType::TRADE_ID, std::string (data[" i " ].GetString ())});
202
+ dataPoint.insert ({MarketDataMessage::DataFieldType::IS_BUYER_MAKER, std::string ( data[" S " ].GetString ()) == " Buy " ? " 1 " : " 0 " });
225
203
marketDataMessage.data [MarketDataMessage::DataType::TRADE].emplace_back (std::move (dataPoint));
226
204
marketDataMessageList.emplace_back (std::move (marketDataMessage));
227
205
} else if (channelId.rfind (CCAPI_WEBSOCKET_BYBIT_CHANNEL_KLINE_2, 0 ) == 0 ) {
206
+ const rj::Value& data = document[" data" ][0 ];
228
207
MarketDataMessage marketDataMessage;
229
208
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_CANDLESTICK;
230
209
marketDataMessage.recapType = MarketDataMessage::RecapType::NONE;
231
- marketDataMessage.tp = TimePoint (std::chrono::milliseconds (std::stoll (data[ " t " ].GetString ())));
210
+ marketDataMessage.tp = TimePoint (std::chrono::milliseconds (std::stoll (document[ " ts " ].GetString ())));
232
211
marketDataMessage.exchangeSubscriptionId = exchangeSubscriptionId;
233
212
MarketDataMessage::TypeForDataPoint dataPoint;
234
- dataPoint.insert ({MarketDataMessage::DataFieldType::OPEN_PRICE, data[" o " ].GetString ()});
235
- dataPoint.insert ({MarketDataMessage::DataFieldType::HIGH_PRICE, data[" h " ].GetString ()});
236
- dataPoint.insert ({MarketDataMessage::DataFieldType::LOW_PRICE, data[" l " ].GetString ()});
237
- dataPoint.insert ({MarketDataMessage::DataFieldType::CLOSE_PRICE, data[" c " ].GetString ()});
238
- dataPoint.insert ({MarketDataMessage::DataFieldType::VOLUME, data[" v " ].GetString ()});
213
+ dataPoint.insert ({MarketDataMessage::DataFieldType::OPEN_PRICE, data[" open " ].GetString ()});
214
+ dataPoint.insert ({MarketDataMessage::DataFieldType::HIGH_PRICE, data[" high " ].GetString ()});
215
+ dataPoint.insert ({MarketDataMessage::DataFieldType::LOW_PRICE, data[" low " ].GetString ()});
216
+ dataPoint.insert ({MarketDataMessage::DataFieldType::CLOSE_PRICE, data[" close " ].GetString ()});
217
+ dataPoint.insert ({MarketDataMessage::DataFieldType::VOLUME, data[" volume " ].GetString ()});
239
218
marketDataMessage.data [MarketDataMessage::DataType::CANDLESTICK].emplace_back (std::move (dataPoint));
240
219
marketDataMessageList.emplace_back (std::move (marketDataMessage));
241
220
}
@@ -343,7 +322,7 @@ class MarketDataServiceBybit : public MarketDataServiceBybitBase {
343
322
dataPoint.insert ({MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalString (std::string (x[" price" ].GetString ()))});
344
323
dataPoint.insert ({MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalString (std::string (x[" size" ].GetString ()))});
345
324
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" });
325
+ dataPoint.insert ({MarketDataMessage::DataFieldType::IS_BUYER_MAKER, std::string (x[" side" ].GetString ()) == " Buy " ? " 1" : " 0" });
347
326
marketDataMessage.data [MarketDataMessage::DataType::TRADE].emplace_back (std::move (dataPoint));
348
327
marketDataMessageList.emplace_back (std::move (marketDataMessage));
349
328
}
0 commit comments