Skip to content

Commit

Permalink
Merge pull request #431 from crypto-chassis/experimental/exchange_pro…
Browse files Browse the repository at this point in the history
…vided_candlestick

add draft for streaming exchange provided candlestick
  • Loading branch information
cryptochassis authored Sep 26, 2023
2 parents 65ee040 + 237998b commit 89b5e22
Show file tree
Hide file tree
Showing 13 changed files with 468 additions and 221 deletions.
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Notification: we've added a new feature that allows our users to subscribe to exchange provided candlesticks. There is a small renaming: "OPEN" has been renamed to "OPEN_PRICE", "CLOSE" has been renamed to "CLOSE_PRICE", "HIGH" has been renamed to "HIGH_PRICE", "LOW" has been renamed to "LOW_PRICE". If you have any questions, feel free to directly ask us on Discord https://discord.gg/b5EKcp9s8T.


<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
Expand All @@ -20,7 +23,8 @@
- [Receive subscription events at periodic intervals including when the market depth snapshot hasn't changed](#receive-subscription-events-at-periodic-intervals-including-when-the-market-depth-snapshot-hasnt-changed)
- [Receive subscription market depth updates](#receive-subscription-market-depth-updates)
- [Receive subscription trade events](#receive-subscription-trade-events)
- [Receive subscription OHLC events at periodic intervals](#receive-subscription-ohlc-events-at-periodic-intervals)
- [Receive subscription calculated-candlestick events at periodic intervals](#receive-subscription-calculated-candlestick-events-at-periodic-intervals)
- [Receive subscription exchange-provided-candlestick events at periodic intervals](#receive-subscription-exchange-provided-candlestick-events-at-periodic-intervals)
- [Send generic public requests](#send-generic-public-requests)
- [Make generic public subscriptions](#make-generic-public-subscriptions)
- [Send generic private requests](#send-generic-private-requests)
Expand Down Expand Up @@ -413,13 +417,20 @@ Instantiate `Subscription` with field `TRADE`.
Subscription subscription("coinbase", "BTC-USD", "TRADE");
```

#### Receive subscription OHLC events at periodic intervals
#### Receive subscription calculated-candlestick events at periodic intervals

Instantiate `Subscription` with field `TRADE` and option `CONFLATE_INTERVAL_MILLISECONDS` set to be the desired interval and `CONFLATE_GRACE_PERIOD_MILLISECONDS` to be your network latency.
```
Subscription subscription("coinbase", "BTC-USD", "TRADE", "CONFLATE_INTERVAL_MILLISECONDS=5000&CONFLATE_GRACE_PERIOD_MILLISECONDS=0");
```

#### Receive subscription exchange-provided-candlestick events at periodic intervals

Instantiate `Subscription` with field `CANDLESTICK` and option `CANDLESTICK_INTERVAL_SECONDS` set to be the desired interval.
```
Subscription subscription("okx", "BTC-USDT", "CANDLESTICK", "CANDLESTICK_INTERVAL_SECONDS=60");
```

#### Send generic public requests

Instantiate `Request` with operation `GENERIC_PUBLIC_REQUEST`. Provide request parameters `HTTP_METHOD`, `HTTP_PATH`, and optionally `HTTP_QUERY_STRING` (query string parameter values should be url-encoded), `HTTP_BODY`.
Expand Down
16 changes: 11 additions & 5 deletions include/ccapi_cpp/ccapi_macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,16 @@
#define CCAPI_CANDLESTICK_EMPTY ""
#endif
#ifndef CCAPI_OPEN_PRICE
#define CCAPI_OPEN_PRICE "OPEN"
#define CCAPI_OPEN_PRICE "OPEN_PRICE"
#endif
#ifndef CCAPI_HIGH_PRICE
#define CCAPI_HIGH_PRICE "HIGH"
#define CCAPI_HIGH_PRICE "HIG_PRICEH"
#endif
#ifndef CCAPI_LOW_PRICE
#define CCAPI_LOW_PRICE "LOW"
#define CCAPI_LOW_PRICE "LOW_PRICE"
#endif
#ifndef CCAPI_CLOSE_PRICE
#define CCAPI_CLOSE_PRICE "CLOSE"
#define CCAPI_CLOSE_PRICE "CLOSE_PRICE"
#endif
#ifndef CCAPI_VOLUME
#define CCAPI_VOLUME "VOLUME"
Expand Down Expand Up @@ -267,12 +267,14 @@
#define CCAPI_WEBSOCKET_GEMINI_PARAMETER_TOP_OF_BOOK "top_of_book"
#define CCAPI_WEBSOCKET_KRAKEN_CHANNEL_TRADE "trade"
#define CCAPI_WEBSOCKET_KRAKEN_CHANNEL_BOOK "book"
#define CCAPI_WEBSOCKET_KRAKEN_CHANNEL_OHLC "ohlc"
#define CCAPI_WEBSOCKET_KRAKEN_FUTURES_CHANNEL_TRADE "trade"
#define CCAPI_WEBSOCKET_KRAKEN_FUTURES_CHANNEL_BOOK "book"
#define CCAPI_WEBSOCKET_BITSTAMP_CHANNEL_LIVE_TRADES "live_trades"
#define CCAPI_WEBSOCKET_BITSTAMP_CHANNEL_ORDER_BOOK "order_book"
#define CCAPI_WEBSOCKET_BITFINEX_CHANNEL_TRADES "trades"
#define CCAPI_WEBSOCKET_BITFINEX_CHANNEL_BOOK "book"
#define CCAPI_WEBSOCKET_BITFINEX_CHANNEL_BOOKS "book"
#define CCAPI_WEBSOCKET_BITFINEX_CHANNEL_CANDLES "candles"
#define CCAPI_WEBSOCKET_BITMEX_CHANNEL_TRADE "trade"
#define CCAPI_WEBSOCKET_BITMEX_CHANNEL_QUOTE "quote"
#define CCAPI_WEBSOCKET_BITMEX_CHANNEL_ORDER_BOOK_10 "orderBook10"
Expand Down Expand Up @@ -305,6 +307,7 @@
#define CCAPI_WEBSOCKET_KUCOIN_CHANNEL_MARKET_TICKER "/market/ticker"
#define CCAPI_WEBSOCKET_KUCOIN_CHANNEL_MARKET_LEVEL2DEPTH5 "/spotMarket/level2Depth5"
#define CCAPI_WEBSOCKET_KUCOIN_CHANNEL_MARKET_LEVEL2DEPTH50 "/spotMarket/level2Depth50"
#define CCAPI_WEBSOCKET_KUCOIN_CHANNEL_MARKET_KLINES "/market/candles"
#define CCAPI_WEBSOCKET_KUCOIN_FUTURES_CHANNEL_MARKET_MATCH "/contractMarket/execution"
#define CCAPI_WEBSOCKET_KUCOIN_FUTURES_CHANNEL_MARKET_LEVEL2 "/contractMarket/level2"
#define CCAPI_WEBSOCKET_KUCOIN_FUTURES_CHANNEL_MARKET_TICKER "/contractMarket/tickerV2"
Expand All @@ -320,9 +323,11 @@
#define CCAPI_WEBSOCKET_GATEIO_CHANNEL_TRADES "spot.trades"
#define CCAPI_WEBSOCKET_GATEIO_CHANNEL_BOOK_TICKER "spot.book_ticker"
#define CCAPI_WEBSOCKET_GATEIO_CHANNEL_ORDER_BOOK "spot.order_book"
#define CCAPI_WEBSOCKET_GATEIO_CHANNEL_CANDLESTICKS "spot.candlesticks"
#define CCAPI_WEBSOCKET_GATEIO_PERPETUAL_FUTURES_CHANNEL_TRADES "futures.trades"
#define CCAPI_WEBSOCKET_GATEIO_PERPETUAL_FUTURES_CHANNEL_BOOK_TICKER "futures.book_ticker"
#define CCAPI_WEBSOCKET_GATEIO_PERPETUAL_FUTURES_CHANNEL_ORDER_BOOK "futures.order_book"
#define CCAPI_WEBSOCKET_GATEIO_PERPETUAL_FUTURES_CHANNEL_CANDLESTICKS "futures.candlesticks"
#define CCAPI_WEBSOCKET_CRYPTOCOM_CHANNEL_TRADE "trade.{instrument_name}"
#define CCAPI_WEBSOCKET_CRYPTOCOM_CHANNEL_BOOK "book.{instrument_name}.{depth}"
#define CCAPI_WEBSOCKET_BYBIT_CHANNEL_TRADE "trade.{symbol}"
Expand All @@ -337,6 +342,7 @@
#define CCAPI_WEBSOCKET_ASCENDEX_CHANNEL_TRADES "trades"
#define CCAPI_WEBSOCKET_ASCENDEX_CHANNEL_BBO "bbo"
#define CCAPI_WEBSOCKET_ASCENDEX_CHANNEL_DEPTH "depth"
#define CCAPI_WEBSOCKET_ASCENDEX_CHANNEL_BAR "bar"
#define CCAPI_WEBSOCKET_BITGET_BASE_CHANNEL_TRADES "trade"
#define CCAPI_WEBSOCKET_BITGET_BASE_CHANNEL_BOOKS "books"
#define CCAPI_WEBSOCKET_BITGET_BASE_CHANNEL_BOOKS1 "books1"
Expand Down
8 changes: 7 additions & 1 deletion include/ccapi_cpp/ccapi_session_configs.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class SessionConfigs CCAPI_FINAL {
std::map<std::string, std::string> fieldWebsocketChannelMapKraken = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_KRAKEN_CHANNEL_TRADE},
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_KRAKEN_CHANNEL_BOOK},
{CCAPI_CANDLESTICK, CCAPI_WEBSOCKET_KRAKEN_CHANNEL_OHLC},
};
std::map<std::string, std::string> fieldWebsocketChannelMapKrakenFutures = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_KRAKEN_FUTURES_CHANNEL_TRADE},
Expand All @@ -58,7 +59,8 @@ class SessionConfigs CCAPI_FINAL {
};
std::map<std::string, std::string> fieldWebsocketChannelMapBitfinex = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_BITFINEX_CHANNEL_TRADES},
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_BITFINEX_CHANNEL_BOOK},
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_BITFINEX_CHANNEL_BOOKS},
{CCAPI_CANDLESTICK, CCAPI_WEBSOCKET_BITFINEX_CHANNEL_CANDLES},
};
std::map<std::string, std::string> fieldWebsocketChannelMapBitmex = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_BITMEX_CHANNEL_TRADE},
Expand Down Expand Up @@ -110,6 +112,7 @@ class SessionConfigs CCAPI_FINAL {
std::map<std::string, std::string> fieldWebsocketChannelMapKucoin = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_KUCOIN_CHANNEL_MARKET_MATCH},
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_KUCOIN_CHANNEL_MARKET_LEVEL2},
{CCAPI_CANDLESTICK, CCAPI_WEBSOCKET_KUCOIN_CHANNEL_MARKET_KLINES},
};
std::map<std::string, std::string> fieldWebsocketChannelMapKucoinFutures = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_KUCOIN_FUTURES_CHANNEL_MARKET_MATCH},
Expand All @@ -130,10 +133,12 @@ class SessionConfigs CCAPI_FINAL {
std::map<std::string, std::string> fieldWebsocketChannelMapGateio = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_GATEIO_CHANNEL_TRADES},
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_GATEIO_CHANNEL_ORDER_BOOK},
{CCAPI_CANDLESTICK, CCAPI_WEBSOCKET_GATEIO_CHANNEL_CANDLESTICKS},
};
std::map<std::string, std::string> fieldWebsocketChannelMapGateioPerpetualFutures = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_GATEIO_PERPETUAL_FUTURES_CHANNEL_TRADES},
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_GATEIO_PERPETUAL_FUTURES_CHANNEL_ORDER_BOOK},
{CCAPI_CANDLESTICK, CCAPI_WEBSOCKET_GATEIO_PERPETUAL_FUTURES_CHANNEL_CANDLESTICKS},
};
std::map<std::string, std::string> fieldWebsocketChannelMapCryptocom = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_CRYPTOCOM_CHANNEL_TRADE},
Expand All @@ -152,6 +157,7 @@ class SessionConfigs CCAPI_FINAL {
std::map<std::string, std::string> fieldWebsocketChannelMapAscendex = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_ASCENDEX_CHANNEL_TRADES},
{CCAPI_MARKET_DEPTH, CCAPI_WEBSOCKET_ASCENDEX_CHANNEL_DEPTH},
{CCAPI_CANDLESTICK, CCAPI_WEBSOCKET_ASCENDEX_CHANNEL_BAR},
};
std::map<std::string, std::string> fieldWebsocketChannelMapBitget = {
{CCAPI_TRADE, CCAPI_WEBSOCKET_BITGET_BASE_CHANNEL_TRADES},
Expand Down
10 changes: 8 additions & 2 deletions include/ccapi_cpp/service/ccapi_market_data_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,15 +473,21 @@ class MarketDataService : public Service {
std::string& exchangeSubscriptionId = marketDataMessage.exchangeSubscriptionId;
CCAPI_LOGGER_TRACE("this->channelIdSymbolIdByConnectionIdExchangeSubscriptionIdMap = " +
toString(this->channelIdSymbolIdByConnectionIdExchangeSubscriptionIdMap));
CCAPI_LOGGER_TRACE("this->channelIdSymbolIdByConnectionIdExchangeSubscriptionIdMap.at(wsConnection.id) = " +
toString(this->channelIdSymbolIdByConnectionIdExchangeSubscriptionIdMap.at(wsConnection.id)));
CCAPI_LOGGER_TRACE("exchangeSubscriptionId = " + exchangeSubscriptionId);
std::string& channelId =
this->channelIdSymbolIdByConnectionIdExchangeSubscriptionIdMap.at(wsConnection.id).at(exchangeSubscriptionId).at(CCAPI_CHANNEL_ID);
CCAPI_LOGGER_TRACE("channelId = " + toString(channelId));
std::string& symbolId =
this->channelIdSymbolIdByConnectionIdExchangeSubscriptionIdMap.at(wsConnection.id).at(exchangeSubscriptionId).at(CCAPI_SYMBOL_ID);
CCAPI_LOGGER_TRACE("symbolId = " + toString(symbolId));
CCAPI_LOGGER_TRACE("this->fieldByConnectionIdChannelIdSymbolIdMap = " + toString(this->fieldByConnectionIdChannelIdSymbolIdMap));
CCAPI_LOGGER_TRACE("this->fieldByConnectionIdChannelIdSymbolIdMap.at(wsConnection.id) = " +
toString(this->fieldByConnectionIdChannelIdSymbolIdMap.at(wsConnection.id)));
auto& field = this->fieldByConnectionIdChannelIdSymbolIdMap.at(wsConnection.id).at(channelId).at(symbolId);
CCAPI_LOGGER_TRACE("this->optionMapByConnectionIdChannelIdSymbolIdMap = " + toString(this->optionMapByConnectionIdChannelIdSymbolIdMap));
CCAPI_LOGGER_TRACE("wsConnection = " + toString(wsConnection));
CCAPI_LOGGER_TRACE("channelId = " + toString(channelId));
CCAPI_LOGGER_TRACE("symbolId = " + toString(symbolId));
auto& optionMap = this->optionMapByConnectionIdChannelIdSymbolIdMap.at(wsConnection.id).at(channelId).at(symbolId);
CCAPI_LOGGER_TRACE("optionMap = " + toString(optionMap));
auto& correlationIdList = this->correlationIdListByConnectionIdChannelIdSymbolIdMap.at(wsConnection.id).at(channelId).at(symbolId);
Expand Down
21 changes: 21 additions & 0 deletions include/ccapi_cpp/service/ccapi_market_data_service_ascendex.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class MarketDataServiceAscendex : public MarketDataService {
if (marketDepthRequested == 1) {
channelId = CCAPI_WEBSOCKET_ASCENDEX_CHANNEL_BBO;
}
} else if (field == CCAPI_CANDLESTICK) {
std::string interval = std::to_string(std::stoi(optionMap.at(CCAPI_CANDLESTICK_INTERVAL_SECONDS)) / 60);
channelId += ":" + interval;
}
}
#ifdef CCAPI_LEGACY_USE_WEBSOCKETPP
Expand Down Expand Up @@ -160,6 +163,24 @@ class MarketDataServiceAscendex : public MarketDataService {
marketDataMessage.data[MarketDataMessage::DataType::TRADE].emplace_back(std::move(dataPoint));
marketDataMessageList.emplace_back(std::move(marketDataMessage));
}
} else if (m == "bar") {
std::string channelId = m;
const rj::Value& data = document["data"];
std::string symbolId = document["s"].GetString();
std::string exchangeSubscriptionId = channelId + ":" + std::string(data["i"].GetString()) + ":" + symbolId;
MarketDataMessage marketDataMessage;
marketDataMessage.type = MarketDataMessage::Type::MARKET_DATA_EVENTS_CANDLESTICK;
marketDataMessage.recapType = MarketDataMessage::RecapType::NONE;
marketDataMessage.exchangeSubscriptionId = exchangeSubscriptionId;
marketDataMessage.tp = TimePoint(std::chrono::milliseconds(std::stoll(data["ts"].GetString())));
MarketDataMessage::TypeForDataPoint dataPoint;
dataPoint.insert({MarketDataMessage::DataFieldType::OPEN_PRICE, data["o"].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::HIGH_PRICE, data["h"].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::LOW_PRICE, data["l"].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::CLOSE_PRICE, data["c"].GetString()});
dataPoint.insert({MarketDataMessage::DataFieldType::VOLUME, data["v"].GetString()});
marketDataMessage.data[MarketDataMessage::DataType::CANDLESTICK].emplace_back(std::move(dataPoint));
marketDataMessageList.emplace_back(std::move(marketDataMessage));
} else if (m == "ping") {
ErrorCode ec;
#ifdef CCAPI_LEGACY_USE_WEBSOCKETPP
Expand Down
Loading

0 comments on commit 89b5e22

Please sign in to comment.