Skip to content

Commit 2f91852

Browse files
Merge pull request #560 from crypto-chassis/feat-binance-order-book
add binance full order book
2 parents fe1067a + aa354f1 commit 2f91852

6 files changed

Lines changed: 210 additions & 98 deletions

include/ccapi_cpp/ccapi_macro.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@
418418
#define CCAPI_WEBSOCKET_BINANCE_BASE_CHANNEL_PARTIAL_BOOK_DEPTH "depth"
419419
#define CCAPI_WEBSOCKET_BINANCE_BASE_CHANNEL_AGG_TRADE "aggTrade"
420420
#define CCAPI_WEBSOCKET_BINANCE_BASE_CHANNEL_KLINE "kline"
421+
#define CCAPI_WEBSOCKET_BINANCE_BASE_CHANNEL_DIFF_DEPTH "depth"
421422
#define CCAPI_WEBSOCKET_HUOBI_CHANNEL_TRADE_DETAIL "market.$symbol.trade.detail"
422423
#define CCAPI_WEBSOCKET_HUOBI_CHANNEL_TRADE_DETAIL_REGEX "market\\.(.+)\\.trade\\.detail"
423424
#define CCAPI_WEBSOCKET_HUOBI_CHANNEL_MARKET_BBO "market.$symbol.bbo"

include/ccapi_cpp/ccapi_market_data_message.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,43 +176,56 @@ class MarketDataMessage {
176176
return output;
177177
}
178178

