@@ -50,6 +50,47 @@ class MarketDataServiceKraken : public MarketDataService {
50
50
}
51
51
}
52
52
53
+ static void processForChecksum (std::string& str) {
54
+ str.erase (std::remove (str.begin (), str.end (), ' .' ), str.end ());
55
+ UtilString::ltrimInPlace (str, " 0" );
56
+ }
57
+
58
+ std::vector<std::string> extractTop (const std::map<Decimal, std::string>& snapshot, bool reverse = false ) {
59
+ std::vector<std::string> result;
60
+ int count = 0 ;
61
+
62
+ auto process_item = [&](auto it) {
63
+ std::string price = toString (it->first );
64
+ processForChecksum (price);
65
+ result.push_back (std::move (price));
66
+
67
+ std::string volume = it->second ;
68
+ processForChecksum (volume);
69
+ result.push_back (std::move (volume));
70
+ };
71
+
72
+ if (reverse) {
73
+ for (auto it = snapshot.rbegin (); it != snapshot.rend () && count < 10 ; ++it, ++count) {
74
+ process_item (it);
75
+ }
76
+ } else {
77
+ for (auto it = snapshot.begin (); it != snapshot.end () && count < 10 ; ++it, ++count) {
78
+ process_item (it);
79
+ }
80
+ }
81
+ return result;
82
+ };
83
+
84
+ std::string calculateOrderBookChecksum (const std::map<Decimal, std::string>& snapshotBid, const std::map<Decimal, std::string>& snapshotAsk) override {
85
+ auto csAskData = extractTop (snapshotAsk);
86
+ auto csBidData = extractTop (snapshotBid, true );
87
+
88
+ std::string csStr = UtilString::join (csAskData, " " ) + UtilString::join (csBidData, " " );
89
+ uint_fast32_t csCalc = UtilAlgorithm::crc (csStr.begin (), csStr.end ());
90
+ CCAPI_LOGGER_DEBUG (" csStr: " + csStr + " , csCalc: " + intToHex (csCalc));
91
+ return intToHex (csCalc);
92
+ }
93
+
53
94
std::vector<std::string> createSendStringList (std::shared_ptr<WsConnection> wsConnectionPtr) override {
54
95
std::vector<std::string> sendStringList;
55
96
for (const auto & subscriptionListByChannelIdSymbolId : this ->subscriptionListByConnectionIdChannelIdSymbolIdMap .at (wsConnectionPtr->id )) {
@@ -186,19 +227,26 @@ class MarketDataServiceKraken : public MarketDataService {
186
227
marketDataMessage.exchangeSubscriptionId = exchangeSubscriptionId;
187
228
marketDataMessage.tp = latestTp;
188
229
marketDataMessage.recapType = MarketDataMessage::RecapType::NONE;
230
+ if (this ->sessionOptions .enableCheckOrderBookChecksum ) {
231
+ if (anonymous2.HasMember (" c" )) {
232
+ CCAPI_LOGGER_DEBUG (" Checksum for " + symbolId + " : " + anonymous2[" c" ].GetString ());
233
+ this ->orderBookChecksumByConnectionIdSymbolIdMap [wsConnectionPtr->id ][symbolId] =
234
+ intToHex (static_cast <uint_fast32_t >(static_cast <uint32_t >(std::stoul (anonymous2[" c" ].GetString ()))));
235
+ }
236
+ }
189
237
if (anonymous2.HasMember (" b" )) {
190
238
for (const auto & x : anonymous2[" b" ].GetArray ()) {
191
239
MarketDataMessage::TypeForDataPoint dataPoint;
192
- dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalStringView ( x[0 ].GetString () ));
193
- dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalStringView ( x[1 ].GetString () ));
240
+ dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, x[0 ].GetString ());
241
+ dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, x[1 ].GetString ());
194
242
marketDataMessage.data [MarketDataMessage::DataType::BID].emplace_back (std::move (dataPoint));
195
243
}
196
244
}
197
245
if (anonymous2.HasMember (" a" )) {
198
246
for (const auto & x : anonymous2[" a" ].GetArray ()) {
199
247
MarketDataMessage::TypeForDataPoint dataPoint;
200
- dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalStringView ( x[0 ].GetString () ));
201
- dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalStringView ( x[1 ].GetString () ));
248
+ dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, x[0 ].GetString ());
249
+ dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, x[1 ].GetString ());
202
250
marketDataMessage.data [MarketDataMessage::DataType::ASK].emplace_back (std::move (dataPoint));
203
251
}
204
252
}
@@ -211,14 +259,14 @@ class MarketDataServiceKraken : public MarketDataService {
211
259
marketDataMessage.tp = timeReceived;
212
260
for (const auto & x : anonymous[" bs" ].GetArray ()) {
213
261
MarketDataMessage::TypeForDataPoint dataPoint;
214
- dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalStringView ( x[0 ].GetString () ));
215
- dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalStringView ( x[1 ].GetString () ));
262
+ dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, x[0 ].GetString ());
263
+ dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, x[1 ].GetString ());
216
264
marketDataMessage.data [MarketDataMessage::DataType::BID].emplace_back (std::move (dataPoint));
217
265
}
218
266
for (const auto & x : anonymous[" as" ].GetArray ()) {
219
267
MarketDataMessage::TypeForDataPoint dataPoint;
220
- dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalStringView ( x[0 ].GetString () ));
221
- dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalStringView ( x[1 ].GetString () ));
268
+ dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, x[0 ].GetString ());
269
+ dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, x[1 ].GetString ());
222
270
marketDataMessage.data [MarketDataMessage::DataType::ASK].emplace_back (std::move (dataPoint));
223
271
}
224
272
marketDataMessageList.emplace_back (std::move (marketDataMessage));
@@ -235,8 +283,8 @@ class MarketDataServiceKraken : public MarketDataService {
235
283
tp += std::chrono::nanoseconds (timePair.second );
236
284
marketDataMessage.tp = tp;
237
285
MarketDataMessage::TypeForDataPoint dataPoint;
238
- dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalStringView ( x[0 ].GetString () ));
239
- dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalStringView ( x[1 ].GetString () ));
286
+ dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, x[0 ].GetString ());
287
+ dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, x[1 ].GetString ());
240
288
dataPoint.emplace (MarketDataMessage::DataFieldType::IS_BUYER_MAKER, std::string_view (x[3 ].GetString ()) == " s" ? " 1" : " 0" );
241
289
marketDataMessage.data [MarketDataMessage::DataType::TRADE].emplace_back (std::move (dataPoint));
242
290
marketDataMessageList.emplace_back (std::move (marketDataMessage));
@@ -372,8 +420,8 @@ class MarketDataServiceKraken : public MarketDataService {
372
420
tp += std::chrono::nanoseconds (timePair.second );
373
421
marketDataMessage.tp = tp;
374
422
MarketDataMessage::TypeForDataPoint dataPoint;
375
- dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, UtilString::normalizeDecimalStringView ( x[0 ].GetString () ));
376
- dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, UtilString::normalizeDecimalStringView ( x[1 ].GetString () ));
423
+ dataPoint.emplace (MarketDataMessage::DataFieldType::PRICE, x[0 ].GetString ());
424
+ dataPoint.emplace (MarketDataMessage::DataFieldType::SIZE, x[1 ].GetString ());
377
425
dataPoint.emplace (MarketDataMessage::DataFieldType::IS_BUYER_MAKER, std::string_view (x[3 ].GetString ()) == " s" ? " 1" : " 0" );
378
426
marketDataMessage.data [MarketDataMessage::DataType::TRADE].emplace_back (std::move (dataPoint));
379
427
marketDataMessageList.emplace_back (std::move (marketDataMessage));
0 commit comments