Skip to content

Commit

Permalink
Merge pull request #413 from crypto-chassis/develop
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
cryptochassis committed Aug 8, 2023
2 parents 717cf96 + 2258a6b commit 9685adf
Show file tree
Hide file tree
Showing 47 changed files with 904 additions and 99 deletions.
18 changes: 11 additions & 7 deletions .github/workflows/test.yml
Expand Up @@ -188,9 +188,11 @@ jobs:
set(ENV{PATH} "$ENV{GITHUB_WORKSPACE}${path_separator}$ENV{PATH}")
if ("$ENV{GITHUB_EVENT_NAME}" STREQUAL "push")
set(ENV{BUILD_TYPE} "Release")
set(ENV{CMAKE_BUILD_TYPE} "Release")
set(ENV{DOTNET_BUILD_CONFIGURATION} "Release")
else()
set(ENV{BUILD_TYPE} "Debug")
set(ENV{CMAKE_BUILD_TYPE} "Debug")
set(ENV{DOTNET_BUILD_CONFIGURATION} "Debug")
endif()
execute_process(
Expand All @@ -199,7 +201,7 @@ jobs:
-DBUILD_TEST_UNIT=ON
-S test
-B test/build
-D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE}
-D CMAKE_BUILD_TYPE=$ENV{CMAKE_BUILD_TYPE}
-G Ninja
-D CMAKE_MAKE_PROGRAM=ninja
# -D CMAKE_C_COMPILER_LAUNCHER=ccache
Expand All @@ -214,7 +216,7 @@ jobs:
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
-S example
-B example/build
-D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE}
-D CMAKE_BUILD_TYPE=$ENV{CMAKE_BUILD_TYPE}
-G Ninja
-D CMAKE_MAKE_PROGRAM=ninja
# -D CMAKE_C_COMPILER_LAUNCHER=ccache
Expand All @@ -230,10 +232,12 @@ jobs:
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
-DBUILD_PYTHON=ON
-DBUILD_JAVA=ON
-DBUILD_CSHARP=ON
-DBUILD_TEST=ON
-S binding
-B binding/build
-D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE}
-D CMAKE_BUILD_TYPE=$ENV{CMAKE_BUILD_TYPE}
-D DOTNET_BUILD_CONFIGURATION=$ENV{DOTNET_BUILD_CONFIGURATION}
-G Ninja
-D CMAKE_MAKE_PROGRAM=ninja
# -D CMAKE_C_COMPILER_LAUNCHER=ccache
Expand All @@ -249,7 +253,7 @@ jobs:
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
-S performance
-B performance/build
-D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE}
-D CMAKE_BUILD_TYPE=$ENV{CMAKE_BUILD_TYPE}
-G Ninja
-D CMAKE_MAKE_PROGRAM=ninja
# -D CMAKE_C_COMPILER_LAUNCHER=ccache
Expand All @@ -264,7 +268,7 @@ jobs:
COMMAND ${{ steps.cmake_and_ninja.outputs.cmake_dir }}/cmake
-S app
-B app/build
-D CMAKE_BUILD_TYPE=$ENV{BUILD_TYPE}
-D CMAKE_BUILD_TYPE=$ENV{CMAKE_BUILD_TYPE}
-G Ninja
-D CMAKE_MAKE_PROGRAM=ninja
# -D CMAKE_C_COMPILER_LAUNCHER=ccache
Expand Down
29 changes: 21 additions & 8 deletions README.md
Expand Up @@ -51,7 +51,7 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
# ccapi
* A header-only C++ library for streaming market data and executing trades directly from cryptocurrency exchanges (i.e. the connections are between your server and the exchange server without anything in-between).
* Bindings for other languages such as Python, Java, and C# are provided.
* Bindings for other languages such as Python, Java, C#, and Go are provided.
* Code closely follows Bloomberg's API: https://www.bloomberg.com/professional/support/api-library/.
* It is ultra fast thanks to very careful optimizations: move semantics, regex optimization, locality of reference, lock contention minimization, etc.
* Supported exchanges:
Expand Down Expand Up @@ -109,7 +109,7 @@
mkdir binding/build
cd binding/build
rm -rf * (if rebuild from scratch)
cmake -DBUILD_PYTHON=ON -DBUILD_VERSION=1.0.0 .. (Use -DBUILD_JAVA=ON if the target language is Java, -DBUILD_CSHARP=ON if the target language is C#)
cmake -DBUILD_PYTHON=ON -DBUILD_VERSION=1.0.0 .. (Use -DBUILD_JAVA=ON if the target language is Java, -DBUILD_CSHARP=ON if the target language is C#, -DBUILD_GO=ON if the target language is Go)
cmake --build .
```
* The packaged build artifacts are located in the `binding/build/<language>/packaging/<BUILD_VERSION>` directory. SWIG generated raw files and build artifacts are located in the `binding/build/<language>/ccapi_binding_<language>` directory.
Expand Down Expand Up @@ -177,6 +177,19 @@ env LD_LIBRARY_PATH="$LD_LIBRARY_PATH:../../../build/csharp/packaging/1.0.0" dot
* "error CS0246: The type or namespace name 'ccapi' could not be found". Check that you aren't missing the ccapi assembly reference.
* "System.DllNotFoundException: Unable to load shared library 'ccapi_binding_csharp.so' or one of its dependencies.". Check that environment variable `LD_LIBRARY_PATH` includes `binding/build/csharp/packaging/1.0.0`.

[Go](binding/go/example)
* Go API is nearly identical to C++ API and covers nearly all the functionalities from C++ API.
* Build and install the Go binding as shown [above](#non-c).
* Inside a concrete example directory (e.g. binding/go/example/market_data_simple_subscription), run
```
go clean (if rebuild from scratch)
source ../../../build/go/packaging/1.0.0/export_compiler_options.sh (this step is important)
go build .
./main
```
* Troubleshoot:
* Some C/C++ header files not found. Check that you sourced the export_compiler_options.sh file which provides important environment variables needed by the cgo tool.

## Documentations

### Simple Market Data
Expand All @@ -187,7 +200,7 @@ For a specific exchange and instrument, get recents trades.

**Code 1:**

[C++](example/src/market_data_simple_request/main.cpp) / [Python](binding/python/example/market_data_simple_request/main.py) / [Java](binding/java/example/market_data_simple_request/Main.java) / [C#](binding/csharp/example/market_data_simple_request/MainProgram.cs)
[C++](example/src/market_data_simple_request/main.cpp) / [Python](binding/python/example/market_data_simple_request/main.py) / [Java](binding/java/example/market_data_simple_request/Main.java) / [C#](binding/csharp/example/market_data_simple_request/MainProgram.cs) / [Go](binding/go/example/market_data_simple_request/main.go)
```
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Expand Down Expand Up @@ -260,7 +273,7 @@ For a specific exchange and instrument, whenever the best bid's or ask's price o

**Code 2:**

[C++](example/src/market_data_simple_subscription/main.cpp) / [Python](binding/python/example/market_data_simple_subscription/main.py) / [Java](binding/java/example/market_data_simple_subscription/Main.java) / [C#](binding/csharp/example/market_data_simple_subscription/MainProgram.cs)
[C++](example/src/market_data_simple_subscription/main.cpp) / [Python](binding/python/example/market_data_simple_subscription/main.py) / [Java](binding/java/example/market_data_simple_subscription/Main.java) / [C#](binding/csharp/example/market_data_simple_subscription/MainProgram.cs) / [Go](binding/go/example/market_data_simple_subscription/main.go)
```
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Expand Down Expand Up @@ -434,7 +447,7 @@ For a specific exchange and instrument, submit a simple limit order.

**Code 1:**

[C++](example/src/execution_management_simple_request/main.cpp) / [Python](binding/python/example/execution_management_simple_request/main.py) / [Java](binding/java/example/execution_management_simple_request/Main.java) / [C#](binding/csharp/example/execution_management_simple_request/MainProgram.cs)
[C++](example/src/execution_management_simple_request/main.cpp) / [Python](binding/python/example/execution_management_simple_request/main.py) / [Java](binding/java/example/execution_management_simple_request/Main.java) / [C#](binding/csharp/example/execution_management_simple_request/MainProgram.cs) / [Go](binding/go/example/execution_management_simple_request/main.go)
```
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Expand Down Expand Up @@ -524,7 +537,7 @@ For a specific exchange and instrument, receive order updates.

**Code 2:**

[C++](example/src/execution_management_simple_subscription/main.cpp) / [Python](binding/python/example/execution_management_simple_subscription/main.py) / [Java](binding/java/example/execution_management_simple_subscription/Main.java) / [C#](binding/csharp/example/execution_management_simple_subscription/MainProgram.cs)
[C++](example/src/execution_management_simple_subscription/main.cpp) / [Python](binding/python/example/execution_management_simple_subscription/main.py) / [Java](binding/java/example/execution_management_simple_subscription/Main.java) / [C#](binding/csharp/example/execution_management_simple_subscription/MainProgram.cs) / [Go](binding/go/example/execution_management_simple_subscription/main.go)
```
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Expand Down Expand Up @@ -767,7 +780,7 @@ For a specific exchange and instrument, submit a simple limit order.

**Code:**

[C++](example/src/fix_simple/main.cpp) / [Python](binding/python/example/fix_simple/main.py) / [Java](binding/java/example/fix_simple/Main.java) / [C#](binding/csharp/example/fix_simple/MainProgram.cs)
[C++](example/src/fix_simple/main.cpp) / [Python](binding/python/example/fix_simple/main.py) / [Java](binding/java/example/fix_simple/Main.java) / [C#](binding/csharp/example/fix_simple/MainProgram.cs) / [Go](binding/go/example/fix_simple/main.go)
```
#include "ccapi_cpp/ccapi_session.h"
namespace ccapi {
Expand Down Expand Up @@ -911,7 +924,7 @@ An example can be found [here](example/src/market_data_advanced_subscription/mai

#### Enable library logging

[C++](example/src/enable_library_logging/main.cpp) / [Python](binding/python/example/enable_library_logging/main.py) / [Java](binding/java/example/enable_library_logging/Main.java) / [C#](binding/csharp/example/enable_library_logging/MainProgram.cs)
[C++](example/src/enable_library_logging/main.cpp) / [Python](binding/python/example/enable_library_logging/main.py) / [Java](binding/java/example/enable_library_logging/Main.java) / [C#](binding/csharp/example/enable_library_logging/MainProgram.cs) / [Go](binding/go/example/enable_library_logging/main.go)

Extend a subclass, e.g. `MyLogger`, from class `Logger` and override method `logMessage`. Assign a `MyLogger` pointer to `Logger::logger`. Add one of the following macros in the compiler command line: `CCAPI_ENABLE_LOG_TRACE`, `CCAPI_ENABLE_LOG_DEBUG`, `CCAPI_ENABLE_LOG_INFO`, `CCAPI_ENABLE_LOG_WARN`, `CCAPI_ENABLE_LOG_ERROR`, `CCAPI_ENABLE_LOG_FATAL`. Enable logging if you'd like to inspect raw responses/messages from the exchange for troubleshooting purposes.
```
Expand Down
87 changes: 49 additions & 38 deletions binding/CMakeLists.txt
Expand Up @@ -76,21 +76,18 @@ else()
endforeach()
endif()

option(BUILD_PYTHON "Build Python Library" OFF)
message(STATUS "Build Python: ${BUILD_PYTHON}")

option(BUILD_JAVA "Build Java Library" OFF)
message(STATUS "Build Java: ${BUILD_JAVA}")

option(BUILD_CSHARP "Build C# Library" OFF)
message(STATUS "Build C#: ${BUILD_CSHARP}")

set(CMAKE_CXX_STANDARD 17)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
get_filename_component(CCAPI_PROJECT_DIR ../ ABSOLUTE)
message(STATUS "CCAPI_PROJECT_DIR: ${CCAPI_PROJECT_DIR}")
find_package(OpenSSL REQUIRED)
message(STATUS "OPENSSL_INCLUDE_DIR: ${OPENSSL_INCLUDE_DIR}")
message(STATUS "OPENSSL_CRYPTO_LIBRARY: ${OPENSSL_CRYPTO_LIBRARY}")
get_filename_component(OPENSSL_CRYPTO_LIBRARY_DIR ${OPENSSL_CRYPTO_LIBRARY} DIRECTORY)
message(STATUS "OPENSSL_SSL_LIBRARY: ${OPENSSL_SSL_LIBRARY}")
get_filename_component(OPENSSL_SSL_LIBRARY_DIR ${OPENSSL_SSL_LIBRARY} DIRECTORY)
if(NOT CCAPI_LEGACY_USE_WEBSOCKETPP)
message(STATUS "use boost beast websocket")
if(NOT BOOST_INCLUDE_DIR)
Expand Down Expand Up @@ -145,12 +142,19 @@ else()
set(HFFIX_INCLUDE_DIR ${CCAPI_PROJECT_DIR}/dependency/hffix/include)
include_directories(${CCAPI_PROJECT_DIR}/include ${WEBSOCKETPP_INCLUDE_DIR} ${BOOST_INCLUDE_DIR} ${RAPIDJSON_INCLUDE_DIR} ${HFFIX_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR})
endif()
find_package(OpenSSL REQUIRED)

link_libraries(OpenSSL::Crypto OpenSSL::SSL)

find_package(ZLIB REQUIRED)
link_libraries(ZLIB::ZLIB)
message(STATUS "ZLIB_INCLUDE_DIRS: ${ZLIB_INCLUDE_DIRS}")
message(STATUS "ZLIB_LIBRARIES: ${ZLIB_LIBRARIES}")

set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(SOURCE_LOGGER ${CCAPI_PROJECT_DIR}/binding/ccapi_logger.cpp)
find_package(SWIG REQUIRED)
message(STATUS "SWIG_VERSION: ${SWIG_VERSION}")
message(STATUS "SWIG_EXECUTABLE: ${SWIG_EXECUTABLE}")
include(UseSWIG)
if(BUILD_TEST)
include(CTest)
Expand Down Expand Up @@ -217,33 +221,40 @@ add_compile_definitions(CCAPI_ENABLE_EXCHANGE_MEXC_FUTURES)

add_compile_definitions(CCAPI_ENABLE_EXCHANGE_WHITEBIT)

find_package(ZLIB REQUIRED)
link_libraries(ZLIB::ZLIB)
if(CCAPI_ENABLE_LOG_ERROR)
add_compile_definitions(CCAPI_ENABLE_LOG_ERROR)
endif()

if(BUILD_PYTHON)
configure_file(
swig_interface.i.in
${CMAKE_BINARY_DIR}/python/swig_interface.i
@ONLY)
set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/python/swig_interface.i)
add_subdirectory(python)
endif()

if(BUILD_JAVA)
configure_file(
swig_interface.i.in
${CMAKE_BINARY_DIR}/java/swig_interface.i
@ONLY)
set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/java/swig_interface.i)
add_subdirectory(java)
endif()

if(BUILD_CSHARP)
file(READ csharp/swig_interface_ccapi_language_specific.i SWIG_INTERFACE_CCAPI_LANGUAGE_SPECIFIC)
configure_file(
swig_interface.i.in
${CMAKE_BINARY_DIR}/csharp/swig_interface.i
@ONLY)
set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/csharp/swig_interface.i)
add_subdirectory(csharp)
if(CCAPI_ENABLE_LOG_WARN)
add_compile_definitions(CCAPI_ENABLE_LOG_WARN)
endif()

if(CCAPI_ENABLE_LOG_INFO)
add_compile_definitions(CCAPI_ENABLE_LOG_INFO)
endif()

if(CCAPI_ENABLE_LOG_DEBUG)
add_compile_definitions(CCAPI_ENABLE_LOG_DEBUG)
endif()

if(CCAPI_ENABLE_LOG_TRACE)
add_compile_definitions(CCAPI_ENABLE_LOG_TRACE)
endif()

set(LANG_LIST "python" "java" "csharp" "go" "javascript")
foreach(LANG IN LISTS LANG_LIST)
string(TOUPPER ${LANG} LANG_UPPER)
option(BUILD_${LANG_UPPER} "Build ${LANG} library" OFF)
message(STATUS "Build ${LANG_UPPER}: ${BUILD_${LANG_UPPER}}")
if(BUILD_${LANG_UPPER})
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${LANG}/swig_interface_ccapi_language_specific.i")
file(READ ${LANG}/swig_interface_ccapi_language_specific.i SWIG_INTERFACE_CCAPI_LANGUAGE_SPECIFIC)
endif()
configure_file(
swig_interface.i.in
${CMAKE_BINARY_DIR}/${LANG}/swig_interface.i
@ONLY)
set(SWIG_INTERFACE ${CMAKE_BINARY_DIR}/${LANG}/swig_interface.i)
add_subdirectory(${LANG})
endif()
endforeach()
27 changes: 27 additions & 0 deletions binding/csharp/CMakeLists.txt
Expand Up @@ -55,3 +55,30 @@ add_custom_target(${CSHARP_PACKAGING_TARGET_NAME} ALL
WORKING_DIRECTORY ${SRC_DIR_FULL}
)
add_dependencies(${CSHARP_PACKAGING_TARGET_NAME} ${SWIG_TARGET_NAME})

# Test
if(BUILD_TEST)
set(TEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/test)
file(COPY example DESTINATION ${TEST_DIR})
set(SUBDIRECTORY_LIST "enable_library_logging" "execution_management_simple_request" "execution_management_simple_subscription" "fix_simple" "handle_exception" "market_data_multiple_subscription" "market_data_simple_request" "market_data_simple_subscription")
foreach(SUBDIRECTORY IN LISTS SUBDIRECTORY_LIST)
set(CSHARP_TEST_TARGET_NAME csharp_test_${SUBDIRECTORY})
add_custom_target(${CSHARP_TEST_TARGET_NAME} ALL
COMMAND ${DOTNET_EXECUTABLE} clean
COMMAND ${DOTNET_EXECUTABLE} build --property:CcapiLibraryPath=${PACKAGING_DIR_FULL}/ccapi.dll -c ${DOTNET_BUILD_CONFIGURATION}
WORKING_DIRECTORY ${TEST_DIR}/example/${SUBDIRECTORY}
)
add_dependencies(${CSHARP_TEST_TARGET_NAME} ${CSHARP_PACKAGING_TARGET_NAME})
endforeach()
file(COPY test DESTINATION ${TEST_DIR})
set(CSHARP_TEST_TARGET_NAME csharp_test_test)
add_custom_target(${CSHARP_TEST_TARGET_NAME} ALL
COMMAND ${DOTNET_EXECUTABLE} clean
COMMAND ${DOTNET_EXECUTABLE} build --property:CcapiLibraryPath=${PACKAGING_DIR_FULL}/ccapi.dll -c ${DOTNET_BUILD_CONFIGURATION}
WORKING_DIRECTORY ${TEST_DIR}/test
)
add_dependencies(${CSHARP_TEST_TARGET_NAME} ${CSHARP_PACKAGING_TARGET_NAME})
add_test(NAME csharp_test
COMMAND env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${PACKAGING_DIR_FULL} ${DOTNET_EXECUTABLE} run -c ${DOTNET_BUILD_CONFIGURATION} --no-build
WORKING_DIRECTORY ${TEST_DIR}/test)
endif()
@@ -1,3 +1,4 @@
// usage: when generating the binding code, do cmake -DCCAPI_ENABLE_LOG_TRACE=ON ..., see https://github.com/crypto-chassis/ccapi#non-c
public class MainProgram {
class MyLogger : ccapi.Logger {
public override void LogMessage(string severity, string threadId, string timeISO, string fileName, string lineNumber, string message) {
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion binding/csharp/example/handle_exception/MainProgram.cs
Expand Up @@ -5,7 +5,7 @@ class MyEventHandler : ccapi.EventHandler {
throw new System.Exception("oops");
} catch (System.Exception e) {
System.Console.WriteLine(e.ToString());
System.Environment.Exit(0);
System.Environment.Exit(1);
}
return true;
}
Expand Down
@@ -1,7 +1,9 @@
class MainProgram {
class MyEventHandler : ccapi.EventHandler {
public override bool ProcessEvent(ccapi.Event event_, ccapi.Session session) {
if (event_.GetType_() == ccapi.Event.Type.SUBSCRIPTION_DATA) {
if (event_.GetType_() == ccapi.Event.Type.SUBSCRIPTION_STATUS) {
System.Console.WriteLine(string.Format("Received an event of type SUBSCRIPTION_STATUS:\n{0}", event_.ToStringPretty(2, 2)));
} else if (event_.GetType_() == ccapi.Event.Type.SUBSCRIPTION_DATA) {
foreach (var message in event_.GetMessageList()) {
System.Console.WriteLine(string.Format("Best bid and ask at {0} are:", message.GetTimeISO()));
foreach (var element in message.GetElementList()) {
Expand Down
23 changes: 23 additions & 0 deletions binding/csharp/test/MainProgram.cs
@@ -0,0 +1,23 @@
class MainProgram {
class MyEventHandler : ccapi.EventHandler {
public override bool ProcessEvent(ccapi.Event event_, ccapi.Session session) {
return true;
}
}
static void Main(string[] args) {
var eventHandler = new MyEventHandler();
var option = new ccapi.SessionOptions();
var config = new ccapi.SessionConfigs();
var session = new ccapi.Session(option, config, eventHandler);
var subscriptionList = new ccapi.SubscriptionList();
subscriptionList.Add(new ccapi.Subscription("okx", "BTC-USDT", "MARKET_DEPTH"));
session.Subscribe(subscriptionList);
var request = new ccapi.Request(ccapi.Request.Operation.GET_RECENT_TRADES, "okx", "BTC-USDT");
var param = new ccapi.MapStringString();
param.Add("LIMIT", "1");
request.AppendParam(param);
session.SendRequest(request);
session.Stop();
System.Console.WriteLine("Bye");
}
}
14 changes: 14 additions & 0 deletions binding/csharp/test/main.csproj
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<Configuration>Release</Configuration>
<CcapiLibraryPath>to be provided in command line</CcapiLibraryPath>
</PropertyGroup>
<ItemGroup>
<Reference Include="ccapi">
<HintPath>$(CcapiLibraryPath)</HintPath>
</Reference>
</ItemGroup>
</Project>

0 comments on commit 9685adf

Please sign in to comment.