179-
static std::string dataToString(const TypeForData& data) {
179+
template <typename DataMap>
180+
static std::string dataToString(const DataMap& data) {
180181
std::string output1 = "{";
181182
auto size1 = data.size();
182183
auto i1 = 0;
184+
183185
for (const auto& elem1 : data) {
184186
output1 += dataTypeToString(elem1.first);
185187
output1 += "=";
188+
186189
std::string output2 = "[ ";
187190
auto size2 = elem1.second.size();
188191
auto i2 = 0;
192+
189193
for (const auto& elem2 : elem1.second) {
190194
std::string output3 = "{";
191195
auto size3 = elem2.size();
192196
auto i3 = 0;
197+
193198
for (const auto& elem3 : elem2) {
194199
output3 += dataFieldTypeToString(elem3.first);
195200
output3 += "=";
201+
202+
// Works for std::string, std::string_view, or any type
196203
output3 += ccapi::toString(elem3.second);
204+
197205
if (i3 < size3 - 1) {
198206
output3 += ", ";
199207
}
200208
++i3;
201209
}
210+
202211
output3 += "}";
203212
output2 += output3;
213+
204214
if (i2 < size2 - 1) {
205215
output2 += ", ";
206216
}
207217
++i2;
208218
}
219+
209220
output2 += " ]";
210221
output1 += output2;
222+
211223
if (i1 < size1 - 1) {
212224
output1 += ", ";
213225
}
214226
++i1;
215227
}
228+
216229
output1 += "}";
217230
return output1;
218231
}
@@ -243,7 +256,7 @@ class MarketDataMessage {
243256

244257
std::string toString() const {
245258
std::string output = "MarketDataMessage [type = " + typeToString(type) + ", recapType = " + recapTypeToString(recapType) + ", tp = " + ccapi::toString(tp) +
246-
", exchangeSubscriptionId = " + exchangeSubscriptionId + ", data = " + dataToString(data) + "]";
259+
", exchangeSubscriptionId = " + exchangeSubscriptionId + ", data = " + dataToString<TypeForData>(data) + "]";
247260
return output;
248261
}
249262

include/ccapi_cpp/ccapi_session.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,7 @@ class Session {
790790

791791
virtual void onEvent(Event& event, Queue<Event>* eventQueue) {
792792
CCAPI_LOGGER_FUNCTION_ENTER;
793-
CCAPI_LOGGER_TRACE("event = " + toString(event));
793+
CCAPI_LOGGER_DEBUG("event = " + toString(event));
794794
if (eventQueue) {
795795
eventQueue->pushBack(std::move(event));
796796
} else {

include/ccapi_cpp/service/ccapi_market_data_service.h

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ class MarketDataService : public Service {
870870
const TimePoint& tp, const TimePoint& timeReceived, MarketDataMessage::TypeForData& input, const std::string& field,
871871
const std::map<std::string, std::string>& optionMap, const std::vector<std::string>& correlationIdList,
872872
std::map<Decimal, std::string>& snapshotBid, std::map<Decimal, std::string>& snapshotAsk) {
873-
CCAPI_LOGGER_TRACE("input = " + MarketDataMessage::dataToString(input));
873+
CCAPI_LOGGER_TRACE("input = " + MarketDataMessage::dataToString<MarketDataMessage::TypeForData>(input));
874874
if (this->processedInitialSnapshotByConnectionIdChannelIdSymbolIdMap[wsConnectionPtr->id][channelId][symbolId]) {
875875
std::vector<Message> messageList;
876876
CCAPI_LOGGER_TRACE("optionMap = " + toString(optionMap));
@@ -988,7 +988,7 @@ class MarketDataService : public Service {
988988
void processTrade(std::shared_ptr<WsConnection> wsConnectionPtr, const std::string& channelId, const std::string& symbolId, Event& event, const TimePoint& tp,
989989
const TimePoint& timeReceived, MarketDataMessage::TypeForData& input, const std::string& field,
990990
const std::map<std::string, std::string>& optionMap, const std::vector<std::string>& correlationIdList, bool isSolicited) {
991-
CCAPI_LOGGER_TRACE("input = " + MarketDataMessage::dataToString(input));
991+
CCAPI_LOGGER_TRACE("input = " + MarketDataMessage::dataToString<MarketDataMessage::TypeForData>(input));
992992
CCAPI_LOGGER_TRACE("optionMap = " + toString(optionMap));
993993
bool shouldConflate = optionMap.at(CCAPI_CONFLATE_INTERVAL_MILLISECONDS) != CCAPI_CONFLATE_INTERVAL_MILLISECONDS_DEFAULT;
994994
CCAPI_LOGGER_TRACE("shouldConflate = " + toString(shouldConflate));
@@ -1459,20 +1459,18 @@ class MarketDataService : public Service {
14591459
}
14601460

14611461
void buildOrderBookInitialOnFail(std::shared_ptr<WsConnection> wsConnectionPtr, const std::string& exchangeSubscriptionId, long delayMilliseconds) {
1462-
auto thisDelayMilliseconds = delayMilliseconds * 2;
1463-
if (thisDelayMilliseconds > 0) {
1464-
TimerPtr timerPtr(new boost::asio::steady_timer(*this->serviceContextPtr->ioContextPtr, std::chrono::milliseconds(thisDelayMilliseconds)));
1465-
timerPtr->async_wait([wsConnectionPtr, exchangeSubscriptionId, thisDelayMilliseconds, that = this](ErrorCode const& ec) {
1466-
if (ec) {
1467-
that->onError(Event::Type::SUBSCRIPTION_STATUS, Message::Type::GENERIC_ERROR, ec, "timer");
1468-
} else {
1469-
that->buildOrderBookInitial(wsConnectionPtr, exchangeSubscriptionId, thisDelayMilliseconds);
1470-
}
1471-
});
1472-
this->fetchMarketDepthInitialSnapshotTimerByConnectionIdExchangeSubscriptionIdMap[wsConnectionPtr->id][exchangeSubscriptionId] = timerPtr;
1473-
} else {
1474-
this->buildOrderBookInitial(wsConnectionPtr, exchangeSubscriptionId, thisDelayMilliseconds);
1475-
}
1462+
CCAPI_LOGGER_ERROR("buildOrderBookInitialOnFail: wsConnectionPtr = " + toString(*wsConnectionPtr) + ", exchangeSubscriptionId = " + exchangeSubscriptionId +
1463+
", delayMilliseconds = " + toString(delayMilliseconds));
1464+
auto thisDelayMilliseconds = delayMilliseconds > 0 ? delayMilliseconds * 2 : 1000;
1465+
TimerPtr timerPtr(new boost::asio::steady_timer(*this->serviceContextPtr->ioContextPtr, std::chrono::milliseconds(thisDelayMilliseconds)));
1466+
timerPtr->async_wait([wsConnectionPtr, exchangeSubscriptionId, thisDelayMilliseconds, that = this](ErrorCode const& ec) {
1467+
if (ec) {
1468+
that->onError(Event::Type::SUBSCRIPTION_STATUS, Message::Type::GENERIC_ERROR, ec, "timer");
1469+
} else {
1470+
that->buildOrderBookInitial(wsConnectionPtr, exchangeSubscriptionId, thisDelayMilliseconds);
1471+
}
1472+
});
1473+
this->fetchMarketDepthInitialSnapshotTimerByConnectionIdExchangeSubscriptionIdMap[wsConnectionPtr->id][exchangeSubscriptionId] = timerPtr;
14761474
}
14771475

14781476
void buildOrderBookInitial(std::shared_ptr<WsConnection> wsConnectionPtr, const std::string& exchangeSubscriptionId, long delayMilliseconds) {
@@ -1536,39 +1534,39 @@ class MarketDataService : public Service {
15361534
}
15371535
}
15381536
}
1539-
if (that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id).find(exchangeSubscriptionId) !=
1540-
that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id).end()) {
1541-
auto it = that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id)
1542-
.at(exchangeSubscriptionId)
1543-
.upper_bound(versionId);
1544-
while (it != that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id)
1545-
.at(exchangeSubscriptionId)
1546-
.end()) {
1547-
const auto& input = it->second;
1548-
for (const auto& x : input) {
1549-
const auto& type = x.first;
1550-
const auto& detail = x.second;
1551-
if (type == MarketDataMessage::DataType::BID) {
1552-
for (const auto& y : detail) {
1553-
const auto& price = y.at(MarketDataMessage::DataFieldType::PRICE);
1554-
const auto& size = y.at(MarketDataMessage::DataFieldType::SIZE);
1555-
Decimal decimalPrice(price);
1556-
that->updateOrderBook(snapshotBid, decimalPrice, size, that->sessionOptions.enableCheckOrderBookChecksum);
1557-
}
1558-
} else if (type == MarketDataMessage::DataType::ASK) {
1559-
for (const auto& y : detail) {
1560-
const auto& price = y.at(MarketDataMessage::DataFieldType::PRICE);
1561-
const auto& size = y.at(MarketDataMessage::DataFieldType::SIZE);
1562-
Decimal decimalPrice(price);
1563-
that->updateOrderBook(snapshotAsk, decimalPrice, size, that->sessionOptions.enableCheckOrderBookChecksum);
1564-
}
1537+
// if (that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id).find(exchangeSubscriptionId) !=
1538+
// that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id).end()) {
1539+
auto it = that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id)
1540+
.at(exchangeSubscriptionId)
1541+
.upper_bound(versionId);
1542+
while (it != that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id)
1543+
.at(exchangeSubscriptionId)
1544+
.end()) {
1545+
const auto& input = it->second;
1546+
for (const auto& x : input) {
1547+
const auto& type = x.first;
1548+
const auto& detail = x.second;
1549+
if (type == MarketDataMessage::DataType::BID) {
1550+
for (const auto& y : detail) {
1551+
const auto& price = y.at(MarketDataMessage::DataFieldType::PRICE);
1552+
const auto& size = y.at(MarketDataMessage::DataFieldType::SIZE);
1553+
Decimal decimalPrice(price);
1554+
that->updateOrderBook(snapshotBid, decimalPrice, size, that->sessionOptions.enableCheckOrderBookChecksum);
1555+
}
1556+
} else if (type == MarketDataMessage::DataType::ASK) {
1557+
for (const auto& y : detail) {
1558+
const auto& price = y.at(MarketDataMessage::DataFieldType::PRICE);
1559+
const auto& size = y.at(MarketDataMessage::DataFieldType::SIZE);
1560+
Decimal decimalPrice(price);
1561+
that->updateOrderBook(snapshotAsk, decimalPrice, size, that->sessionOptions.enableCheckOrderBookChecksum);
15651562
}
15661563
}
1567-
that->orderbookVersionIdByConnectionIdExchangeSubscriptionIdMap[wsConnectionPtr->id][exchangeSubscriptionId] = it->first;
1568-
it++;
15691564
}
1570-
that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id).erase(exchangeSubscriptionId);
1565+
that->orderbookVersionIdByConnectionIdExchangeSubscriptionIdMap[wsConnectionPtr->id][exchangeSubscriptionId] = it->first;
1566+
it++;
15711567
}
1568+
that->marketDataMessageDataBufferByConnectionIdExchangeSubscriptionIdVersionIdMap.at(wsConnectionPtr->id).erase(exchangeSubscriptionId);
1569+
// }
15721570
Event event;
15731571
event.setType(Event::Type::SUBSCRIPTION_DATA);
15741572
std::vector<Element> elementList;

0 commit comments

Comments
 (0)