Skip to content

Commit

Permalink
Merge pull request #27 from crypto-chassis/execution_management
Browse files Browse the repository at this point in the history
Execution management
  • Loading branch information
cryptochassis authored Dec 8, 2020
2 parents bcf5fd2 + eee93b1 commit 1dc5b9c
Show file tree
Hide file tree
Showing 31 changed files with 935 additions and 348 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/build_cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ env:

jobs:
build:
timeout-minutes: 5
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
Expand Down Expand Up @@ -152,7 +153,8 @@ jobs:
execute_process(
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
-S ./include
-DBUILD_BUILD_TEST=ON
-S test
-B build
-D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE}
-G Ninja
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/cpplint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
- master
jobs:
cpplint:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
- master
jobs:
release:
timeout-minutes: 5
name: release
runs-on: ubuntu-latest
steps:
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,15 @@ For a specific exchange and instrument, whenever the top 10 bids' or asks' price
```
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Logger* Logger::logger = 0; // This line is needed.
Logger* Logger::logger = nullptr; // This line is needed.
class MyEventHandler : public EventHandler {
public:
bool processEvent(const Event& event, Session *session) override {
if (event.getType() == Event::Type::SUBSCRIPTION_DATA) {
for (const auto & message : event.getMessageList()) {
if (message.getRecapType() == Message::RecapType::NONE) {
std::cout << std::string("Top ") + CCAPI_EXCHANGE_VALUE_MARKET_DEPTH_MAX_DEFAULT + " bids and asks at " + UtilTime::getISOTimestamp(message.getTime()) + " are:" << std::endl;
std::cout << std::string("Best bid and ask at ") + UtilTime::getISOTimestamp(message.getTime()) + " are:"
<< std::endl;
for (const auto & element : message.getElementList()) {
const std::map<std::string, std::string>& elementNameValueMap = element.getNameValueMap();
std::cout << " " + toString(elementNameValueMap) << std::endl;
Expand Down Expand Up @@ -190,7 +192,7 @@ std::vector<Event> eventList = session.eventQueue.purge();
Add one of the following macros in the compiler command line: ENABLE_LOG_TRACE, ENABLE_LOG_DEBUG, ENABLE_LOG_INFO, ENABLE_LOG_WARN, ENABLE_LOG_ERROR, ENABLE_LOG_FATAL. Extend a subclass, e.g. MyLogger, from class Logger and override method logMessage. Assign a MyLogger pointer to Logger::logger.
```
namespace ccapi {
Logger* Logger::logger = 0; // This line is needed.
Logger* Logger::logger = nullptr; // This line is needed.
class MyLogger final: public Logger {
public:
virtual void logMessage(Logger::Severity severity, std::thread::id threadId,
Expand Down
4 changes: 3 additions & 1 deletion example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
cmake_minimum_required(VERSION 3.14)
project(example)
set(NAME example)
project(${NAME})
set(CMAKE_CXX_STANDARD 14)
if(NOT APPLE AND NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
Expand All @@ -16,4 +17,5 @@ include_directories(${CCAPI_CPP_PROJECT_DIR}/include ${WEBSOCKETPP_INCLUDE_DIR}
link_libraries(OpenSSL::Crypto OpenSSL::SSL)
add_subdirectory(src/market_data_simple)
add_subdirectory(src/market_data_advanced)
add_subdirectory(src/execution_management_simple)
add_subdirectory(src/sample_market_making)
5 changes: 5 additions & 0 deletions example/src/execution_management_simple/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
set(NAME execution_management_simple)
project(${NAME})
add_definitions(-DENABLE_SERVICE_EXECUTION_MANAGEMENT)
add_definitions(-DENABLE_EXCHANGE_BINANCE_US)
add_executable(${NAME} main.cpp)
137 changes: 87 additions & 50 deletions example/src/execution_management_simple/main.cpp
Original file line number Diff line number Diff line change
@@ -1,50 +1,87 @@
// #include "ccapi_cpp/ccapi_session.h"
// namespace ccapi {
// class ExampleLogger final: public Logger {
// public:
// void logMessage(Logger::Severity severity, std::thread::id threadId,
// std::chrono::system_clock::time_point time,
// std::string fileName, int lineNumber,
// std::string message) override {
// lock.lock();
// std::cout << threadId << ": [" << UtilTime::getISOTimestamp(time) << "] {"
// << fileName << ":" << lineNumber << "} "
// << Logger::severityToString(severity) << std::string(8, ' ') << message
// << std::endl;
// lock.unlock();
// }
// private:
// std::mutex lock;
// };
// Logger* Logger::logger = 0; // This line is needed.
// class MyEventHandler : public EventHandler {
// bool processEvent(const Event& event, Session *session) override {
// CCAPI_LOGGER_TRACE(toString(event));
// return true;
// }
// };
// } /* namespace ccapi */
// int main(int argc, char** argv) {
// using namespace ccapi; // NOLINT(build/namespaces)
// ExampleLogger exampleLogger;
// Logger::logger = &exampleLogger;
// SessionOptions sessionOptions;
// SessionConfigs sessionConfigs;
// MyEventHandler eventHandler;
// Session session(sessionOptions, sessionConfigs, &eventHandler);
// Request::Operation operation = Request::Operation::CREATE_ORDER;
// std::map<std::string, std::string> credential = {
// {BINANCE_US_API_KEY, UtilSystem::getEnvAsString(BINANCE_US_API_KEY)},
// {BINANCE_US_API_SECRET, UtilSystem::getEnvAsString(BINANCE_US_API_SECRET)}
// };
// CorrelationId correlationId("this is my correlation id");
// Request request(operation, credential, CCAPI_EXCHANGE_NAME_BINANCE_US, "ETHUSD", correlationId);
// request.setParam(CCAPI_EM_SIDE, CCAPI_EM_SIDE_BUY);
// request.setParam(CCAPI_EM_QUANTITY, "0.04");
// request.setParam(CCAPI_EM_LIMIT_PRICE, "300");
// Queue<Event> eventQueue;
// session.sendRequest(request, &eventQueue);
// std::vector<Event> eventList = eventQueue.purge();
// CCAPI_LOGGER_TRACE("eventList = "+toString(eventList));
// return EXIT_SUCCESS;
// }
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Logger* Logger::logger = nullptr; // This line is needed.
class MyEventHandler : public EventHandler {
bool processEvent(const Event& event, Session *session) override {
std::cout << "Received an event: " + toString(event) << std::endl;
return true;
}
};
} /* namespace ccapi */
int main(int argc, char** argv) {
using namespace ccapi; // NOLINT(build/namespaces)
std::vector<std::string> modeList = { "create_order", "cancel_order", "get_order", "get_open_orders",
"cancel_open_orders" };
if (argc < 2 || std::find(modeList.begin(), modeList.end(), argv[1]) == modeList.end()) {
std::cerr << "Please provide the first command line argument from this list: " + toString(modeList) << std::endl;
return EXIT_FAILURE;
}
std::string mode(argv[1]);
std::string key = UtilSystem::getEnvAsString("BINANCE_US_API_KEY");
if (key.empty()) {
std::cerr << "Please provide environment variable BINANCE_US_API_KEY" << std::endl;
return EXIT_FAILURE;
}
std::string secret = UtilSystem::getEnvAsString("BINANCE_US_API_SECRET");
if (secret.empty()) {
std::cerr << "Please provide environment variable BINANCE_US_API_SECRET" << std::endl;
return EXIT_FAILURE;
}
std::map<std::string, std::string> credential = { { CCAPI_BINANCE_US_API_KEY, key }, { CCAPI_BINANCE_US_API_SECRET,
secret } };
SessionOptions sessionOptions;
SessionConfigs sessionConfigs;
MyEventHandler eventHandler;
Session session(sessionOptions, sessionConfigs, &eventHandler);
Queue<Event> eventQueue;
if (mode == "create_order") {
if (argc != 6) {
std::cerr << "Usage: <program name> create_order <symbol> <buy or sell> <order quantity> <limit price>\n"
<< "Example:\n" << " main create_order BTCUSD buy 0.0005 20000" << std::endl;
return EXIT_FAILURE;
}
Request request(Request::Operation::CREATE_ORDER, credential, "binance-us", argv[2]);
request.setParam("SIDE", strcmp(argv[3], "buy") == 0 ? "BUY" : "SELL");
request.setParam("QUANTITY", argv[4]);
request.setParam("LIMIT_PRICE", argv[5]);
session.sendRequest(request, &eventQueue);
} else if (mode == "cancel_order") {
if (argc != 4) {
std::cerr << "Usage: <program name> cancel_order <symbol> <order id>\n" << "Example:\n"
<< " main cancel_order BTCUSD 4" << std::endl;
return EXIT_FAILURE;
}
Request request(Request::Operation::CANCEL_ORDER, credential, "binance-us", argv[2]);
request.setParam("ORDER_ID", argv[3]);
session.sendRequest(request, &eventQueue);
} else if (mode == "get_order") {
if (argc != 4) {
std::cerr << "Usage: <program name> get_order <symbol> <order id>\n" << "Example:\n"
<< " main get_order BTCUSD 4" << std::endl;
return EXIT_FAILURE;
}
Request request(Request::Operation::GET_ORDER, credential, "binance-us", argv[2]);
request.setParam("ORDER_ID", argv[3]);
session.sendRequest(request, &eventQueue);
} else if (mode == "get_open_orders") {
if (argc != 3) {
std::cerr << "Usage: <program name> get_open_orders <symbol>\n" << "Example:\n"
<< " main get_open_orders BTCUSD" << std::endl;
return EXIT_FAILURE;
}
Request request(Request::Operation::GET_OPEN_ORDERS, credential, "binance-us", argv[2]);
session.sendRequest(request, &eventQueue);
} else if (mode == "cancel_open_orders") {
if (argc != 3) {
std::cerr << "Usage: <program name> cancel_open_orders <symbol>\n" << "Example:\n"
<< " main cancel_open_orders BTCUSD" << std::endl;
return EXIT_FAILURE;
}
Request request(Request::Operation::CANCEL_OPEN_ORDERS, credential, "binance-us", argv[2]);
session.sendRequest(request, &eventQueue);
}
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
std::cout << "Bye" << std::endl;
return EXIT_SUCCESS;
}
6 changes: 3 additions & 3 deletions example/src/market_data_advanced/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
project(market_data_advanced)
set(NAME market_data_advanced)
project(${NAME})
add_definitions(-DENABLE_SERVICE_MARKET_DATA)
add_definitions(-DENABLE_EXCHANGE_COINBASE)
add_definitions(-DENABLE_EXCHANGE_BINANCE_US)
file(GLOB SOURCES main.cpp)
add_executable(market_data_advanced ${SOURCES})
add_executable(${NAME} main.cpp)
37 changes: 16 additions & 21 deletions example/src/market_data_advanced/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Logger* Logger::logger = 0; // This line is needed.
Logger* Logger::logger = nullptr; // This line is needed.
class MyEventHandler : public EventHandler {
public:
bool processEvent(const Event& event, Session *session) override {
Expand All @@ -11,19 +11,13 @@ class MyEventHandler : public EventHandler {
} /* namespace ccapi */
int main(int argc, char **argv) {
using namespace ccapi; // NOLINT(build/namespaces)
std::vector<std::string> modeList = {
"specify_correlation_id",
"normalize_instrument_name",
"multiple_exchanges_instruments",
"specify_market_depth",
"receive_events_at_periodic_intervals",
std::vector<std::string> modeList = { "specify_correlation_id", "normalize_instrument_name",
"multiple_exchanges_instruments", "specify_market_depth", "receive_events_at_periodic_intervals",
"receive_events_at_periodic_intervals_including_when_the_market_depth_snapshot_has_not_changed",
"dispatch_events_to_multiple_threads",
"handle_events_synchronously"
};
"dispatch_events_to_multiple_threads", "handle_events_synchronously" };
if (argc != 2 || std::find(modeList.begin(), modeList.end(), argv[1]) == modeList.end()) {
std::cout << "Please provide one command line argument from this list: "+toString(modeList) << std::endl;
return 0;
std::cerr << "Please provide one command line argument from this list: " + toString(modeList) << std::endl;
return EXIT_FAILURE;
}
std::string mode(argv[1]);
if (mode == "specify_correlation_id") {
Expand All @@ -33,7 +27,7 @@ int main(int argc, char **argv) {
Session session(sessionOptions, sessionConfigs, &eventHandler);
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH", "", "cool correlation id");
session.subscribe(subscription);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
} else if (mode == "normalize_instrument_name") {
SessionOptions sessionOptions;
Expand All @@ -45,7 +39,7 @@ int main(int argc, char **argv) {
Session session(sessionOptions, sessionConfigs, &eventHandler);
Subscription subscription("coinbase", coolName, "MARKET_DEPTH");
session.subscribe(subscription);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
} else if (mode == "multiple_exchanges_instruments") {
SessionOptions sessionOptions;
Expand All @@ -58,7 +52,7 @@ int main(int argc, char **argv) {
Subscription subscription_2("binance-us", "ethusd", "MARKET_DEPTH", "", "binance-us|eth_usd");
subscriptionList.push_back(subscription_2);
session.subscribe(subscriptionList);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
} else if (mode == "specify_market_depth") {
SessionOptions sessionOptions;
Expand All @@ -67,7 +61,7 @@ int main(int argc, char **argv) {
Session session(sessionOptions, sessionConfigs, &eventHandler);
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH", "MARKET_DEPTH_MAX=2");
session.subscribe(subscription);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
} else if (mode == "receive_events_at_periodic_intervals") {
SessionOptions sessionOptions;
Expand All @@ -76,16 +70,17 @@ int main(int argc, char **argv) {
Session session(sessionOptions, sessionConfigs, &eventHandler);
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH", "CONFLATE_INTERVAL_MILLISECONDS=1000");
session.subscribe(subscription);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
} else if (mode == "receive_events_at_periodic_intervals_including_when_the_market_depth_snapshot_has_not_changed") {
SessionOptions sessionOptions;
SessionConfigs sessionConfigs;
MyEventHandler eventHandler;
Session session(sessionOptions, sessionConfigs, &eventHandler);
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH", "CONFLATE_INTERVAL_MILLISECONDS=1000&CONFLATE_GRACE_PERIOD_MILLISECONDS=0");
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH",
"CONFLATE_INTERVAL_MILLISECONDS=1000&CONFLATE_GRACE_PERIOD_MILLISECONDS=0");
session.subscribe(subscription);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
} else if (mode == "dispatch_events_to_multiple_threads") {
SessionOptions sessionOptions;
Expand All @@ -95,7 +90,7 @@ int main(int argc, char **argv) {
Session session(sessionOptions, sessionConfigs, &eventHandler, &eventDispatcher);
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH");
session.subscribe(subscription);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::this_thread::sleep_for(std::chrono::seconds(10));
session.stop();
eventDispatcher.stop();
} else if (mode == "handle_events_synchronously") {
Expand All @@ -104,7 +99,7 @@ int main(int argc, char **argv) {
Session session(sessionOptions, sessionConfigs);
Subscription subscription("coinbase", "BTC-USD", "MARKET_DEPTH");
session.subscribe(subscription);
std::this_thread::sleep_for(std::chrono::seconds(5));
std::this_thread::sleep_for(std::chrono::seconds(10));
std::vector<Event> eventList = session.eventQueue.purge();
for (const auto & event : eventList) {
std::cout << toString(event) + "\n" << std::endl;
Expand Down
6 changes: 3 additions & 3 deletions example/src/market_data_simple/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
project(market_data_simple)
set(NAME market_data_simple)
project(${NAME})
add_definitions(-DENABLE_SERVICE_MARKET_DATA)
add_definitions(-DENABLE_EXCHANGE_COINBASE)
file(GLOB SOURCES main.cpp)
add_executable(market_data_simple ${SOURCES})
add_executable(${NAME} main.cpp)
5 changes: 3 additions & 2 deletions example/src/market_data_simple/main.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Logger* Logger::logger = 0; // This line is needed.
Logger* Logger::logger = nullptr; // This line is needed.
class MyEventHandler : public EventHandler {
public:
bool processEvent(const Event& event, Session *session) override {
if (event.getType() == Event::Type::SUBSCRIPTION_DATA) {
for (const auto & message : event.getMessageList()) {
if (message.getRecapType() == Message::RecapType::NONE) {
std::cout << std::string("Best bid and ask at " + UtilTime::getISOTimestamp(message.getTime()) + " are:" << std::endl;
std::cout << std::string("Best bid and ask at ") + UtilTime::getISOTimestamp(message.getTime()) + " are:"
<< std::endl;
for (const auto & element : message.getElementList()) {
const std::map<std::string, std::string>& elementNameValueMap = element.getNameValueMap();
std::cout << " " + toString(elementNameValueMap) << std::endl;
Expand Down
6 changes: 3 additions & 3 deletions example/src/sample_market_making/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
project(sample_market_making)
set(NAME sample_market_making)
project(${NAME})
add_definitions(-DENABLE_SERVICE_MARKET_DATA)
add_definitions(-DENABLE_SERVICE_EXECUTION_MANAGEMENT)
add_definitions(-DENABLE_EXCHANGE_BINANCE_US)
file(GLOB SOURCES main.cpp)
add_executable(sample_market_making ${SOURCES})
add_executable(${NAME} main.cpp)
Loading

0 comments on commit 1dc5b9c

Please sign in to comment.