Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release #437

Merged
merged 6 commits into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +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.

# Notifications:
* New features: added REST endpoints for fetching historical public trades, historical/recent candlesticks, and market depth (i.e. order book snapshot).
* Small breaking change to correct an English typo: In `SessionOptions`, the substring "MilliSeconds" has been renamed to "Milliseconds".

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
Expand Down Expand Up @@ -279,8 +280,8 @@ Received an event:
]
Bye
```
* Request operation types: `GET_INSTRUMENT`, `GET_INSTRUMENTS`, `GET_RECENT_TRADES`, `GET_RECENT_AGG_TRADES`(only applicable to binance family: https://binance-docs.github.io/apidocs/spot/en/#compressed-aggregate-trades-list).
* Request parameter names: `LIMIT`, `INSTRUMENT_TYPE`. Instead of these convenient names you can also choose to use arbitrary parameter names and they will be passed to the exchange's native API. See [this example](example/src/market_data_advanced_request/main.cpp).
* Request operation types: `GET_INSTRUMENT`, `GET_INSTRUMENTS`, `GET_RECENT_TRADES`, `GET_HISTORICAL_TRADES`, `GET_RECENT_CANDLESTICKS`, `GET_HISTORICAL_CANDLESTICKS`, `GET_RECENT_AGG_TRADES`, `GET_HISTORICAL_AGG_TRADES`(only applicable to binance family: https://binance-docs.github.io/apidocs/spot/en/#compressed-aggregate-trades-list), ``.
* Request parameter names: `LIMIT`, `INSTRUMENT_TYPE`, `CANDLESTICK_INTERVAL_SECONDS`, `START_TIME_SECONDS`, `END_TIME_SECONDS`, `START_TRADE_ID`, `END_TRADE_ID`, `START_AGG_TRADE_ID`, `END_AGG_TRADE_ID`. Instead of these convenient names you can also choose to use arbitrary parameter names and they will be passed to the exchange's native API. See [this example](example/src/market_data_advanced_request/main.cpp).
* Message's `time` represents the exchange's reported timestamp. Its `timeReceived` represents the library's receiving timestamp. `time` can be retrieved by `getTime` method and `timeReceived` can be retrieved by `getTimeReceived` method. (For non-C++, please use `getTimeUnix` and `getTimeReceivedUnix` methods or `getTimeISO` and `getTimeReceivedISO` methods).

**Objective 2:**
Expand Down Expand Up @@ -338,7 +339,7 @@ Best bid and ask at 2020-07-27T23:56:51.884855000Z are:
Best bid and ask at 2020-07-27T23:56:51.935993000Z are:
...
```
* Subscription fields: `MARKET_DEPTH`, `TRADE`, `AGG_TRADE`(only applicable to binance family: https://binance-docs.github.io/apidocs/spot/en/#aggregate-trade-streams).
* Subscription fields: `MARKET_DEPTH`, `TRADE`, `CANDLESTICK`, `AGG_TRADE`(only applicable to binance family: https://binance-docs.github.io/apidocs/spot/en/#aggregate-trade-streams).

### Advanced Market Data

Expand Down
2 changes: 1 addition & 1 deletion app/src/single_order_execution/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ int main(int argc, char** argv) {
eventHandler.promisePtr = promisePtr;
#ifndef CCAPI_APP_IS_BACKTEST
SessionOptions sessionOptions;
sessionOptions.httpConnectionPoolIdleTimeoutMilliSeconds = 1;
sessionOptions.httpConnectionPoolIdleTimeoutMilliseconds = 1;
sessionOptions.httpMaxNumRetry = 0;
sessionOptions.httpMaxNumRedirect = 0;
SessionConfigs sessionConfigs;
Expand Down
2 changes: 1 addition & 1 deletion app/src/spot_market_making/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ int main(int argc, char** argv) {
eventHandler.promisePtr = promisePtr;
#ifndef CCAPI_APP_IS_BACKTEST
SessionOptions sessionOptions;
sessionOptions.httpConnectionPoolIdleTimeoutMilliSeconds = 1 + eventHandler.accountBalanceRefreshWaitSeconds;
sessionOptions.httpConnectionPoolIdleTimeoutMilliseconds = 1 + eventHandler.accountBalanceRefreshWaitSeconds;
sessionOptions.httpMaxNumRetry = 0;
sessionOptions.httpMaxNumRedirect = 0;
SessionConfigs sessionConfigs;
Expand Down
4 changes: 2 additions & 2 deletions example/src/fix_advanced/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
SessionOptions sessionOptions;
sessionOptions.heartbeatFixIntervalMilliSeconds = 30000; // Note the unit is millisecond
sessionOptions.heartbeatFixTimeoutMilliSeconds = 5000; // Note the unit is millisecond, should be less than heartbeatFixIntervalMilliSeconds
sessionOptions.heartbeatFixIntervalMilliseconds = 30000; // Note the unit is millisecond
sessionOptions.heartbeatFixTimeoutMilliseconds = 5000; // Note the unit is millisecond, should be less than heartbeatFixIntervalMilliseconds
SessionConfigs sessionConfigs;
MyEventHandler eventHandler;
Session session(sessionOptions, sessionConfigs, &eventHandler);
Expand Down
15 changes: 15 additions & 0 deletions include/ccapi_cpp/ccapi_macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,21 @@
#ifndef CCAPI_LIMIT
#define CCAPI_LIMIT "LIMIT"
#endif
#ifndef CCAPI_START_TRADE_ID
#define CCAPI_START_TRADE_ID "START_TRADE_ID"
#endif
#ifndef CCAPI_END_TRADE_ID
#define CCAPI_END_TRADE_ID "END_TRADE_ID"
#endif
#ifndef CCAPI_START_AGG_TRADE_ID
#define CCAPI_START_AGG_TRADE_ID "START_AGG_TRADE_ID"
#endif
#ifndef CCAPI_START_TIME_SECONDS
#define CCAPI_START_TIME_SECONDS "START_TIME_SECONDS"
#endif
#ifndef CCAPI_END_TIME_SECONDS
#define CCAPI_END_TIME_SECONDS "END_TIME_SECONDS"
#endif
#ifndef CCAPI_BASE_ASSET
#define CCAPI_BASE_ASSET "BASE_ASSET"
#endif
Expand Down
20 changes: 20 additions & 0 deletions include/ccapi_cpp/ccapi_message.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ class Message CCAPI_FINAL {
GET_ACCOUNT_BALANCES,
GET_ACCOUNT_POSITIONS,
GET_RECENT_TRADES,
GET_HISTORICAL_TRADES,
GET_RECENT_AGG_TRADES,
GET_HISTORICAL_AGG_TRADES,
GET_RECENT_CANDLESTICKS,
GET_HISTORICAL_CANDLESTICKS,
GET_MARKET_DEPTH,
GET_INSTRUMENT,
GET_INSTRUMENTS,
RESPONSE_ERROR,
Expand Down Expand Up @@ -147,9 +152,24 @@ class Message CCAPI_FINAL {
case Type::GET_RECENT_TRADES:
output = "GET_RECENT_TRADES";
break;
case Type::GET_HISTORICAL_TRADES:
output = "GET_HISTORICAL_TRADES";
break;
case Type::GET_RECENT_AGG_TRADES:
output = "GET_RECENT_AGG_TRADES";
break;
case Type::GET_HISTORICAL_AGG_TRADES:
output = "GET_HISTORICAL_AGG_TRADES";
break;
case Type::GET_RECENT_CANDLESTICKS:
output = "GET_RECENT_CANDLESTICKS";
break;
case Type::GET_HISTORICAL_CANDLESTICKS:
output = "GET_HISTORICAL_CANDLESTICKS";
break;
case Type::GET_MARKET_DEPTH:
output = "GET_MARKET_DEPTH";
break;
case Type::GET_INSTRUMENT:
output = "GET_INSTRUMENT";
break;
Expand Down
20 changes: 20 additions & 0 deletions include/ccapi_cpp/ccapi_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ class Request CCAPI_FINAL {
GENERIC_PRIVATE_REQUEST = CCAPI_REQUEST_OPERATION_TYPE_GENERIC_PRIVATE_REQUEST,
FIX = CCAPI_REQUEST_OPERATION_TYPE_FIX,
GET_RECENT_TRADES = CCAPI_REQUEST_OPERATION_TYPE_MARKET_DATA,
GET_HISTORICAL_TRADES,
GET_RECENT_AGG_TRADES,
GET_HISTORICAL_AGG_TRADES,
GET_RECENT_CANDLESTICKS,
GET_HISTORICAL_CANDLESTICKS,
GET_MARKET_DEPTH,
GET_INSTRUMENT,
GET_INSTRUMENTS,
CREATE_ORDER = CCAPI_REQUEST_OPERATION_TYPE_EXECUTION_MANAGEMENT_ORDER,
Expand Down Expand Up @@ -61,9 +66,24 @@ class Request CCAPI_FINAL {
case Operation::GET_RECENT_TRADES:
output = "GET_RECENT_TRADES";
break;
case Operation::GET_HISTORICAL_TRADES:
output = "GET_HISTORICAL_TRADES";
break;
case Operation::GET_RECENT_AGG_TRADES:
output = "GET_RECENT_AGG_TRADES";
break;
case Operation::GET_HISTORICAL_AGG_TRADES:
output = "GET_HISTORICAL_AGG_TRADES";
break;
case Operation::GET_RECENT_CANDLESTICKS:
output = "GET_RECENT_CANDLESTICKS";
break;
case Operation::GET_HISTORICAL_CANDLESTICKS:
output = "GET_HISTORICAL_CANDLESTICKS";
break;
case Operation::GET_MARKET_DEPTH:
output = "GET_MARKET_DEPTH";
break;
case Operation::GET_INSTRUMENT:
output = "GET_INSTRUMENT";
break;
Expand Down
14 changes: 7 additions & 7 deletions include/ccapi_cpp/ccapi_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -821,13 +821,13 @@ class Session {
this->sendRequestByWebsocket(x);
}
}
virtual void sendRequest(Request& request, Queue<Event>* eventQueuePtr = nullptr, long delayMilliSeconds = 0) {
virtual void sendRequest(Request& request, Queue<Event>* eventQueuePtr = nullptr, long delayMilliseconds = 0) {
CCAPI_LOGGER_FUNCTION_ENTER;
std::vector<Request> requestList({request});
this->sendRequest(requestList, eventQueuePtr, delayMilliSeconds);
this->sendRequest(requestList, eventQueuePtr, delayMilliseconds);
CCAPI_LOGGER_FUNCTION_EXIT;
}
virtual void sendRequest(std::vector<Request>& requestList, Queue<Event>* eventQueuePtr = nullptr, long delayMilliSeconds = 0) {
virtual void sendRequest(std::vector<Request>& requestList, Queue<Event>* eventQueuePtr = nullptr, long delayMilliseconds = 0) {
CCAPI_LOGGER_FUNCTION_ENTER;
std::vector<std::shared_ptr<std::future<void> > > futurePtrList;
// std::set<std::string> serviceNameExchangeSet;
Expand All @@ -854,7 +854,7 @@ class Session {
// serviceNameExchangeSet.insert(key);
// }
auto now = UtilTime::now();
auto futurePtr = servicePtr->sendRequest(request, !!eventQueuePtr, now, delayMilliSeconds, eventQueuePtr);
auto futurePtr = servicePtr->sendRequest(request, !!eventQueuePtr, now, delayMilliseconds, eventQueuePtr);
if (eventQueuePtr) {
futurePtrList.push_back(futurePtr);
}
Expand Down Expand Up @@ -886,10 +886,10 @@ class Session {
this->onEvent(event, eventQueuePtr);
}
#ifndef SWIG
virtual void setTimer(const std::string& id, long delayMilliSeconds, std::function<void(const boost::system::error_code&)> errorHandler,
virtual void setTimer(const std::string& id, long delayMilliseconds, std::function<void(const boost::system::error_code&)> errorHandler,
std::function<void()> successHandler) {
boost::asio::post(*this->serviceContextPtr->ioContextPtr, [this, id, delayMilliSeconds, errorHandler, successHandler]() {
std::shared_ptr<steady_timer> timerPtr(new steady_timer(*this->serviceContextPtr->ioContextPtr, boost::asio::chrono::milliseconds(delayMilliSeconds)));
boost::asio::post(*this->serviceContextPtr->ioContextPtr, [this, id, delayMilliseconds, errorHandler, successHandler]() {
std::shared_ptr<steady_timer> timerPtr(new steady_timer(*this->serviceContextPtr->ioContextPtr, boost::asio::chrono::milliseconds(delayMilliseconds)));
timerPtr->async_wait([this, id, errorHandler, successHandler](const boost::system::error_code& ec) {
if (this->eventHandler) {
#ifdef CCAPI_USE_SINGLE_THREAD
Expand Down
36 changes: 18 additions & 18 deletions include/ccapi_cpp/ccapi_session_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,44 @@ class SessionOptions CCAPI_FINAL {
", enableCheckPingPongWebsocketProtocolLevel = " + ccapi::toString(enableCheckPingPongWebsocketProtocolLevel) +
", enableCheckPingPongWebsocketApplicationLevel = " + ccapi::toString(enableCheckPingPongWebsocketApplicationLevel) +
", enableCheckHeartbeatFix = " + ccapi::toString(enableCheckHeartbeatFix) +
", pingWebsocketProtocolLevelIntervalMilliSeconds = " + ccapi::toString(pingWebsocketProtocolLevelIntervalMilliSeconds) +
", pongWebsocketProtocolLevelTimeoutMilliSeconds = " + ccapi::toString(pongWebsocketProtocolLevelTimeoutMilliSeconds) +
", pingWebsocketApplicationLevelIntervalMilliSeconds = " + ccapi::toString(pingWebsocketApplicationLevelIntervalMilliSeconds) +
", pongWebsocketApplicationLevelTimeoutMilliSeconds = " + ccapi::toString(pongWebsocketApplicationLevelTimeoutMilliSeconds) +
", heartbeatFixIntervalMilliSeconds = " + ccapi::toString(heartbeatFixIntervalMilliSeconds) +
", heartbeatFixTimeoutMilliSeconds = " + ccapi::toString(heartbeatFixTimeoutMilliSeconds) +
", pingWebsocketProtocolLevelIntervalMilliseconds = " + ccapi::toString(pingWebsocketProtocolLevelIntervalMilliseconds) +
", pongWebsocketProtocolLevelTimeoutMilliseconds = " + ccapi::toString(pongWebsocketProtocolLevelTimeoutMilliseconds) +
", pingWebsocketApplicationLevelIntervalMilliseconds = " + ccapi::toString(pingWebsocketApplicationLevelIntervalMilliseconds) +
", pongWebsocketApplicationLevelTimeoutMilliseconds = " + ccapi::toString(pongWebsocketApplicationLevelTimeoutMilliseconds) +
", heartbeatFixIntervalMilliseconds = " + ccapi::toString(heartbeatFixIntervalMilliseconds) +
", heartbeatFixTimeoutMilliseconds = " + ccapi::toString(heartbeatFixTimeoutMilliseconds) +
", maxEventQueueSize = " + ccapi::toString(maxEventQueueSize) + ", httpMaxNumRetry = " + ccapi::toString(httpMaxNumRetry) +
", httpMaxNumRedirect = " + ccapi::toString(httpMaxNumRedirect) +
", httpRequestTimeoutMilliSeconds = " + ccapi::toString(httpRequestTimeoutMilliSeconds) +
", httpRequestTimeoutMilliseconds = " + ccapi::toString(httpRequestTimeoutMilliseconds) +
", httpConnectionPoolMaxSize = " + ccapi::toString(httpConnectionPoolMaxSize) +
", httpConnectionPoolIdleTimeoutMilliSeconds = " + ccapi::toString(httpConnectionPoolIdleTimeoutMilliSeconds) +
", httpConnectionPoolIdleTimeoutMilliseconds = " + ccapi::toString(httpConnectionPoolIdleTimeoutMilliseconds) +
", enableOneHttpConnectionPerRequest = " + ccapi::toString(enableOneHttpConnectionPerRequest) + "]";
return output;
}
// long warnLateEventMaxMilliSeconds{}; // used to print a warning log message if en event arrives late
// long warnLateEventMaxMilliseconds{}; // used to print a warning log message if en event arrives late
bool enableCheckSequence{}; // used to check sequence number discontinuity
bool enableCheckOrderBookChecksum{}; // used to check order book checksum
bool enableCheckOrderBookCrossed{true}; // used to check order book cross, usually this should be set to true
bool enableCheckPingPongWebsocketProtocolLevel{true}; // used to check ping-pong health for exchange connections on websocket protocol level
bool enableCheckPingPongWebsocketApplicationLevel{true}; // used to check ping-pong health for exchange connections on websocket application level
bool enableCheckHeartbeatFix{true}; // used to check heartbeat health for exchange connections on FIX
long pingWebsocketProtocolLevelIntervalMilliSeconds{60000};
long pongWebsocketProtocolLevelTimeoutMilliSeconds{30000}; // should be less than pingWebsocketProtocolLevelIntervalMilliSeconds
long pingWebsocketApplicationLevelIntervalMilliSeconds{60000};
long pongWebsocketApplicationLevelTimeoutMilliSeconds{30000}; // should be less than pingWebsocketApplicationLevelIntervalMilliSeconds
long heartbeatFixIntervalMilliSeconds{60000};
long heartbeatFixTimeoutMilliSeconds{30000}; // should be less than heartbeatFixIntervalMilliSeconds
long pingWebsocketProtocolLevelIntervalMilliseconds{60000};
long pongWebsocketProtocolLevelTimeoutMilliseconds{30000}; // should be less than pingWebsocketProtocolLevelIntervalMilliseconds
long pingWebsocketApplicationLevelIntervalMilliseconds{60000};
long pongWebsocketApplicationLevelTimeoutMilliseconds{30000}; // should be less than pingWebsocketApplicationLevelIntervalMilliseconds
long heartbeatFixIntervalMilliseconds{60000};
long heartbeatFixTimeoutMilliseconds{30000}; // should be less than heartbeatFixIntervalMilliseconds
int maxEventQueueSize{0}; // if set to a positive integer, the event queue will throw an exception when overflown
int httpMaxNumRetry{1};
int httpMaxNumRedirect{1};
long httpRequestTimeoutMilliSeconds{10000};
long httpRequestTimeoutMilliseconds{10000};
int httpConnectionPoolMaxSize{1}; // used to set the maximal number of http connections to be kept in the pool (connections in the pool are idle)
long httpConnectionPoolIdleTimeoutMilliSeconds{0}; // used to purge the http connection pool if all connections in the
long httpConnectionPoolIdleTimeoutMilliseconds{0}; // used to purge the http connection pool if all connections in the
// pool have stayed idle for at least this amount of time
bool enableOneHttpConnectionPerRequest{}; // create a new http connection for each request
#ifdef CCAPI_LEGACY_USE_WEBSOCKETPP
#else
long websocketConnectTimeoutMilliSeconds{10000};
long websocketConnectTimeoutMilliseconds{10000};
#endif
};
} /* namespace ccapi */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
}
that->onFail_(thisWsConnection);
},
this->sessionOptions.httpRequestTimeoutMilliSeconds);
this->sessionOptions.httpRequestTimeoutMilliseconds);
}
void onOpen(wspp::connection_hdl hdl) override {
ExecutionManagementService::onOpen(hdl);
Expand Down Expand Up @@ -138,7 +138,7 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
[wsConnection, that_2 = that->shared_from_base<ExecutionManagementServiceBinanceBase>()](const http::response<http::string_body>& res) {
CCAPI_LOGGER_DEBUG("ping listen key success");
},
that->sessionOptions.httpRequestTimeoutMilliSeconds);
that->sessionOptions.httpRequestTimeoutMilliseconds);
});
}
void onClose(wspp::connection_hdl hdl) override {
Expand Down Expand Up @@ -201,7 +201,7 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
}
that->onFail_(wsConnectionPtr);
},
this->sessionOptions.httpRequestTimeoutMilliSeconds);
this->sessionOptions.httpRequestTimeoutMilliseconds);
}
void onOpen(std::shared_ptr<WsConnection> wsConnectionPtr) override {
ExecutionManagementService::onOpen(wsConnectionPtr);
Expand Down Expand Up @@ -265,7 +265,7 @@ class ExecutionManagementServiceBinanceBase : public ExecutionManagementService
[wsConnectionPtr, that_2 = that->shared_from_base<ExecutionManagementServiceBinanceBase>()](const http::response<http::string_body>& res) {
CCAPI_LOGGER_DEBUG("ping listen key success");
},
that->sessionOptions.httpRequestTimeoutMilliSeconds);
that->sessionOptions.httpRequestTimeoutMilliseconds);
});
this->pingListenKeyTimerMapByConnectionIdMap[wsConnectionPtr->id] = timerPtr;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ class ExecutionManagementServiceBitstamp : public ExecutionManagementService {
}
that->onFail_(thisWsConnection);
},
this->sessionOptions.httpRequestTimeoutMilliSeconds);
this->sessionOptions.httpRequestTimeoutMilliseconds);
}
#else
void prepareConnect(std::shared_ptr<WsConnection> wsConnectionPtr) override {
Expand Down Expand Up @@ -381,7 +381,7 @@ class ExecutionManagementServiceBitstamp : public ExecutionManagementService {
}
that->onFail_(wsConnectionPtr);
},
this->sessionOptions.httpRequestTimeoutMilliSeconds);
this->sessionOptions.httpRequestTimeoutMilliseconds);
}
#endif
std::vector<std::string> createSendStringListFromSubscription(const WsConnection& wsConnection, const Subscription& subscription, const TimePoint& now,
Expand Down
Loading