@@ -50,6 +50,47 @@ class MarketDataServiceKraken : public MarketDataService {
5050 }
5151 }
5252
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+
5394 std::vector<std::string> createSendStringList (std::shared_ptr<WsConnection> wsConnectionPtr) override {
5495 std::vector<std::string> sendStringList;
5596 for (const auto & subscriptionListByChannelIdSymbolId : this ->subscriptionListByConnectionIdChannelIdSymbolIdMap .at (wsConnectionPtr->id )) {
@@ -186,19 +227,26 @@ class MarketDataServiceKraken : public MarketDataService {
186227 marketDataMessage.exchangeSubscriptionId = exchangeSubscriptionId;
187228 marketDataMessage.tp = latestTp;
188229 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+ }
189237 if (anonymous2.HasMember (" b" )) {
190238 for (const auto & x : anonymous2[" b" ].GetArray ()) {
191239 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 ());
194242 marketDataMessage.data [MarketDataMessage::DataType::BID].emplace_back (std::move (dataPoint));
195243 }
196244 }
197245 if (anonymous2.HasMember (" a" )) {
198246 for (const auto & x : anonymous2[" a" ].GetArray ()) {
199247 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 ());
202250 marketDataMessage.data [MarketDataMessage::DataType::ASK].emplace_back (std::move (dataPoint));
203251 }
204252 }
@@ -211,14 +259,14 @@ class MarketDataServiceKraken : public MarketDataService {
211259 marketDataMessage.tp = timeReceived;
212260 for (const auto & x : anonymous[" bs" ].GetArray ()) {
213261 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 ());
216264 marketDataMessage.data [MarketDataMessage::DataType::BID].emplace_back (std::move (dataPoint));
217265 }
218266 for (const auto & x : anonymous[" as" ].GetArray ()) {
219267 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 ());
222270 marketDataMessage.data [MarketDataMessage::DataType::ASK].emplace_back (std::move (dataPoint));
223271 }
224272 marketDataMessageList.emplace_back (std::move (marketDataMessage));
@@ -235,8 +283,8 @@ class MarketDataServiceKraken : public MarketDataService {
235283 tp += std::chrono::nanoseconds (timePair.second );
236284 marketDataMessage.tp = tp;
237285 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 ());
240288 dataPoint.emplace (MarketDataMessage::DataFieldType::IS_BUYER_MAKER, std::string_view (x[3 ].GetString ()) == " s" ? " 1" : " 0" );
241289 marketDataMessage.data [MarketDataMessage::DataType::TRADE].emplace_back (std::move (dataPoint));
242290 marketDataMessageList.emplace_back (std::move (marketDataMessage));
@@ -372,8 +420,8 @@ class MarketDataServiceKraken : public MarketDataService {
372420 tp += std::chrono::nanoseconds (timePair.second );
373421 marketDataMessage.tp = tp;
374422 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 ());
377425 dataPoint.emplace (MarketDataMessage::DataFieldType::IS_BUYER_MAKER, std::string_view (x[3 ].GetString ()) == " s" ? " 1" : " 0" );
378426 marketDataMessage.data [MarketDataMessage::DataType::TRADE].emplace_back (std::move (dataPoint));
379427 marketDataMessageList.emplace_back (std::move (marketDataMessage));
0 commit comments