Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea4e599ac6 | ||
|
|
fd2ba70031 | ||
|
|
ab410c339f | ||
|
|
9e3f16d8bc | ||
|
|
a3f194d708 |
No files matched your search
@@ -7,6 +7,24 @@
|
||||
"commands": [
|
||||
"dotnet-format"
|
||||
]
|
||||
},
|
||||
"fable": {
|
||||
"version": "4.0.0-theta-018",
|
||||
"commands": [
|
||||
"fable"
|
||||
]
|
||||
},
|
||||
"fantomas": {
|
||||
"version": "5.2.2",
|
||||
"commands": [
|
||||
"fantomas"
|
||||
]
|
||||
},
|
||||
"fake-cli": {
|
||||
"version": "6.0.0",
|
||||
"commands": [
|
||||
"fake"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Note installations that take a while (more than 10s)
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y ca-certificates
|
||||
RUN apt-get install -y ccache
|
||||
RUN apt-get install -y curl
|
||||
RUN apt-get install -y fish
|
||||
RUN apt-get install -y gdb
|
||||
# git-all: ~250s
|
||||
RUN apt-get install -y git-all
|
||||
RUN apt-get install -y gnupg
|
||||
# liblttng-ust-dev: ~30s
|
||||
RUN apt-get install -y liblttng-ust-dev
|
||||
RUN apt-get install -y libssh2-1-dev
|
||||
RUN apt-get install -y locales
|
||||
RUN apt-get install -y ninja-build
|
||||
# openssh-server: ~40s
|
||||
RUN apt-get install -y openssh-server
|
||||
RUN apt-get install -y pkg-config
|
||||
RUN apt-get install -y software-properties-common
|
||||
RUN apt-get install -y sudo
|
||||
RUN apt-get install -y tzdata
|
||||
RUN apt-get install -y vim
|
||||
RUN apt-get install -y zip
|
||||
|
||||
# Python: ~30s
|
||||
RUN apt-get install -y \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
&& python3 -m pip install --upgrade pip
|
||||
|
||||
# GCC
|
||||
ARG gcc_major=13
|
||||
RUN \
|
||||
add-apt-repository ppa:ubuntu-toolchain-r/test \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y g++-$gcc_major
|
||||
|
||||
# Clang
|
||||
ARG clang_major=17
|
||||
RUN \
|
||||
curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key 2> /dev/null \
|
||||
| gpg --dearmor - \
|
||||
| tee /usr/share/keyrings/llvm-snapshot.gpg > /dev/null \
|
||||
&& echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-$clang_major main" \
|
||||
| tee -a "/etc/apt/sources.list.d/llvm.list" \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y \
|
||||
clang-$clang_major \
|
||||
clang-format-$clang_major \
|
||||
clangd-$clang_major
|
||||
|
||||
# CMake
|
||||
RUN \
|
||||
curl -fsSL https://apt.kitware.com/keys/kitware-archive-latest.asc 2> /dev/null \
|
||||
| gpg --dearmor - \
|
||||
| tee /usr/share/keyrings/kitware-archive-keyring.gpg > /dev/null \
|
||||
&& echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" \
|
||||
| tee /etc/apt/sources.list.d/kitware.list > /dev/null \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y cmake
|
||||
|
||||
# Dotnet
|
||||
RUN apt-get update && apt-get install -y dotnet7
|
||||
|
||||
# Node
|
||||
ARG node_major=18
|
||||
RUN mkdir -p /etc/apt/keyrings \
|
||||
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
|
||||
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
|
||||
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$node_major.x nodistro main" \
|
||||
| tee /etc/apt/sources.list.d/nodesource.list \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y nodejs
|
||||
|
||||
# Emumba (deps)
|
||||
RUN apt-get update && apt-get -y install rapidjson-dev
|
||||
# Emumba
|
||||
COPY emumba /emumba
|
||||
RUN dpkg -i /emumba/emumba-deribit-connector-3.3.1-Linux.LICENSE_DISABLED.deb \
|
||||
&& rm -r /emumba
|
||||
|
||||
# Pcap
|
||||
RUN apt-get update && apt-get install -y libpcap0.8-dev
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
docker.io \
|
||||
docker-compose \
|
||||
docker-compose-v2
|
||||
|
||||
# Set up default executables (update-alternatives)
|
||||
RUN \
|
||||
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-$clang_major 100; \
|
||||
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-$clang_major 100; \
|
||||
update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-$clang_major 100; \
|
||||
update-alternatives --install /usr/bin/clangd clangd /usr/bin/clangd-$clang_major 100; \
|
||||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-$gcc_major 100; \
|
||||
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-$gcc_major 100
|
||||
|
||||
# Add compiler symlinks for ccache
|
||||
RUN \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/clang; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/clang++; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/clang-$clang_major; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/clang++-$clang_major; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/gcc; \
|
||||
ln -s /usr/bin/ccache /usr/local/bin/g++
|
||||
|
||||
RUN locale-gen en_US.UTF-8
|
||||
|
||||
ARG docker_user="bts"
|
||||
ARG docker_uid="1000"
|
||||
ARG docker_pass="bts"
|
||||
|
||||
RUN \
|
||||
groupadd -g "$docker_uid" "$docker_user" \
|
||||
&& useradd \
|
||||
-m \
|
||||
-u "$docker_uid" \
|
||||
-g "$docker_uid" \
|
||||
-G sudo \
|
||||
--password "$(openssl passwd -1 "$docker_pass")" \
|
||||
"$docker_user"
|
||||
|
||||
RUN usermod -aG docker "$docker_user"
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"dockerFile": "Dockerfile",
|
||||
// Creates local dir to mount to HOME in docker
|
||||
"initializeCommand": "mkdir -p ${localEnv:HOME}/.bts/devcontainer-mounts/${devcontainerId}",
|
||||
"hostRequirements": {
|
||||
"memory": "4gb",
|
||||
"storage": "6gb"
|
||||
},
|
||||
"postCreateCommand": "/home/bts/spark/docker/sparkd/dev/devcontainer_post_create.sh",
|
||||
"containerUser": "bts",
|
||||
"workspaceMount": "source=${localWorkspaceFolder},target=/home/bts/spark,type=bind",
|
||||
"workspaceFolder": "/home/bts/spark",
|
||||
"updateRemoteUserUID": true,
|
||||
"shutdownAction": "none",
|
||||
// Note: If running multiple containers on the same host, each must use a
|
||||
// unique set of ports. Usually we just add 1000 to each port as needed. For
|
||||
// example, if 8000-8003 is taken, go with 9000-9003, then 10000-10003, etc.
|
||||
"runArgs": [
|
||||
"--shm-size",
|
||||
"2gb",
|
||||
"--network",
|
||||
"host"
|
||||
],
|
||||
"mounts": [
|
||||
"source=${localEnv:HOME}/.bts/devcontainer-mounts/${devcontainerId},target=/home/bts,type=bind",
|
||||
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
|
||||
],
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"clangd.arguments": [
|
||||
"--compile-commands-dir=${workspaceFolder}/build/clang/debug"
|
||||
]
|
||||
},
|
||||
"extensions": [
|
||||
"eamodio.gitlens",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"ms-vscode.cmake-tools",
|
||||
"ms-vscode.cpptools"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -42,7 +42,7 @@ trace_data/
|
||||
/.ignore
|
||||
*.rej
|
||||
.clangd/
|
||||
*CMakeDeps*.cmake
|
||||
*CMakeDeps.cmake
|
||||
/sniper.ipynb
|
||||
/src/.clang-format
|
||||
/src/server/sparkd/cmds/spartan/analysis/.ipynb_checkpoints
|
||||
|
||||
+6
-3
@@ -1,6 +1,9 @@
|
||||
[submodule "externals"]
|
||||
path = externals
|
||||
url = git@bitbucket.org:bluetradesys/externals.git
|
||||
[submodule "vcpkg"]
|
||||
path = vcpkg
|
||||
url = https://github.com/microsoft/vcpkg.git
|
||||
[submodule "docker/linux"]
|
||||
path = docker/linux
|
||||
url = git@bitbucket.org:bluetradesys/linux_docker.git
|
||||
[submodule "docker/windows"]
|
||||
path = docker/windows
|
||||
url = git@bitbucket.org:bluetradesys/windows_docker.git
|
||||
+76
-25
@@ -1,6 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(spark)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
if(WIN32)
|
||||
set(platform "windows")
|
||||
@@ -14,49 +13,101 @@ set(
|
||||
CACHE
|
||||
STRING
|
||||
"External dependencies root folder (should contain folders: lib, bin, include")
|
||||
set(EXTERNALS_BIN "${EXTERNALS_ROOT}/bin")
|
||||
set(EXTERNALS_INCLUDE "${EXTERNALS_ROOT}/include")
|
||||
set(EXTERNALS_LIB "${EXTERNALS_ROOT}/lib/$<CONFIG>")
|
||||
set(BUILD_DOCS OFF CACHE BOOL "Build documentation")
|
||||
set(SPARK_PYTHON "${EXTERNALS_ROOT}/python")
|
||||
set(SPARK_BIN "${EXTERNALS_ROOT}/bin")
|
||||
set(SPARK_INCLUDE "${EXTERNALS_ROOT}/include")
|
||||
set(SPARK_LIB "${EXTERNALS_ROOT}/lib/${CMAKE_BUILD_TYPE}")
|
||||
set(BUILD_SDK OFF CACHE BOOL "Build the sdk")
|
||||
set(EXPORT_MD_CONSUMER OFF CACHE BOOL "Export (extern) C functions for MD consumer interop")
|
||||
if (WIN32)
|
||||
set(BUILD_SPARKD OFF CACHE BOOL "Build sparkd")
|
||||
set(BUILD_WEB OFF CACHE BOOL "Build the web server")
|
||||
else()
|
||||
set(BUILD_SPARKD ON CACHE BOOL "Build sparkd")
|
||||
set(BUILD_WEB ON CACHE BOOL "Build the web server")
|
||||
endif()
|
||||
set(BUILD_WEB ON CACHE BOOL "Build the web server")
|
||||
|
||||
include_directories(BEFORE SYSTEM ${EXTERNALS_INCLUDE} ${EXTERNALS_ROOT}/include/zlib)
|
||||
link_directories(${EXTERNALS_LIB})
|
||||
include_directories(BEFORE SYSTEM ${SPARK_INCLUDE} ${EXTERNALS_ROOT}/include/zlib)
|
||||
link_directories(${SPARK_LIB})
|
||||
|
||||
add_compile_definitions(EXPORT_MD_CONSUMER="${EXPORT_MD_CONSUMER}")
|
||||
if(WIN32)
|
||||
# flags
|
||||
set(
|
||||
CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} \
|
||||
/MP \
|
||||
/WX /wd4251 /wd4250 /wd4251 /wd4244 /wd4267 /wd4355 /wd4275 /wd4345 \
|
||||
/bigobj \
|
||||
/DCURL_STATICLIB \
|
||||
/D_WINSOCK_DEPRECATED_NO_WARNINGS \
|
||||
/D__TBB_NO_IMPLICIT_LINKAGE \
|
||||
/DBOOST_ALL_NO_LIB \
|
||||
/std:c++17 \
|
||||
/D_SCL_SECURE_NO_WARNINGS /D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_DEBUG} /MT")
|
||||
set(
|
||||
CMAKE_SHARED_LINKER_FLAGS_RELEASE
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_RELEASE} \
|
||||
/DEBUG \
|
||||
/OPT:REF \
|
||||
/OPT:ICF \
|
||||
/LTCG")
|
||||
|
||||
# subdirs
|
||||
add_subdirectory(src/lib)
|
||||
else()
|
||||
# make sparkd look for libspark.so in its directory
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||
set(CMAKE_INSTALL_RPATH ".")
|
||||
set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}/install/${CMAKE_BUILD_TYPE}/sparkd")
|
||||
add_compile_definitions(SPARK_ENABLE_CCAPI)
|
||||
add_compile_definitions(CCAPI_ENABLE_SERVICE_MARKET_DATA)
|
||||
add_compile_definitions(CCAPI_ENABLE_SERVICE_EXECUTION_MANAGEMENT)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_FTX)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_BINANCE)
|
||||
add_compile_definitions(CCAPI_ENABLE_EXCHANGE_DERIBIT)
|
||||
add_compile_definitions(CCAPI_ENABLE_LOG_WARN)
|
||||
|
||||
# flags
|
||||
set(
|
||||
CMAKE_CXX_FLAGS_DEBUG
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} \
|
||||
-fPIC \
|
||||
-Wall \
|
||||
-pedantic \
|
||||
-Wextra \
|
||||
-Werror \
|
||||
-Wno-missing-braces \
|
||||
-Wno-ignored-qualifiers \
|
||||
--std=c++17 -fdiagnostics-color")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -DNDEBUG -O3")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wno-undef")
|
||||
|
||||
# subdirs
|
||||
if (BUILD_SPARKD)
|
||||
add_subdirectory(src/server/sparkd)
|
||||
add_subdirectory(src/data_files)
|
||||
endif()
|
||||
add_subdirectory(src/server/sparkd)
|
||||
add_subdirectory(src/lib)
|
||||
if (BUILD_WEB)
|
||||
add_subdirectory(src/web)
|
||||
endif()
|
||||
if(BUILD_DOCS)
|
||||
add_subdirectory(doc/user)
|
||||
endif()
|
||||
add_subdirectory(doc/user)
|
||||
if(BUILD_SDK)
|
||||
add_subdirectory(src/sdk)
|
||||
endif()
|
||||
add_subdirectory(src/data_files)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/server/sparkd/sparkd ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/web ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/data_files ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/lib/libspark.so ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND
|
||||
ln ARGS -sf
|
||||
${EXTERNALS_ROOT}/lib/Release/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0
|
||||
${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${EXTERNALS_ROOT}/lib/Release/libACE-5.7.5.so ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/server/plugins
|
||||
COMMENT "Creating server runtime layout"
|
||||
DEPENDS sparkd data_files_dir)
|
||||
|
||||
add_custom_target(server_layout ALL DEPENDS ${CMAKE_BINARY_DIR}/server)
|
||||
|
||||
install(DIRECTORY "${CMAKE_BINARY_DIR}/server/plugins" DESTINATION bin)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/externals/linux/lib/${CMAKE_BUILD_TYPE}/libACE-5.7.5.so" DESTINATION bin)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/externals/linux/lib/${CMAKE_BUILD_TYPE}/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0" DESTINATION bin)
|
||||
install(FILES "${CMAKE_SOURCE_DIR}/externals/src/emumba/sparkd.lic" DESTINATION bin)
|
||||
endif()
|
||||
@@ -1,215 +0,0 @@
|
||||
{
|
||||
"version": 4,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 23,
|
||||
"patch": 0
|
||||
},
|
||||
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "spark",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"environment": {
|
||||
"SPARK_CMAKE_CXX_FLAGS": "/MP /WX /wd4250 /wd4251 /wd4244 /wd4267 /wd4355 /wd4275 /wd4345 /bigobj /EHsc /DCURL_STATICLIB /D_WINSOCK_DEPRECATED_NO_WARNINGS /D__TBB_NO_IMPLICIT_LINKAGE /DBOOST_ALL_NO_LIB /std:c++20 /D_SCL_SECURE_NO_WARNINGS /D_CRT_SECURE_NO_WARNINGS /D_WIN32_WINNT=0x0600"
|
||||
},
|
||||
"cacheVariables": {
|
||||
"CMAKE_CXX_FLAGS": "$env{SPARK_CMAKE_CXX_FLAGS}",
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "$env{SPARK_CMAKE_CXX_FLAGS} /MTd",
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "$env{SPARK_CMAKE_CXX_FLAGS} /MT",
|
||||
"CMAKE_CXX_STANDARD": "20",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}",
|
||||
"CMAKE_SHARED_LINKER_FLAGS_DEBUG": "/DEBUG",
|
||||
"CMAKE_SHARED_LINKER_FLAGS_RELEASE": "/OPT:REF /OPT:ICF /LTCG",
|
||||
"CMAKE_TOOLCHAIN_FILE": "${sourceDir}/vcpkg/scripts/buildsystems/vcpkg.cmake",
|
||||
"EXTERNALS_ROOT": "${sourceDir}/externals/windows",
|
||||
"CONFIG_DEFAULTS_PATH": "config/defaults/*.conf",
|
||||
"DOTNET_BINARY_DIR": "${sourceDir}/build/$<CONFIG>/bin/net7.0;${sourceDir}/build/$<CONFIG>/bin/net7.0-windows",
|
||||
"EXPORT_MD_CONSUMER": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"platform": "",
|
||||
"CMAKE_CXX_STANDARD": "20",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}",
|
||||
"CMAKE_EXE_LINKER_FLAGS": "-Wno-undef",
|
||||
"CONFIG_DEFAULTS_PATH": "config/defaults/*.conf",
|
||||
"EXTERNALS_ROOT": "${sourceDir}/externals/linux",
|
||||
"BUILD_SDK": {
|
||||
"type": "BOOL",
|
||||
"value": "OFF"
|
||||
},
|
||||
"BUILD_ADMIN_WEB_APP": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug",
|
||||
"inherits": "sparkd",
|
||||
"hidden": true,
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"CMAKE_EXPORT_COMPILE_COMMANDS": {
|
||||
"type": "BOOL",
|
||||
"value": "ON"
|
||||
},
|
||||
"CCAPI_LOG_LEVEL": "Info"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release",
|
||||
"inherits": "sparkd",
|
||||
"hidden": true,
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CCAPI_LOG_LEVEL": "Warn"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-clang",
|
||||
"inherits": "sparkd-debug",
|
||||
"displayName": "Sparkd (Debug | Clang)",
|
||||
"description": "Debug build compiled w/ clang",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -DDEBUG"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-gcc",
|
||||
"inherits": "sparkd-debug",
|
||||
"displayName": "Sparkd (Debug | Gcc)",
|
||||
"description": "Debug build compiled w/ gcc",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "gcc",
|
||||
"CMAKE_CXX_COMPILER": "g++",
|
||||
"CMAKE_CXX_FLAGS_DEBUG": "-g -fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -Wno-stringop-overread -DDEBUG"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release-clang",
|
||||
"inherits": "sparkd-release",
|
||||
"displayName": "Sparkd (Release | Clang)",
|
||||
"description": "Release build compiled w/ clang",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers --std=c++20 -fdiagnostics-color -fno-omit-frame-pointer -DNDEBUG -O3"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release-gcc",
|
||||
"inherits": "sparkd-release",
|
||||
"displayName": "Sparkd (Release | Gcc)",
|
||||
"description": "Release build compiled w/ gcc",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "gcc",
|
||||
"CMAKE_CXX_COMPILER": "g++",
|
||||
"CMAKE_CXX_FLAGS_RELEASE": "-fPIC -Wall -pedantic -Wextra -Werror -Wno-missing-braces -Wno-ignored-qualifiers -Wno-stringop-overflow --std=c++20 -fdiagnostics-color -Wno-stringop-overread -Wno-maybe-uninitialized -fno-omit-frame-pointer -DNDEBUG -O3"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"buildPresets": [
|
||||
{
|
||||
"name": "spark",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Windows"
|
||||
},
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
{
|
||||
"name": "spark-debug",
|
||||
"displayName": "Spark (Debug)",
|
||||
"inherits": "spark",
|
||||
"configurePreset": "spark",
|
||||
"configuration": "Debug"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "spark-release",
|
||||
"displayName": "Spark (Release)",
|
||||
"inherits": "spark",
|
||||
"configurePreset": "spark",
|
||||
"configuration": "Release"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd",
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-clang",
|
||||
"configurePreset": "sparkd-debug-clang",
|
||||
"displayName": "Sparkd (Debug | Clang)",
|
||||
"inherits": "sparkd"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-clang-j6",
|
||||
"configurePreset": "sparkd-debug-clang",
|
||||
"displayName": "Sparkd (Debug | Clang | jobs=6)",
|
||||
"inherits": "sparkd",
|
||||
"jobs": 6
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-debug-gcc",
|
||||
"configurePreset": "sparkd-debug-gcc",
|
||||
"displayName": "Sparkd (Debug | Gcc)",
|
||||
"inherits": "sparkd"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release-clang",
|
||||
"configurePreset": "sparkd-release-clang",
|
||||
"displayName": "Sparkd (Release | Clang)",
|
||||
"inherits": "sparkd"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "sparkd-release-gcc",
|
||||
"configurePreset": "sparkd-release-gcc",
|
||||
"displayName": "Sparkd (Release | Gcc)",
|
||||
"inherits": "sparkd"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/PackBasic.cmake)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
function(install_basic)
|
||||
set(_options)
|
||||
set(_one_value_args)
|
||||
set(_multi_value_args HEADERS)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
if (_ARGS_HEADERS)
|
||||
set(${PROJECT_NAME}_HEADERS ${_ARGS_HEADERS})
|
||||
else()
|
||||
file(
|
||||
GLOB_RECURSE ${PROJECT_NAME}_HEADERS
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.h
|
||||
)
|
||||
endif()
|
||||
|
||||
target_sources(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
FILE_SET HEADERS FILES ${${PROJECT_NAME}_HEADERS})
|
||||
|
||||
install(
|
||||
TARGETS ${PROJECT_NAME}
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT ${PROJECT_NAME}Targets
|
||||
FILE ${PROJECT_NAME}Targets.cmake
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
||||
|
||||
pack_basic()
|
||||
endfunction()
|
||||
@@ -1,36 +0,0 @@
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
function(pack_basic)
|
||||
find_package(Git QUIET)
|
||||
|
||||
if(GIT_FOUND)
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE PROJECT_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT GIT_FOUND OR PROJECT_VERSION STREQUAL "")
|
||||
set(PROJECT_VERSION "0.0.0")
|
||||
endif()
|
||||
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
)
|
||||
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
|
||||
endfunction()
|
||||
@@ -1,12 +0,0 @@
|
||||
function(print_list var)
|
||||
set(CMAKE_MESSAGE_INDENT "")
|
||||
set(_var_str "")
|
||||
foreach(item IN LISTS ${var})
|
||||
set(_var_str "${_var_str}\n ${item}")
|
||||
endforeach()
|
||||
if ("${ARGN}" STREQUAL "VERBOSE")
|
||||
message(VERBOSE "***${var}:${_var_str}")
|
||||
else()
|
||||
message("***${var}:${_var_str}")
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -1,5 +1,5 @@
|
||||
set(Protobuf_PROTOC_EXECUTABLE "${EXTERNALS_BIN}/protoc")
|
||||
set(PROTOBUF_INCLUDE_DIRS "${EXTERNALS_INCLUDE}")
|
||||
set(Protobuf_PROTOC_EXECUTABLE "${SPARK_BIN}/protoc")
|
||||
set(PROTOBUF_INCLUDE_DIRS "${SPARK_INCLUDE}")
|
||||
set(PROTOBUF_STATIC_LIB "libprotobuf")
|
||||
|
||||
function(Protobuf_Generate_Cpp SRCS HDRS)
|
||||
|
||||
Submodule
+1
Submodule docker/linux added at 6537812262.
Submodule
+1
Submodule docker/windows added at de7d40c09d.
+1
-1
Submodule externals updated: 800873c856...4a3e40193e.
@@ -4,6 +4,8 @@ VisualStudioVersion = 17.3.32922.545
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_api", "src\client\spark_api\spark_api.csproj", "{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libspark", "build\src\lib\libspark.vcxproj", "{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spark", "src\client\spark\Spark.csproj", "{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sparkcmd", "src\client\sparkcmd\sparkcmd.csproj", "{387566C6-C6F6-412C-A30C-9855BBCB4816}"
|
||||
@@ -11,6 +13,9 @@ EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_core", "src\client\spark_core\spark_core.csproj", "{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_sdk", "src\client\spark_sdk\spark_sdk.csproj", "{6963C314-83C4-4667-B0D0-C2F7AE208C29}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25} = {FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_test", "src\client\spark_test\spark_test.csproj", "{ECD78CC5-138F-4809-A764-2358C2AC2E82}"
|
||||
EndProject
|
||||
|
||||
@@ -63,9 +63,9 @@ namespace mbts.spark {
|
||||
vs_input, vs_nonvol_data.contracts, aux_data_map);
|
||||
_timer.stop();
|
||||
var tag_str = tag == null ? "Null" : tag.ToString();
|
||||
bts.Log.Gen.info($"SingleVolSurfaceCommittedOutputRetriever._recompute_and_publish " +
|
||||
$"vs_id: {_vs_id} time:{_timer.lastIntervalTime} ms tag:{tag_str} " +
|
||||
$"tid:{_tid()}"); //output: {vs_output.log_string()}*/");
|
||||
// bts.Log.Gen.info($"SingleVolSurfaceCommittedOutputRetriever._recompute_and_publish " +
|
||||
// $"vs_id: {_vs_id} time:{_timer.lastIntervalTime} ms tag:{tag_str} " +
|
||||
// $"tid:{_tid()}"); //output: {vs_output.log_string()}*/");
|
||||
_logger.log(_log_id, _log_id, _timer.lastIntervalTime);
|
||||
_bb.post(_out_bb_computed_vol_tag, vs_output);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace mbts.spark {
|
||||
var exp_price_map = OptionDriverPriceMap.get_vs_price_map(
|
||||
all_sym_price_map, (s) => _option_symbols.Contains(s));
|
||||
if (sc_data != null && vs_nonvol_input != null && exp_price_map != null) {
|
||||
bts.Log.Gen.info($"SingleVolSurfaceNonVolDataSource vs_id:{_vs_id} " +
|
||||
bts.Log.Gen.diag($"SingleVolSurfaceNonVolDataSource vs_id:{_vs_id} " +
|
||||
"publishing VolSurfaceNonVolData");
|
||||
_bb.post(_out_bb_vs_nonvol_data_tag,
|
||||
new VolSurfaceNonVolData(
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace mbts.analytics {
|
||||
output.Add(symbol, symbol_data);
|
||||
}
|
||||
IReadOnlyDictionary<string, TData> ro_output = output;
|
||||
bts.Log.Gen.info($"SymbolAggregationPublisher._on_timer publishing " +
|
||||
bts.Log.Gen.diag($"SymbolAggregationPublisher._on_timer publishing " +
|
||||
$"tag: {_out_tag} sz: {ro_output.Count}");
|
||||
_bb.post(_out_tag, ro_output);
|
||||
}
|
||||
|
||||
@@ -28,9 +28,10 @@ namespace mbts.spark {
|
||||
_candidate_value.Changed += on_candidate_changed;
|
||||
_is_dirty.Changed += (o, n) => {
|
||||
Log.assert(o != n);
|
||||
Log.Ui.info(
|
||||
$"VolSurface '{expiration}.{column}' is_dirty changed to {n}. " +
|
||||
$"commited: {committed_value}; candidate: {candidate_value}");
|
||||
// TODO: John, this was logged too many times
|
||||
// Log.Ui.info(
|
||||
// $"VolSurface '{expiration}.{column}' is_dirty changed to {n}. " +
|
||||
// $"commited: {committed_value}; candidate: {candidate_value}");
|
||||
};
|
||||
|
||||
void on_committed_changed(object? oldval, object? newval) =>
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
using mbts.co2;
|
||||
|
||||
namespace mbts.analytics {
|
||||
using Size = System.Single;
|
||||
public class VolSurfaceMDUnit : IEquatable<VolSurfaceMDUnit> {
|
||||
public readonly double bid_price, ask_price;
|
||||
public readonly Size bid_size, ask_size;
|
||||
public readonly uint bid_size, ask_size;
|
||||
public readonly double mark_price = double.NaN;
|
||||
private static VolSurfaceMDUnit _empty =
|
||||
new VolSurfaceMDUnit(Double.NaN, 0, Double.NaN, 0, Double.NaN);
|
||||
|
||||
public VolSurfaceMDUnit(double this_bid_price, Size this_bid_size,
|
||||
double this_ask_price, Size this_ask_size,
|
||||
public VolSurfaceMDUnit(double this_bid_price, uint this_bid_size,
|
||||
double this_ask_price, uint this_ask_size,
|
||||
double this_mark_price) {
|
||||
bid_price = this_bid_price;
|
||||
bid_size = this_bid_size;
|
||||
@@ -29,7 +28,7 @@ namespace mbts.analytics {
|
||||
|
||||
public VolSurfaceMDUnit(NativePriceSize bid, NativePriceSize ask,
|
||||
double mark_price)
|
||||
: this(bid.price, bid.size_f, ask.price, ask.size_f, mark_price) {
|
||||
: this(bid.price, bid.size, ask.price, ask.size, mark_price) {
|
||||
}
|
||||
|
||||
public bool is_two_sided() { return bid_size != 0 && ask_size != 0; }
|
||||
@@ -42,7 +41,7 @@ namespace mbts.analytics {
|
||||
}
|
||||
|
||||
public double get_weighted_mid_price(bool get_one_sided_mid = true) {
|
||||
Size sum_q = bid_size + ask_size;
|
||||
uint sum_q = bid_size + ask_size;
|
||||
if (sum_q == 0) {
|
||||
return Double.NaN;
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ namespace mbts.analytics {
|
||||
|
||||
public void set_driver_price(
|
||||
IDictionary<VolSurfaceExpiration, double> driver_price_map) {
|
||||
Log.Gen.info($"VolSurfaceInterpGreeksProducer.set_driver_price " +
|
||||
$"vs_id: {_vs_id} exp_count: {driver_price_map.Count}");
|
||||
// Log.Gen.info($"VolSurfaceInterpGreeksProducer.set_driver_price " +
|
||||
// $"vs_id: {_vs_id} exp_count: {driver_price_map.Count}");
|
||||
_driver_price_map = new Dictionary<VolSurfaceExpiration, double>(driver_price_map);
|
||||
_compute_and_fire(InputType.DriverPrice);
|
||||
}
|
||||
|
||||
@@ -52,23 +52,17 @@ namespace bts {
|
||||
string rv = "MergedMDDaemon Options:\n";
|
||||
foreach (var kv in sec_map) {
|
||||
var sec = kv.Value.security;
|
||||
var md = kv.Value.md;
|
||||
ulong time = 0;
|
||||
NativePriceSize bid, ask;
|
||||
var has_md = md.get_bbo(ref time, out bid, out ask);
|
||||
if (sec.HasOption) {
|
||||
rv += $"id: {kv.Key} desc: {sec.security_desc()} sym: {sec.Symbol} " +
|
||||
$"exp: {sec.security_expiration()} " +
|
||||
$"k: {sec.Option.Strike} cp: {sec.Option.CallPut} " +
|
||||
$"bid: p: {bid.price} q: {bid.size} qf: {bid.size_f} ask: p: {ask.price} q: {ask.size} qf: {ask.size_f}" +
|
||||
"\n";
|
||||
$"k: {sec.Option.Strike} cp: {sec.Option.CallPut}" + "\n";
|
||||
}
|
||||
}
|
||||
Log.Gen.info(rv);
|
||||
}
|
||||
|
||||
private void _on_server_sec_map(IReadOnlyDictionary<uint, SecurityMD> sec_map) {
|
||||
_log_options(sec_map);
|
||||
//_log_options(sec_map);
|
||||
bts.Log.Gen.info(String.Format("MergedMDDaemon._on_server_sec_map sz: {0}", sec_map.Count()));
|
||||
_server_sec_map = new Dictionary<uint, SecurityMD>(sec_map);
|
||||
_merge_and_post();
|
||||
|
||||
@@ -218,14 +218,10 @@ namespace mbts.spark {
|
||||
background = buy_sell_background_fill_color;
|
||||
hoverbackground = _mk_hover_bg_brush(dark, _darkbg, 0);
|
||||
|
||||
_num_root_orders = 0;
|
||||
_filled = 0;
|
||||
_quantity = 0;
|
||||
foreach (var n in _root_nodes) {
|
||||
_num_root_orders++;
|
||||
_filled += n.filled_quantity();
|
||||
_quantity += n.quantity();
|
||||
}
|
||||
(_num_root_orders, _filled, _quantity) = _root_nodes
|
||||
.Select(n => (1u, n.filled_quantity(), n.quantity()))
|
||||
.Sum();
|
||||
|
||||
if (_num_root_orders == 1) {
|
||||
var order = _root_nodes.First();
|
||||
border = _owner.model.order_gateway.factory.get_metadata(order).Color.rgb_brush();
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using mbts.analytics;
|
||||
|
||||
using System;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BCG {
|
||||
using Size = System.Single;
|
||||
public enum BidAskAlertZone { buy, sell, none }
|
||||
public class BBOPacket {
|
||||
public enum MarketSide {
|
||||
@@ -13,8 +15,8 @@ namespace BCG {
|
||||
|
||||
private double _bid_price => md.bid_price;
|
||||
private double _ask_price => md.ask_price;
|
||||
private Size _bid_size => md.bid_size;
|
||||
private Size _ask_size => md.ask_size;
|
||||
private UInt32 _bid_size => md.bid_size;
|
||||
private UInt32 _ask_size => md.ask_size;
|
||||
private static BBOPacket _null_pack = new BBOPacket(VolSurfaceMDUnit.empty);
|
||||
public readonly VolSurfaceMDUnit md;
|
||||
|
||||
@@ -22,6 +24,21 @@ namespace BCG {
|
||||
this.md = md;
|
||||
}
|
||||
|
||||
public static bool bid_through_theo(BBOPacket md, mbts.spark.TheoPoint tp, bool is_call) {
|
||||
return false;
|
||||
// if (tp != null && md != null && md._md_row != null)
|
||||
// return get_bid_price(md) > (is_call ? tp.call : tp.put);
|
||||
// else
|
||||
// return false;
|
||||
}
|
||||
|
||||
public static bool ask_through_theo(BBOPacket md, mbts.spark.TheoPoint tp, bool is_call) {
|
||||
// if (tp != null && md != null && md._md_row != null)
|
||||
// return get_ask_price(md) < (is_call ? tp.call : tp.put);
|
||||
// else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static double get_mid_price(BBOPacket md) {
|
||||
return (get_bid_price(md) + get_ask_price(md)) / 2.0;
|
||||
}
|
||||
@@ -30,16 +47,21 @@ namespace BCG {
|
||||
return md != null ? md._bid_price : Double.NaN;
|
||||
}
|
||||
|
||||
public static Size get_bid_size(BBOPacket md) {
|
||||
return md != null ? md._bid_size : (Size)0;
|
||||
public static UInt32 get_bid_size(BBOPacket md) {
|
||||
return md != null ? md._bid_size : (UInt32)0;
|
||||
}
|
||||
|
||||
public static double get_ask_price(BBOPacket md) {
|
||||
return md != null ? md._ask_price : Double.NaN;
|
||||
}
|
||||
|
||||
public static Size get_ask_size(BBOPacket md) {
|
||||
return md != null ? md._ask_size : (Size)0;
|
||||
public static UInt32 get_ask_size(BBOPacket md) {
|
||||
return md != null ? md._ask_size : (UInt32)0;
|
||||
}
|
||||
public static Tuple<double, UInt32> get_md(BBOPacket md, bool is_bid) {
|
||||
double price = is_bid ? BBOPacket.get_bid_price(md) : BBOPacket.get_ask_price(md);
|
||||
UInt32 sz = is_bid ? BBOPacket.get_bid_size(md) : BBOPacket.get_ask_size(md);
|
||||
return Tuple.Create(price, sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,6 +123,15 @@ namespace BCG {
|
||||
|
||||
#endregion
|
||||
|
||||
#region Orders
|
||||
[System.ComponentModel.Category("Orders / Algo")]
|
||||
[System.ComponentModel.DisplayName("Default Account")]
|
||||
public string Account { get; set; }
|
||||
[System.ComponentModel.Category("Orders / Algo")]
|
||||
[System.ComponentModel.DisplayName("Default Qty")]
|
||||
public Nullable<double> DefaultQty { get; set; }
|
||||
#endregion
|
||||
|
||||
public NMSheetSettingLayout() {
|
||||
show_settings_header = false;
|
||||
show_exp_navigator = false;
|
||||
|
||||
@@ -18,6 +18,7 @@ using mbts.spark.filters;
|
||||
using System.Collections;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using bts.api.orderman;
|
||||
|
||||
namespace BCG {
|
||||
public partial class NMSheetControl : UserControl {
|
||||
@@ -555,6 +556,17 @@ namespace BCG {
|
||||
}
|
||||
private void _launch_order_entry_window(NMSheetTheoGrid.GridCell cell,
|
||||
OrderEntryWindow window_type) {
|
||||
Func<string, bts.AccountTuple> get_account = (string default_acc) => {
|
||||
string account = _settings.setting_layout.Account;
|
||||
if (String.IsNullOrEmpty(account)) {
|
||||
account = default_acc;
|
||||
}
|
||||
Nullable<uint> id = _get_account_id(account);
|
||||
if (!id.HasValue) {
|
||||
id = 0;
|
||||
}
|
||||
return new bts.AccountTuple(id.Value, account);
|
||||
};
|
||||
uint key;
|
||||
var found = _sheet_data.get_security_key(cell.expiration,
|
||||
cell.strike, cell.call_selected, out key);
|
||||
@@ -566,7 +578,20 @@ namespace BCG {
|
||||
if (sc_data.sec_md_map.TryGetValue(key, out var smd)) {
|
||||
switch (window_type) {
|
||||
case OrderEntryWindow.Ticket:
|
||||
_threaded_bb.post(SparkTags.ShowOrderTicketFromSecurityTag, smd);
|
||||
bool is_bid = NMSheetSettingColumnOrganization.get_column_info(cell.col).is_bid;
|
||||
bts.AccountTuple acc_tup = get_account("SMALL");
|
||||
Nullable<double> qty = _settings.setting_layout.DefaultQty;
|
||||
OrderDefinition od = new OrderDefinition() {
|
||||
SecurityKey = smd.id,
|
||||
TimeInForce = TimeInForce.Gtc,
|
||||
Account = acc_tup.name,
|
||||
AccountId = acc_tup.id
|
||||
};
|
||||
BBOPacket bbo = _sheet_data.get_bbo(smd.id);
|
||||
Tuple<double, UInt32> pr_sz = BBOPacket.get_md(bbo, is_bid);
|
||||
UInt32 effective_qty = qty.HasValue ? Convert.ToUInt32(Math.Abs(qty.Value)) : pr_sz.Item2;
|
||||
_threaded_bb.post(SparkTags.ShowOrderTicketTag,
|
||||
(new OrderDefinitionImmutable(od), pr_sz.Item1, effective_qty));
|
||||
break;
|
||||
case OrderEntryWindow.Ladder:
|
||||
_threaded_bb.post(SparkTags.ShowLadderTag, smd);
|
||||
|
||||
@@ -190,24 +190,13 @@ namespace mbts.analytics {
|
||||
}
|
||||
}
|
||||
|
||||
void _compute_swipe_sum() {
|
||||
swipe_sum_puts = 0;
|
||||
swipe_sum_calls = 0;
|
||||
swipe_sum_net = 0;
|
||||
foreach (var (row, exps) in _visible_selected_cells) {
|
||||
foreach (var exp in exps) {
|
||||
var (p, c, n) = row.get_cell_values(exp);
|
||||
if (!p.is_nan()) {
|
||||
swipe_sum_puts += p;
|
||||
}
|
||||
if (!c.is_nan()) {
|
||||
swipe_sum_calls += c;
|
||||
}
|
||||
if (!n.is_nan()) {
|
||||
swipe_sum_net += n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void _compute_swipe_sum() =>
|
||||
(swipe_sum_puts, swipe_sum_calls, swipe_sum_net) = _visible_selected_cells
|
||||
.SelectMany(tup =>
|
||||
tup.exps.Select(exp => {
|
||||
var (p, c, n) = tup.row.get_cell_values(exp);
|
||||
return (p.if_nan(0), c.if_nan(0), n.if_nan(0));
|
||||
}))
|
||||
.Sum();
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ namespace mbts.analytics {
|
||||
timer.stop();
|
||||
Log.Ui.info($"PNLReportCalculator n_pos: {output.position_data.Count()} " +
|
||||
$"n_day_trades: {output.day_trades.Count()} time(msecs): {timer.lastIntervalTime}");
|
||||
_log_before_posting(output.position_data);
|
||||
//_log_before_posting(output.position_data);
|
||||
_bus.post(SparkTags.ReportBlackboardTags.PNL.PNLData, output);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -115,21 +115,21 @@ namespace mbts.analytics {
|
||||
}
|
||||
|
||||
private void _handle_nonvol_data(VolSurfaceNonVolData vs_nonvol_data) {
|
||||
bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_nonvol_data report {0}",
|
||||
_report.ReportName));
|
||||
// bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_nonvol_data report {0}",
|
||||
// _report.ReportName));
|
||||
_vs_nonvol_data = vs_nonvol_data;
|
||||
}
|
||||
|
||||
private void _handle_future_prices(
|
||||
IReadOnlyDictionary<SecurityExpiration, FutureTheoStructure> future_prices_map) {
|
||||
bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_future_prices report {0}",
|
||||
_report.ReportName));
|
||||
// bts.Log.Gen.Diag(String.Format("SlideReportCalculator._handle_future_prices report {0}",
|
||||
// _report.ReportName));
|
||||
_future_prices_map = future_prices_map.ToDictionary(kv => kv.Key, kv => kv.Value.theo);
|
||||
}
|
||||
|
||||
private void _handle_trades(IEnumerable<ITradeLogRow> trades) {
|
||||
bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_trades report {0}",
|
||||
_report.ReportName));
|
||||
// bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_trades report {0}",
|
||||
// _report.ReportName));
|
||||
_all_trades = trades.Where(t => t.is_active);
|
||||
if (_report.CalcMode == Report.Types.ReportCalculationMode.PositionOrTheoChange) {
|
||||
_compute_dirty = true;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<UseWPF>true</UseWPF>
|
||||
@@ -22,39 +21,33 @@
|
||||
<RootNamespace>bts</RootNamespace>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<Version>$(major).$(minor).$(patch)</Version>
|
||||
<Version Condition="'$(version)'=='..'">1.0.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageReference Include="GitVersion.MsBuild" Version="5.12.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.24.3" />
|
||||
<PackageReference Include="IronPython" Version="3.4.1" />
|
||||
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||
<PackageReference Include="NAudio" Version="2.0.1" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="OxyPlot.Core" Version="2.1.2" />
|
||||
<PackageReference Include="OxyPlot.Wpf" Version="2.1.2" />
|
||||
<PackageReference Include="protobuf-net" Version="3.2.26" />
|
||||
<PackageReference Include="System.Composition" Version="7.0.0-preview.2.22152.2" />
|
||||
<PackageReference Include="System.Composition.AttributedModel" Version="7.0.0-preview.2.22152.2" />
|
||||
<PackageReference Include="System.Composition.Hosting" Version="7.0.0-preview.2.22152.2" />
|
||||
<PackageReference Include="System.Composition.TypedParts" Version="7.0.0-preview.2.22152.2" />
|
||||
<PackageReference Include="System.Reactive" Version="6.0.0" />
|
||||
<PackageReference Include="System.Reactive.Core" Version="6.0.0" />
|
||||
<PackageReference Include="System.Reactive.Interfaces" Version="6.0.0" />
|
||||
<PackageReference Include="System.Reactive.Linq" Version="6.0.0" />
|
||||
<PackageReference Include="System.Reactive.PlatformServices" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\spark_api\spark_api.csproj" />
|
||||
<ProjectReference Include="..\spark_core\spark_core.csproj" />
|
||||
<PackageReference Include="System.Reactive.Core" Version="5.0.0" />
|
||||
<PackageReference Include="System.Reactive.Interfaces" Version="5.0.0" />
|
||||
<PackageReference Include="System.Reactive.Linq" Version="5.0.0" />
|
||||
<PackageReference Include="System.Reactive.PlatformServices" Version="5.0.0" />
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
<ProjectReference Include="../spark_api/spark_api.csproj" />
|
||||
<ProjectReference Include="../spark_core/spark_core.csproj" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.21.4" />
|
||||
<PackageReference Include="IronPython" Version="2.7.12" />
|
||||
<PackageReference Include="NAudio" Version="2.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
|
||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||
<PackageReference Include="protobuf-net" Version="3.1.17" />
|
||||
<PackageReference Include="OxyPlot.Core" Version="2.1.2" />
|
||||
<PackageReference Include="OxyPlot.Wpf" Version="2.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -62,20 +55,15 @@
|
||||
<Resource Include="**/*.png" />
|
||||
<ConfigDefaults Include="../../lib/config/defaults/*.conf" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Resource Remove="logo.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="logo.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Sounds/game_sound_correct.wav" />
|
||||
<EmbeddedResource Include="Sounds/whistle.wav" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="diagnostic" AfterTargets="PreBuildEvent" />
|
||||
|
||||
</Project>
|
||||
@@ -35,7 +35,7 @@ namespace bts.core {
|
||||
// TODO: for debugging purposes, remove it later
|
||||
if (tag != mbts.spark.SparkTags.SparkTimer) {
|
||||
var tid = System.Threading.Thread.CurrentThread.ManagedThreadId;
|
||||
bts.Log.Ui.diag($"SimpleBus.post tag:{tag} tid:{tid}");
|
||||
//bts.Log.Ui.diag($"SimpleBus.post tag:{tag} tid:{tid}");
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@@ -45,7 +45,7 @@ namespace bts.core {
|
||||
|
||||
public IObservable<T> subscribe<T>(ITag<T> tag) {
|
||||
var tid = System.Threading.Thread.CurrentThread.ManagedThreadId;
|
||||
bts.Log.Ui.info($"SimpleBus.post tag:{tag} tid:{tid}");
|
||||
//bts.Log.Ui.info($"SimpleBus.subscribe tag:{tag} tid:{tid}");
|
||||
return subject<T>(tag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
|
||||
// Compare bids
|
||||
if (direct.int_price == implied.int_price) {
|
||||
bid[x] = new NativePriceSize(direct.int_price, direct.size_f, implied.size_f);
|
||||
bid[x] = new NativePriceSize(direct.int_price, direct.size, implied.size);
|
||||
dbid_idx++;
|
||||
ibid_idx++;
|
||||
}
|
||||
@@ -185,7 +185,7 @@
|
||||
|
||||
// Compare asks
|
||||
if (direct.int_price == implied.int_price) {
|
||||
ask[x] = new NativePriceSize(direct.int_price, direct.size_f, implied.size_f);
|
||||
ask[x] = new NativePriceSize(direct.int_price, direct.size, implied.size);
|
||||
dask_idx++;
|
||||
iask_idx++;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
namespace mbts.co2 {
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Size = System.Single;
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public readonly struct NativePriceLevel {
|
||||
readonly IntPrice _bid;
|
||||
readonly IntPrice _ask;
|
||||
readonly Size _bid_size;
|
||||
readonly Size _ask_size;
|
||||
readonly uint _bid_size;
|
||||
readonly uint _ask_size;
|
||||
|
||||
public NativePriceLevel(IntPrice bid, Size bid_size, IntPrice ask, Size ask_size) {
|
||||
public NativePriceLevel(IntPrice bid, uint bid_size, IntPrice ask, uint ask_size) {
|
||||
_bid = bid;
|
||||
_bid_size = bid_size;
|
||||
_ask = ask;
|
||||
|
||||
@@ -5,29 +5,27 @@ namespace mbts.co2 {
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using Size = System.Single;
|
||||
|
||||
public readonly struct NativePriceSize : IEquatable<NativePriceSize> {
|
||||
readonly IntPrice _price;
|
||||
readonly Size _size;
|
||||
readonly Size _direct_size;
|
||||
readonly uint _size;
|
||||
readonly uint _direct_size;
|
||||
|
||||
static NativePriceSize() =>
|
||||
Log.assert(Marshal.SizeOf<NativePriceSize>() == 16);
|
||||
|
||||
public NativePriceSize(IntPrice price, Size size) {
|
||||
public NativePriceSize(IntPrice price, uint size) {
|
||||
_price = price;
|
||||
_size = size;
|
||||
_direct_size = size;
|
||||
}
|
||||
|
||||
public NativePriceSize(long mantissa, sbyte exponent, Size size) {
|
||||
public NativePriceSize(long mantissa, sbyte exponent, uint size) {
|
||||
_price = new IntPrice(mantissa, exponent);
|
||||
_size = size;
|
||||
_direct_size = size;
|
||||
}
|
||||
|
||||
public NativePriceSize(IntPrice price, Size direct_size, Size implied_size) {
|
||||
public NativePriceSize(IntPrice price, uint direct_size, uint implied_size) {
|
||||
_price = price;
|
||||
_size = direct_size + implied_size;
|
||||
_direct_size = direct_size;
|
||||
@@ -38,18 +36,15 @@ namespace mbts.co2 {
|
||||
public IntPrice int_price => _price;
|
||||
public long mantissa => _price.mantissa;
|
||||
public sbyte exponent => _price.exponent;
|
||||
public uint size => (uint)_size;
|
||||
public uint direct_size => (uint)_direct_size;
|
||||
public uint implied_size => (uint)(_size - _direct_size);
|
||||
public Size size_f => _size;
|
||||
public Size direct_size_f => _direct_size;
|
||||
public Size implied_size_f => _size - _direct_size;
|
||||
public uint size => _size;
|
||||
public uint direct_size => _direct_size;
|
||||
public uint implied_size => _size - _direct_size;
|
||||
public double price => _price.price();
|
||||
public bool is_nan => _price.is_nan;
|
||||
|
||||
|
||||
public override string ToString() =>
|
||||
$"{price} {size_f} ({implied_size})";
|
||||
$"{price} {size} ({implied_size})";
|
||||
|
||||
public override bool Equals(object obj) =>
|
||||
obj is NativePriceSize p ? Equals(p) : base.Equals(obj);
|
||||
|
||||
@@ -3,14 +3,13 @@ using mbts.co2;
|
||||
|
||||
namespace bts.md
|
||||
{
|
||||
using Size = System.Single;
|
||||
public class PriceSize
|
||||
{
|
||||
public Size size { get; }
|
||||
public Size direct_size { get; }
|
||||
public Size implied_size { get; }
|
||||
public uint size { get; }
|
||||
public uint direct_size { get; }
|
||||
public uint implied_size { get; }
|
||||
public double price { get; }
|
||||
public PriceSize(Size sz, Size direct_sz, Size implied_sz, double prx)
|
||||
public PriceSize(uint sz, uint direct_sz, uint implied_sz, double prx)
|
||||
{
|
||||
size = sz;
|
||||
direct_size = direct_sz;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace bts.api {
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
|
||||
public static class SecurityExtensions {
|
||||
public static Security.ContractOneofCase contract_case(this SecurityType type) =>
|
||||
@@ -97,8 +96,6 @@ namespace bts.api {
|
||||
return security.Ice.SecurityDesc;
|
||||
} else if (security.HasDeribit) {
|
||||
return security.Deribit.SecurityDesc;
|
||||
} else if (security.HasFtx) {
|
||||
return security.Ftx.SecurityDesc;
|
||||
}
|
||||
Log.assert(false, "security_desc not implemented for exchange");
|
||||
return null;
|
||||
@@ -139,7 +136,6 @@ namespace bts.api {
|
||||
domain.Venue.Bts => Venue.Bts,
|
||||
domain.Venue.Sim => Venue.Sim,
|
||||
domain.Venue.Deribit => Venue.Deribit,
|
||||
domain.Venue.Ftx => Venue.Ftx,
|
||||
domain.Venue.Glbx => Venue.Glbx,
|
||||
domain.Venue.None => Venue.Unset,
|
||||
_ => throw new NotImplementedException(),
|
||||
@@ -150,7 +146,6 @@ namespace bts.api {
|
||||
Venue.Bts => domain.Venue.Bts,
|
||||
Venue.Sim => domain.Venue.Sim,
|
||||
Venue.Deribit => domain.Venue.Deribit,
|
||||
Venue.Ftx => domain.Venue.Ftx,
|
||||
Venue.Glbx => domain.Venue.Glbx,
|
||||
Venue.Unset => domain.Venue.None,
|
||||
_ => throw new NotImplementedException(),
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
string.IsNullOrEmpty(exch_desc) ? format_option(symbol, option) : exch_desc;
|
||||
|
||||
static string _format(SecurityImmutable? security) =>
|
||||
security.HasValue ? _format(security.Value) : "Unknown-security1";
|
||||
security.HasValue ? _format(security.Value) : "Unknown-security";
|
||||
|
||||
static string _format(SecurityImmutable security, bool exchange_specific_formatting = true) {
|
||||
switch (security.ContractCase) {
|
||||
@@ -71,10 +71,8 @@
|
||||
return string.Join("", _format_legs(new ContractLegEnumerable(security.Spread.Legs, 1)));
|
||||
case Security.ContractOneofCase.Synthetic:
|
||||
return security.Synthetic.Name;
|
||||
case Security.ContractOneofCase.Spot:
|
||||
return security.security_desc();
|
||||
default:
|
||||
return "Unknown-security2";
|
||||
return "Unknown-security";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,40 +79,6 @@ Misc:
|
||||
To search for a publisher for an event search for make_stream<Event_Name>, for
|
||||
example make_stream<OrderStateUpdateEvent>()
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
market data
|
||||
--------------------------------------------------------------------------
|
||||
adding exchanges:
|
||||
the following places need to accommodate exchanges
|
||||
managed:
|
||||
- SecurityExtensions: public static string security_desc(this SecurityImmutable security) ..
|
||||
- SecurityExtensions: public static Venue to_venue(this domain.Venue api_venue) ..
|
||||
- SecurityExtensions: public static domain.Venue to_api_venue(this Venue venue) ..
|
||||
C++
|
||||
- AdminServiceUtils.cpp, 6 switch statements should compilation error
|
||||
- Symbols.proto in Symbols
|
||||
- Symbols.conf exchange section in SymbolLists and Symbols
|
||||
- Security.proto, 3 places
|
||||
- PlatformLoader.cpp, in get_system_md_symbols(), could be concverted into switch
|
||||
- FixedSecurity.cpp, exchange_id(..) and convert_security(..) both switch
|
||||
- QueryServer set_mic, switch
|
||||
- VenueOption name(..) switch
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
adding security type
|
||||
---------------------------------------------------------------------------
|
||||
modified: src/lib/api/service_helpers/AdminServiceUtils.cpp
|
||||
modified: src/lib/domain_model/Security.cpp
|
||||
modified: src/lib/domain_model/Security.proto
|
||||
modified: src/lib/md/MDConsumer.cpp
|
||||
modified: src/lib/md/PlatformLoader.cpp
|
||||
modified: src/lib/md/SecurityMapper.cpp
|
||||
modified: src/lib/md/Shm/FixedSecurity.cpp
|
||||
modified: src/lib/md/Shm/FixedSecurity.h
|
||||
modified: src/lib/md/ccApi/CCMain.cpp
|
||||
modified: src/lib/md/ccApi/CCMarketDataListener.cpp
|
||||
modified: src/lib/md/relay/RelayClient.cpp
|
||||
modified: src/lib/orderman/limiter/Limiter.cpp
|
||||
|
||||
ALGO:
|
||||
----
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
set(sources api/analytics/ExpirationDriver.proto;api/analytics/TimeWeightedInterpolatedDriver.proto;api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/domain/Currency.proto;api/domain/SecurityCriteria.proto;api/domain/SecurityCriteriaClause.proto;api/domain/SecurityExpiration.proto;api/domain/SecurityMetadata.proto;api/domain/SecurityMetadataCollection.proto;api/domain/SecurityMetadataItem.proto;api/domain/SecurityType.proto;api/domain/TickDisplaySettings.proto;api/domain/TickFactors.proto;api/domain/Venue.proto;api/io/URL.proto;api/md/MarketDataSubscriptionParams.proto;api/md/binance/BinanceDepthStreamParams.proto;api/md/binance/BinanceMarketDataSubscriptionParams.proto;api/md/deribit/DeribitMarketDataSubscriptionParams.proto;api/md/ftx/FTXDepthStreamParams.proto;api/md/ftx/FTXMarketDataSubscriptionParams.proto;api/md/glbx/GlbxMarketDataSubscriptionParams.proto;api/md/huobi/HuobiMarketDataSubscriptionParams.proto;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/AnalyticsService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MarketDataService.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;communincation/websockets/tests/WebsocketSyncClientTests.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/SecurityMetadataCollection.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/algo_types.proto;config/protos/cme_reference_data.proto;config/protos/exchange_sim_cfg.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/market_data.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/ports.proto;config/protos/position_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spartan.proto;config/protos/spreader.proto;config/protos/subprocess.proto;config/protos/symbols.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/protos/ui.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain/AggressorSide.cpp;domain/NewOrder.cpp;domain/OrderDefinition.cpp;domain/OrderStatus.cpp;domain/OrderUpdate.cpp;domain/Side.cpp;domain/TimeInForce.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;io/QueryParams.cpp;io/URL.cpp;io/http/CurlHandle.cpp;io/http/HTTPClient.cpp;io/http/HTTPHeaders.cpp;io/http/HTTPRequest.cpp;io/http/HTTPResponse.cpp;io/websocket/WebsocketClient.cpp;io/websocket/WebsocketClientConfiguration.cpp;io/websocket/WebsocketError.cpp;io/websocket/WebsocketMessage.cpp;io/websocket/WebsocketSSLClientInternal.cpp;io/websocket/tests/WebsocketClientTests.cpp;jetfix/codec/FIXArray.cpp;jetfix/common/OutFIX.cpp;jetfix/connection/AsyncReader.cpp;jetfix/connection/IConnection.cpp;jetfix/connection/SocketConnection.cpp;jetfix/gateway/CoreGateway.cpp;jetfix/gateway/JetFIXGatLine truncated
|
||||
@@ -0,0 +1 @@
|
||||
set(sources api/analytics/ExpirationDriver.proto;api/analytics/TimeWeightedInterpolatedDriver.proto;api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/domain/Currency.proto;api/domain/SecurityCriteria.proto;api/domain/SecurityCriteriaClause.proto;api/domain/SecurityExpiration.proto;api/domain/SecurityMetadata.proto;api/domain/SecurityMetadataCollection.proto;api/domain/SecurityMetadataItem.proto;api/domain/SecurityType.proto;api/domain/TickDisplaySettings.proto;api/domain/TickFactors.proto;api/domain/Venue.proto;api/io/URL.proto;api/md/MarketDataSubscriptionParams.proto;api/md/binance/BinanceDepthStreamParams.proto;api/md/binance/BinanceMarketDataSubscriptionParams.proto;api/md/deribit/DeribitMarketDataSubscriptionParams.proto;api/md/ftx/FTXDepthStreamParams.proto;api/md/ftx/FTXMarketDataSubscriptionParams.proto;api/md/glbx/GlbxMarketDataSubscriptionParams.proto;api/md/huobi/HuobiMarketDataSubscriptionParams.proto;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/AnalyticsService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MarketDataService.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/SecurityMetadataCollection.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/algo_types.proto;config/protos/cme_reference_data.proto;config/protos/exchange_sim_cfg.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/market_data.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/ports.proto;config/protos/position_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spartan.proto;config/protos/spreader.proto;config/protos/subprocess.proto;config/protos/symbols.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/protos/ui.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;io/QueryParams.cpp;io/URL.cpp;io/http/CurlHandle.cpp;io/http/HTTPClient.cpp;io/http/HTTPHeaders.cpp;io/http/HTTPRequest.cpp;io/http/HTTPResponse.cpp;io/websocket/WebsocketClient.cpp;io/websocket/WebsocketClientConfiguration.cpp;io/websocket/WebsocketError.cpp;io/websocket/WebsocketMessage.cpp;io/websocket/WebsocketSSLClientInternal.cpp;io/websocket/tests/WebsocketClientTests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/CCApiDepthWalker.cpp;md/CCApiListenerAdaptor.cpp;md/CCApiRequestor.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MarketDataError.cpp;md/MarketDataGateway.cpLine truncated
|
||||
+162
-76
@@ -1,84 +1,170 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(libspark)
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
include(GNUInstallDirs)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/safe_dep_glob.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/Protobuf.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GenerateDefaultConfig.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/PrintList.cmake)
|
||||
|
||||
if (DEFINED DOTNET_BINARY_DIR OR DEFINED DOTNET_WINDOWS_BINARY_DIR)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/AddCopyBinariesTarget.cmake)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(BUILD_SPARKD)
|
||||
message(FATAL_ERROR "Cannot build sparkd on Windows (Please set BUILD_SPARKD to False)")
|
||||
endif()
|
||||
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetWindowsClientSources.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetWindowsClientLinkLibraries.cmake)
|
||||
elseif(${BUILD_SPARKD})
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetLinuxServerSources.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetLinuxServerLinkLibraries.cmake)
|
||||
else()
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetLinuxClientSources.cmake)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GetLinuxClientLinkLibraries.cmake)
|
||||
endif()
|
||||
|
||||
# Cpp sources
|
||||
set(${PROJECT_NAME}_Sources)
|
||||
get_cpp_sources(${PROJECT_NAME}_Sources)
|
||||
print_list(${PROJECT_NAME}_Sources VERBOSE)
|
||||
|
||||
# Proto sources
|
||||
get_proto_sources(_cfg_protos _non_cfg_protos _service_protos _cfg_defaults)
|
||||
print_list(_cfg_protos VERBOSE)
|
||||
print_list(_non_cfg_protos VERBOSE)
|
||||
print_list(_service_protos VERBOSE)
|
||||
print_list(_cfg_defaults VERBOSE)
|
||||
|
||||
update_deps_file("${${PROJECT_NAME}_Sources};${_cfg_protos};${_service_protos};${_non_cfg_protos};${_cfg_defaults}")
|
||||
|
||||
# Generate proto cpp
|
||||
message(STATUS "Generating proto cpp")
|
||||
protobuf_generate_cpp(_proto_srcs _proto_hdrs ${_non_cfg_protos} ${_cfg_protos})
|
||||
service_compiler_generate_cpp(SERVICE_COMPILER_SRCS SERVICE_COMPILER_HDRS ${_service_protos})
|
||||
message(STATUS "Generating default config")
|
||||
generate_default_config(_cfg_protos _cfg_defaults)
|
||||
add_library(${PROJECT_NAME} SHARED ${${PROJECT_NAME}_Sources} ${_proto_srcs} ${SERVICE_COMPILER_SRCS})
|
||||
|
||||
target_include_directories(
|
||||
${PROJECT_NAME} PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src>
|
||||
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
get_link_libraries(_link_libs)
|
||||
print_list(_link_libs VERBOSE)
|
||||
target_link_libraries(${PROJECT_NAME} ${_link_libs})
|
||||
|
||||
# Copy binaries to Dotnet build dirs (for csprojs that depend on libspark)
|
||||
if (DEFINED DOTNET_BINARY_DIR)
|
||||
add_copy_binaries_target(
|
||||
copy_to_dotnet_binary_dir
|
||||
"${DOTNET_BINARY_DIR}"
|
||||
"Copy ${PROJECT_NAME} bins to Dotnet build dir")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/vs_filters.cmake)
|
||||
endif()
|
||||
|
||||
foreach(_hdr ${_proto_hdrs})
|
||||
file(RELATIVE_PATH _relative_path ${CMAKE_CURRENT_BINARY_DIR}/protobufs ${_hdr})
|
||||
install(FILES ${_hdr} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${_relative_path})
|
||||
endforeach()
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/InstallBasic.cmake)
|
||||
# DEPENDENCIES
|
||||
file(
|
||||
GLOB_RECURSE _hdrs
|
||||
GLOB_RECURSE Config_Protos
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.h
|
||||
)
|
||||
install_basic(HEADERS ${_hdrs})
|
||||
config/protos/*.proto
|
||||
api/domain/SecurityMetadataCollection.proto)
|
||||
file(
|
||||
GLOB_RECURSE Service_Protos
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
api/services/*.proto)
|
||||
file(
|
||||
GLOB_RECURSE NonConfig_Protos
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.proto)
|
||||
list(REMOVE_ITEM NonConfig_Protos ${Service_Protos} ${Config_Protos})
|
||||
file(
|
||||
GLOB_RECURSE Conf_Defaults
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
config/defaults/*.conf)
|
||||
|
||||
if(WIN32)
|
||||
file(
|
||||
GLOB_RECURSE SparkLib_Sources
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
api/*.cpp
|
||||
config/*.cpp
|
||||
domain_model/*.cpp
|
||||
expression/*.cpp
|
||||
logging/*.cpp
|
||||
io/*.cpp
|
||||
md/*.cpp
|
||||
os/*.cpp
|
||||
quickbus/*.cpp
|
||||
sparkproto/*.cpp
|
||||
testing/*.cpp
|
||||
utils/*.cpp)
|
||||
else()
|
||||
file(
|
||||
GLOB_RECURSE SparkLib_Sources
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.cpp)
|
||||
endif()
|
||||
|
||||
update_deps_file("${SparkLib_Sources};${Config_Protos};${Service_Protos};${NonConfig_Protos};${Conf_Defaults}")
|
||||
# END DEPENDENCIES
|
||||
|
||||
protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS ${NonConfig_Protos} ${Config_Protos})
|
||||
service_compiler_generate_cpp(SERVICE_COMPILER_SRCS SERVICE_COMPILER_HDRS ${Service_Protos})
|
||||
|
||||
# generate list of config protos
|
||||
set(config_proto_file ${CMAKE_CURRENT_BINARY_DIR}/config_proto_files.h)
|
||||
|
||||
# generate a string with the current config files
|
||||
set(config_proto_str "const char * config_proto_files[] = { // generated file\n")
|
||||
foreach(protopath ${Config_Protos})
|
||||
get_filename_component(protoname ${protopath} NAME)
|
||||
string(APPEND config_proto_str "\"${protoname}\",\n")
|
||||
endforeach(protopath)
|
||||
string(APPEND config_proto_str "} ;\n")
|
||||
|
||||
# compare with file and if there is any difference update the file
|
||||
set(old_config_proto_str "")
|
||||
if(EXISTS "${config_proto_file}")
|
||||
file(READ "${config_proto_file}" old_config_proto_str)
|
||||
endif()
|
||||
if(NOT old_config_proto_str STREQUAL config_proto_str)
|
||||
file(WRITE "${config_proto_file}" "${config_proto_str}")
|
||||
endif()
|
||||
|
||||
# generate static defaults
|
||||
set(config_defaults_file ${CMAKE_CURRENT_BINARY_DIR}/config_defaults.h)
|
||||
# Defaults cannot be a single string because the compiler complains about a string longer than 65k
|
||||
set(config_defaults_str "const char * config_static_defaults[] = { ")
|
||||
foreach(cfg_file_path ${Conf_Defaults})
|
||||
file(READ ${cfg_file_path} cfg_file_content)
|
||||
string(REPLACE "\"" "\\\"" cfg_file_content_escaped ${cfg_file_content})
|
||||
string(REPLACE "\n" ";" cfg_lines ${cfg_file_content_escaped})
|
||||
foreach(line ${cfg_lines})
|
||||
string(APPEND config_defaults_str "\n \"${line}\",")
|
||||
endforeach(line)
|
||||
endforeach(cfg_file_path)
|
||||
string(APPEND config_defaults_str "};")
|
||||
set(old_defaults_str "")
|
||||
if(EXISTS ${config_defaults_file})
|
||||
file(READ ${config_defaults_file} old_defaults_str)
|
||||
endif()
|
||||
if(NOT config_defaults_str STREQUAL old_defaults_str)
|
||||
file(WRITE "${config_defaults_file}" "${config_defaults_str}")
|
||||
endif()
|
||||
|
||||
# lib
|
||||
if(WIN32)
|
||||
add_library(libspark SHARED ${SparkLib_Sources} ${PROTO_SRCS} ${SERVICE_COMPILER_SRCS})
|
||||
else()
|
||||
add_library(libspark SHARED ${SparkLib_Sources} ${PROTO_SRCS} ${SERVICE_COMPILER_SRCS})
|
||||
endif()
|
||||
|
||||
# include paths
|
||||
target_include_directories(
|
||||
libspark PUBLIC
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_BINARY_DIR}/src)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(
|
||||
libspark
|
||||
libcurl
|
||||
debug
|
||||
fmtd
|
||||
optimized
|
||||
fmt
|
||||
libtbb
|
||||
libboost_system
|
||||
libboost_thread
|
||||
libboost_filesystem
|
||||
libboost_regex
|
||||
libboost_chrono
|
||||
libboost_date_time
|
||||
libboost_atomic
|
||||
libprotobuf
|
||||
libprotoc
|
||||
libssl
|
||||
libcrypto
|
||||
crypt32)
|
||||
else()
|
||||
target_link_libraries(
|
||||
libspark
|
||||
protobuf
|
||||
double-conversion
|
||||
boost_system
|
||||
boost_thread
|
||||
boost_filesystem
|
||||
boost_regex
|
||||
boost_chrono
|
||||
boost_date_time
|
||||
boost_atomic
|
||||
SQLiteCpp
|
||||
sqlite3
|
||||
curl
|
||||
uuid
|
||||
ssl
|
||||
crypto
|
||||
fmt
|
||||
tbb
|
||||
cryptopp
|
||||
pugixml
|
||||
lttng-ust
|
||||
Pcap++
|
||||
Packet++
|
||||
Common++
|
||||
ssh2
|
||||
-lrt
|
||||
-ldl
|
||||
-lpcap
|
||||
-static-libgcc
|
||||
-static-libstdc++
|
||||
-pthread)
|
||||
|
||||
install(TARGETS libspark DESTINATION bin)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
include(${CMAKE_SOURCE_DIR}/tools/vs_filters.cmake)
|
||||
endif()
|
||||
@@ -1,5 +0,0 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
|
||||
check_required_components(@PROJECT_NAME@)
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "lib/config/protos/quickbus_cfg.pb.h"
|
||||
#include "lib/config/protos/system.pb.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef WIN32
|
||||
#include <excpt.h>
|
||||
#endif
|
||||
|
||||
@@ -59,7 +59,7 @@ CAPI Quickbus *api_create_quickbus(const char *qbconfig, long length) {
|
||||
}
|
||||
|
||||
CAPI void api_destroy_quickbus(Quickbus *qbus) {
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
if (qbus != nullptr) {
|
||||
delete qbus;
|
||||
}
|
||||
@@ -186,7 +186,7 @@ CAPI void api_client_send(
|
||||
void *extra) {
|
||||
LOG(Api, Diag, "send rpc {}", ((int64_t)buffer));
|
||||
std::string strbuf(buffer, buffer_length);
|
||||
qbus::RPCRequest request(std::move(strbuf));
|
||||
qbus::RPCRequest request(move(strbuf));
|
||||
api_client_send_internal(
|
||||
pclient, std::move(request), cb, rpc_connect_timeout_ms(), extra);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ CAPI void api_server_call_callback(
|
||||
reinterpret_cast<qbus::ReplyHandler **>(ppvhandler);
|
||||
std::string reply_buffer((const char *)buffer, (size_t)length);
|
||||
qbus::RPCReplyPtr replyptr =
|
||||
std::make_shared<qbus::RPCReply>(std::move(reply_buffer));
|
||||
std::make_shared<qbus::RPCReply>(move(reply_buffer));
|
||||
(**pphandler)(replyptr);
|
||||
delete (*pphandler);
|
||||
*pphandler = nullptr;
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "lib/api/domain/Venue.proto";
|
||||
|
||||
package bts.api.md;
|
||||
|
||||
message DepthStreamConfig {
|
||||
bts.api.domain.Venue venue = 1;
|
||||
repeated string symbols = 2;
|
||||
uint32 num_levels = 3;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "lib/api/md/DepthStreamConfig.proto";
|
||||
|
||||
package bts.api.md;
|
||||
|
||||
message MarketDataConfig {
|
||||
repeated bts.api.md.DepthStreamConfig depth_streams = 1;
|
||||
uint32 num_dispatcher_threads = 2;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "lib/api/md/binance/BinanceMarketDataSubscriptionParams.proto";
|
||||
import "lib/api/md/deribit/DeribitMarketDataSubscriptionParams.proto";
|
||||
import "lib/api/md/ftx/FTXMarketDataSubscriptionParams.proto";
|
||||
import "lib/api/md/glbx/GlbxMarketDataSubscriptionParams.proto";
|
||||
import "lib/api/md/huobi/HuobiMarketDataSubscriptionParams.proto";
|
||||
|
||||
package bts.api.md;
|
||||
|
||||
message MarketDataSubscriptionParams {
|
||||
oneof VenueParams {
|
||||
bts.api.md.glbx.GlbxMarketDataSubscriptionParams glbx = 1;
|
||||
bts.api.md.deribit.DeribitMarketDataSubscriptionParams deribit = 2;
|
||||
bts.api.md.binance.BinanceMarketDataSubscriptionParams binance = 3;
|
||||
bts.api.md.huobi.HuobiMarketDataSubscriptionParams huobi = 4;
|
||||
bts.api.md.ftx.FTXMarketDataSubscriptionParams ftx = 5;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package bts.api.md.deribit;
|
||||
|
||||
message DeribitMarketDataSubscriptionParams {
|
||||
// TODO
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package bts.api.md.ftx;
|
||||
|
||||
message FTXDepthStreamParams {
|
||||
repeated string symbols = 1;
|
||||
uint32 num_levels = 2;
|
||||
uint32 num_dispatcher_threads = 3;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
import "lib/api/md/ftx/FTXDepthStreamParams.proto";
|
||||
|
||||
package bts.api.md.ftx;
|
||||
|
||||
message FTXMarketDataSubscriptionParams {
|
||||
repeated FTXDepthStreamParams depth_streams = 2;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package bts.api.md.glbx;
|
||||
|
||||
message GlbxMarketDataSubscriptionParams {
|
||||
// TODO
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package bts.api.md.huobi;
|
||||
|
||||
message HuobiMarketDataSubscriptionParams {
|
||||
// TODO
|
||||
}
|
||||
@@ -72,7 +72,7 @@ class ClientChannel {
|
||||
response_buffer + header_size,
|
||||
response_size - header_size);
|
||||
if (response->ParseFromZeroCopyStream(&data_stream)) {
|
||||
on_response(Result<Response>(std::move(response)));
|
||||
on_response(Result<Response>(move(response)));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ void QuickbusClientChannel::send_core(
|
||||
(*on_response)(buffer, length);
|
||||
delete on_response;
|
||||
};
|
||||
OnReply *heap_on_response = new OnReply(std::move(on_response));
|
||||
OnReply *heap_on_response = new OnReply(move(on_response));
|
||||
api_client_send(
|
||||
_pclient, request_envalope.c_str(), request_envalope.size(), trampoline,
|
||||
heap_on_response);
|
||||
|
||||
@@ -161,7 +161,7 @@ def to_type_model(field, msg):
|
||||
elif field.type == types.TYPE_DOUBLE: return TypeModel("double", islist, "double?", jstype='number')
|
||||
elif field.type == types.TYPE_FLOAT: return TypeModel("float", islist, "float?", jstype='number', fstype='float32')
|
||||
elif field.type == types.TYPE_STRING: return TypeModel("string", islist, cpptype="std::string")
|
||||
elif field.type == types.TYPE_BYTES: return TypeModel("ByteString", islist, cpptype="std::string", jstype='Uint8Array', fstype='Fable.Import.JS.Uint8Array')
|
||||
elif field.type == types.TYPE_BYTES: return TypeModel("ByteString", islist, cpptype="std::string", jstype='Uint8Array', fstype='Fable.Core.JS.Uint8Array')
|
||||
elif field.type == types.TYPE_BOOL: return TypeModel("bool", islist, "bool?", jstype='boolean', natural_key=True)
|
||||
elif field.type == types.TYPE_ENUM:
|
||||
nested_enums = [x.name for x in msg.enum_type]
|
||||
|
||||
@@ -11,8 +11,8 @@ using namespace rxcpp::operators;
|
||||
{{#each service}}
|
||||
|
||||
// Constructor
|
||||
{{name}}::{{name}}(std::unique_ptr<bts::api::ClientChannel> pchannel) : _pchannel(std::move(pchannel)) {}
|
||||
{{name}}::{{name}}({{name}}&& other) : _pchannel(std::move(other._pchannel)) { }
|
||||
{{name}}::{{name}}(std::unique_ptr<bts::api::ClientChannel> pchannel) : _pchannel(move(pchannel)) {}
|
||||
{{name}}::{{name}}({{name}}&& other) : _pchannel(move(other._pchannel)) { }
|
||||
|
||||
{{#each method}}
|
||||
{{#if server_streaming}}
|
||||
|
||||
@@ -52,7 +52,6 @@ bool AdminServiceUtils::has_exchange(
|
||||
rv = conn.has_ice_connection();
|
||||
break;
|
||||
case api::Venue::VENUE_DERIBIT: // TODO
|
||||
case api::Venue::VENUE_FTX:
|
||||
case api::Venue::VENUE_BTS:
|
||||
case api::Venue::VENUE_CBOE:
|
||||
case api::Venue::VENUE_CBOECFE:
|
||||
@@ -162,7 +161,6 @@ AdminServiceUtils::resolve_connection(
|
||||
rv = resolve_sim_connection(data, account, sec);
|
||||
break;
|
||||
case api::Venue::VENUE_DERIBIT:
|
||||
case api::Venue::VENUE_FTX:
|
||||
rv = resolve_sim_connection(data, account, sec);
|
||||
break;
|
||||
case api::Venue::VENUE_CBOE:
|
||||
@@ -412,7 +410,6 @@ std::string AdminServiceUtils::find_account_exchange_account(
|
||||
}
|
||||
case api::Venue::VENUE_UNSET:
|
||||
case api::Venue::VENUE_DERIBIT: // TODO
|
||||
case api::Venue::VENUE_FTX: // TODO
|
||||
case api::Venue::VENUE_BTS:
|
||||
case api::Venue::VENUE_CBOE:
|
||||
case api::Venue::VENUE_CBOECFE:
|
||||
@@ -689,7 +686,6 @@ bts::api::orderman::RoutingRecord AdminServiceUtils::get_routing_record(
|
||||
rv.set_customer_or_firm(sim_account_data->origin());
|
||||
return rv;
|
||||
} break;
|
||||
case api::VENUE_FTX: // TODO
|
||||
case api::Venue::VENUE_UNSET:
|
||||
case api::Venue::VENUE_BTS:
|
||||
case api::Venue::VENUE_CBOE:
|
||||
@@ -1079,7 +1075,6 @@ std::string AdminServiceUtils::find_user_exchange_id(
|
||||
break;
|
||||
}
|
||||
case api::Venue::VENUE_DERIBIT: // TODO
|
||||
case api::Venue::VENUE_FTX: // TODO
|
||||
case api::Venue::VENUE_UNSET:
|
||||
case api::Venue::VENUE_BTS:
|
||||
case api::Venue::VENUE_CBOE:
|
||||
@@ -1108,7 +1103,6 @@ std::string AdminServiceUtils::find_user_company_id(
|
||||
break;
|
||||
}
|
||||
case api::Venue::VENUE_DERIBIT:
|
||||
case api::Venue::VENUE_FTX: // TODO
|
||||
case api::Venue::VENUE_SIM:
|
||||
case api::Venue::VENUE_SIMICE:
|
||||
case api::Venue::VENUE_GLBX:
|
||||
@@ -1646,8 +1640,6 @@ api::SecurityType AdminServiceUtils::security_type(
|
||||
return api::SecurityType::SECURITYTYPE_FUTURE;
|
||||
case api::Security::ContractCase::kOption:
|
||||
return api::SecurityType::SECURITYTYPE_OPTION;
|
||||
case api::Security::ContractCase::kSpot:
|
||||
return api::SecurityType::SECURITYTYPE_STOCK;
|
||||
case api::Security::ContractCase::kSpread:
|
||||
return api::SecurityType::SECURITYTYPE_SPREAD;
|
||||
case api::Security::ContractCase::kSynthetic:
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
function(add_copy_binaries_target tgt_name dest_dir)
|
||||
set(_dest_files)
|
||||
foreach (_dest_dir ${dest_dir})
|
||||
set(_dest_file ${_dest_dir}/${PROJECT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
list(APPEND _dest_files ${_dest_file})
|
||||
add_custom_command(
|
||||
OUTPUT ${_dest_file}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS -E copy
|
||||
${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${PROJECT_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${_dest_file}
|
||||
DEPENDS ${PROJECT_NAME})
|
||||
endforeach()
|
||||
add_custom_target(${tgt_name} ALL DEPENDS ${_dest_files} COMMENT ${ARGN})
|
||||
endfunction()
|
||||
@@ -1,53 +0,0 @@
|
||||
function(generate_default_config cfg_protos cfg_defaults)
|
||||
# generate list of config protos
|
||||
set(_cfg_proto_file ${CMAKE_CURRENT_BINARY_DIR}/config_proto_files.h)
|
||||
|
||||
# generate a string with the current config files
|
||||
set(_cfg_proto_str "const char * config_proto_files[] = { // generated file\n")
|
||||
|
||||
foreach(_proto_path ${${cfg_protos}})
|
||||
get_filename_component(_proto_name ${_proto_path} NAME)
|
||||
string(APPEND _cfg_proto_str "\"${_proto_name}\",\n")
|
||||
endforeach(_proto_path)
|
||||
|
||||
string(APPEND _cfg_proto_str "} ;\n")
|
||||
|
||||
# compare with file and if there is any difference update the file
|
||||
set(_old_cfg_proto_str "")
|
||||
|
||||
if(EXISTS "${_cfg_proto_file}")
|
||||
file(READ "${_cfg_proto_file}" _old_cfg_proto_str)
|
||||
endif()
|
||||
|
||||
if(NOT _old_cfg_proto_str STREQUAL _cfg_proto_str)
|
||||
file(WRITE "${_cfg_proto_file}" "${_cfg_proto_str}")
|
||||
endif()
|
||||
|
||||
# generate static defaults
|
||||
set(_cfg_defaults_file ${CMAKE_CURRENT_BINARY_DIR}/config_defaults.h)
|
||||
|
||||
# Defaults cannot be a single string because the compiler complains about a
|
||||
# string longer than 65k
|
||||
set(_cfg_defaults_str "const char * config_static_defaults[] = { ")
|
||||
|
||||
foreach(_cfg_file_path ${${cfg_defaults}})
|
||||
file(READ ${_cfg_file_path} _cfg_file_content)
|
||||
string(REPLACE "\"" "\\\"" _cfg_file_content_escaped ${_cfg_file_content})
|
||||
string(REPLACE "\n" ";" _cfg_lines ${_cfg_file_content_escaped})
|
||||
|
||||
foreach(_line ${_cfg_lines})
|
||||
string(APPEND _cfg_defaults_str "\n \"${_line}\",")
|
||||
endforeach(_line)
|
||||
endforeach(_cfg_file_path)
|
||||
|
||||
string(APPEND _cfg_defaults_str "};")
|
||||
set(_old_cfg_defaults_str "")
|
||||
|
||||
if(EXISTS ${_cfg_defaults_file})
|
||||
file(READ ${_cfg_defaults_file} _old_cfg_defaults_str)
|
||||
endif()
|
||||
|
||||
if(NOT _cfg_defaults_str STREQUAL _old_cfg_defaults_str)
|
||||
file(WRITE "${_cfg_defaults_file}" "${_cfg_defaults_str}")
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -1,23 +0,0 @@
|
||||
function(get_link_libraries dest)
|
||||
set(${dest}
|
||||
curl
|
||||
tbb
|
||||
boost_system
|
||||
boost_thread
|
||||
boost_filesystem
|
||||
boost_regex
|
||||
boost_chrono
|
||||
boost_date_time
|
||||
boost_atomic
|
||||
protobuf
|
||||
protoc
|
||||
ssl
|
||||
crypto
|
||||
debug fmtd
|
||||
optimized fmt
|
||||
cryptopp
|
||||
SQLiteCpp
|
||||
sqlite3
|
||||
uuid
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,172 +0,0 @@
|
||||
function(get_proto_sources cfg_srcs non_cfg_srcs service_srcs cfg_defaults)
|
||||
file(
|
||||
GLOB_RECURSE _cfg_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
config/protos/*.proto
|
||||
api/domain/SecurityMetadataCollection.proto)
|
||||
file(
|
||||
GLOB_RECURSE _service_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
api/services/*.proto)
|
||||
file(
|
||||
GLOB_RECURSE _non_cfg_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.proto)
|
||||
list(REMOVE_ITEM _non_cfg_srcs ${_service_srcs} ${_cfg_srcs})
|
||||
|
||||
file(
|
||||
GLOB_RECURSE _cfg_defaults
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CONFIG_DEFAULTS_PATH})
|
||||
|
||||
set(_cfg_defaults)
|
||||
|
||||
foreach(cfg_path ${CONFIG_DEFAULTS_PATH})
|
||||
file(
|
||||
GLOB_RECURSE cfg_files
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${cfg_path})
|
||||
list(APPEND _cfg_defaults ${cfg_files})
|
||||
endforeach()
|
||||
|
||||
set(${cfg_srcs} ${_cfg_srcs} PARENT_SCOPE)
|
||||
set(${non_cfg_srcs} ${_non_cfg_srcs} PARENT_SCOPE)
|
||||
set(${service_srcs} ${_service_srcs} PARENT_SCOPE)
|
||||
set(${cfg_defaults} ${_cfg_defaults} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_cpp_sources dest)
|
||||
set(${dest}
|
||||
api/core/ApiClientInterop.cpp
|
||||
api/core/ApiServerInterop.cpp
|
||||
api/md/MarketDataConfigUtils.cpp
|
||||
api/public/ApiServer.cpp
|
||||
api/public/ClientChannel.cpp
|
||||
api/public/QuickbusClientChannel.cpp
|
||||
api/public/ServerChannel.cpp
|
||||
api/public/ServiceContext.cpp
|
||||
api/test/ApiTests.cpp
|
||||
api/test/HelloServiceServer.cpp
|
||||
config/ConfigDownloader.cpp
|
||||
config/ConfigErrorCollector.cpp
|
||||
config/ConfigPropertyEvaluator.cpp
|
||||
config/ConfigQuerier.cpp
|
||||
config/ConfigValueQueue.cpp
|
||||
config/ConfigurationException.cpp
|
||||
config/ConfigurationState.cpp
|
||||
config/PreprocessInputStream.cpp
|
||||
config/config.cpp
|
||||
config/tests/HTTPServer.cpp
|
||||
config/tests/config_ref_tests.cpp
|
||||
config/tests/config_tests.cpp
|
||||
config/text_format/text_format.cpp
|
||||
core/TimeSpan.cpp
|
||||
core/TimeStamp.cpp
|
||||
domain/DomainSecurityUtils.cpp
|
||||
domain/SecurityCriteria.cpp
|
||||
domain/SecurityCriteriaClause.cpp
|
||||
domain_model/Security.cpp
|
||||
domain_model/SecurityTests.cpp
|
||||
domain_model/sod.cpp
|
||||
domain_model/tests/domain_tests.cpp
|
||||
expression/BooleanGrammar.cpp
|
||||
expression/ExpressionEvaluator.cpp
|
||||
expression/ParserExceptions.cpp
|
||||
expression/Value.cpp
|
||||
expression/tests/expression_parser_tests.cpp
|
||||
io/http/CurlHandle.cpp
|
||||
io/http/HTTPClient.cpp
|
||||
io/http/HTTPHeaders.cpp
|
||||
io/http/HTTPRequest.cpp
|
||||
io/http/HTTPResponse.cpp
|
||||
logging/LoggerHub.cpp
|
||||
logging/Sink.cpp
|
||||
logging/logging.cpp
|
||||
logging/tests/logging_tests.cpp
|
||||
md/Diag/MDPeriodicDumper.cpp
|
||||
md/Diag/ShmDumper.cpp
|
||||
md/MBOProcessor.cpp
|
||||
md/MBOServiceServer.cpp
|
||||
md/MDClient.cpp
|
||||
md/MDConsumer.cpp
|
||||
md/MDConsumerHandle.cpp
|
||||
md/MDConsumerInterop.cpp
|
||||
md/MDProducer.cpp
|
||||
md/MDProducerHandle.cpp
|
||||
md/MemorySegmentUtils.cpp
|
||||
md/PriceSize.cpp
|
||||
md/Product.cpp
|
||||
md/SecurityCache.cpp
|
||||
md/SecurityDB.cpp
|
||||
md/SecurityIDRecorder.cpp
|
||||
md/SecurityMapper.cpp
|
||||
md/SecurityMarketState.cpp
|
||||
md/SecurityOracle.cpp
|
||||
md/SecurityStore.cpp
|
||||
md/SettlementRecorder.cpp
|
||||
md/Shm/FixedSecurity.cpp
|
||||
md/SyntheticSecurityService.cpp
|
||||
md/cme/MDP3Utils.cpp
|
||||
md/common.cpp
|
||||
md/ice/ICEUtils.cpp
|
||||
md/relay/QueryServer.cpp
|
||||
md/relay/RelayClient.cpp
|
||||
md/relay/RelayRecorder.cpp
|
||||
md/service/MarketDataServiceServer.cpp
|
||||
md/test/Co2ManagedTestHelper.cpp
|
||||
md/test/Co2TestInstrument.cpp
|
||||
md/test/mbo_tests.cpp
|
||||
md/test/md2_tests.cpp
|
||||
md/test/md_test_utils.cpp
|
||||
md/test/synthetic_book_merge_tests.cpp
|
||||
os/os.cpp
|
||||
os/tests/os_tests.cpp
|
||||
quickbus/core/LocalNode.cpp
|
||||
quickbus/core/Quickbus.cpp
|
||||
quickbus/core/SubscriptionID.cpp
|
||||
quickbus/core/TableID.cpp
|
||||
quickbus/message_model/Update.cpp
|
||||
quickbus/message_model/merge_updates.cpp
|
||||
quickbus/network/QBConnection.cpp
|
||||
quickbus/network/QBConnectionManager.cpp
|
||||
quickbus/network/endpoint_description.cpp
|
||||
quickbus/pubsub/TablePublisher.cpp
|
||||
quickbus/pubsub/TableSubscriber.cpp
|
||||
quickbus/pubsub/tests/qb_pubsub_tests.cpp
|
||||
quickbus/routing/INode.cpp
|
||||
quickbus/routing/NodeID.cpp
|
||||
quickbus/routing/Router.cpp
|
||||
quickbus/rpc/RPCClient.cpp
|
||||
quickbus/rpc/RPCServer.cpp
|
||||
quickbus/rpc/RPCSessionID.cpp
|
||||
quickbus/rpc/rpc_utils.cpp
|
||||
quickbus/rpc/tests/qb_rpc_tests.cpp
|
||||
quickbus/tests/quickbus_tests.cpp
|
||||
testing/catch_test_runner.cpp
|
||||
utils/AuthSessionManager.cpp
|
||||
utils/AuthToken.cpp
|
||||
utils/Dispatcher.cpp
|
||||
utils/FileUtils.cpp
|
||||
utils/GrowableSPSCQueue.cpp
|
||||
utils/HTTPStream.cpp
|
||||
utils/MathUtils.cpp
|
||||
utils/PBUtils.cpp
|
||||
utils/Puid.cpp
|
||||
utils/SecureLogon.cpp
|
||||
utils/SharedMemory.cpp
|
||||
utils/Sqlite_utils.cpp
|
||||
utils/Uuid.cpp
|
||||
utils/datetime.cpp
|
||||
utils/download.cpp
|
||||
utils/file_utils.cpp
|
||||
utils/init_spark_lib.cpp
|
||||
utils/is_unittest_environment.cpp
|
||||
utils/sftp.cpp
|
||||
utils/stats.cpp
|
||||
utils/tests/AuthTokenTests.cpp
|
||||
utils/tests/IDGeneratorTests.cpp
|
||||
utils/tests/MathUtilsTests.cpp
|
||||
utils/tests/SingleWriterConcurrentVectorTests.cpp
|
||||
utils/thread_manager.cpp
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,35 +0,0 @@
|
||||
function(get_link_libraries dest)
|
||||
set(${dest}
|
||||
protobuf
|
||||
double-conversion
|
||||
boost_system
|
||||
boost_thread
|
||||
boost_filesystem
|
||||
boost_regex
|
||||
boost_chrono
|
||||
boost_date_time
|
||||
boost_atomic
|
||||
SQLiteCpp
|
||||
sqlite3
|
||||
curl
|
||||
uuid
|
||||
ssl
|
||||
crypto
|
||||
debug fmtd
|
||||
optimized fmt
|
||||
tbb
|
||||
cryptopp
|
||||
pugixml
|
||||
lttng-ust
|
||||
Pcap++
|
||||
Packet++
|
||||
Common++
|
||||
ssh2
|
||||
-lrt
|
||||
-ldl
|
||||
-lpcap
|
||||
-static-libgcc
|
||||
-static-libstdc++
|
||||
-pthread
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,45 +0,0 @@
|
||||
function(get_proto_sources cfg_srcs non_cfg_srcs service_srcs cfg_defaults)
|
||||
file(
|
||||
GLOB_RECURSE _cfg_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
config/protos/*.proto
|
||||
api/domain/SecurityMetadataCollection.proto
|
||||
api/md/MarketDataConfig.proto)
|
||||
file(
|
||||
GLOB_RECURSE _service_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
api/services/*.proto)
|
||||
file(
|
||||
GLOB_RECURSE _non_cfg_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.proto)
|
||||
list(REMOVE_ITEM _non_cfg_srcs ${_service_srcs} ${_cfg_srcs})
|
||||
|
||||
file(
|
||||
GLOB_RECURSE _cfg_defaults
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CONFIG_DEFAULTS_PATH})
|
||||
|
||||
set(_cfg_defaults)
|
||||
|
||||
foreach(cfg_path ${CONFIG_DEFAULTS_PATH})
|
||||
file(
|
||||
GLOB_RECURSE cfg_files
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${cfg_path})
|
||||
list(APPEND _cfg_defaults ${cfg_files})
|
||||
endforeach()
|
||||
|
||||
set(${cfg_srcs} ${_cfg_srcs} PARENT_SCOPE)
|
||||
set(${non_cfg_srcs} ${_non_cfg_srcs} PARENT_SCOPE)
|
||||
set(${service_srcs} ${_service_srcs} PARENT_SCOPE)
|
||||
set(${cfg_defaults} ${_cfg_defaults} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_cpp_sources dest)
|
||||
file(
|
||||
GLOB_RECURSE _dest
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.cpp)
|
||||
set(${dest} ${_dest} PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,20 +0,0 @@
|
||||
function(get_link_libraries dest)
|
||||
find_package(fmt CONFIG REQUIRED)
|
||||
set(${dest}
|
||||
crypt32
|
||||
fmt::fmt-header-only
|
||||
libcrypto
|
||||
libcurl
|
||||
libboost_system
|
||||
libboost_thread
|
||||
libboost_filesystem
|
||||
libboost_regex
|
||||
libboost_chrono
|
||||
libboost_date_time
|
||||
libboost_atomic
|
||||
libprotobuf
|
||||
libprotoc
|
||||
libssl
|
||||
libtbb
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -1,162 +0,0 @@
|
||||
function(get_proto_sources cfg_srcs non_cfg_srcs service_srcs cfg_defaults)
|
||||
file(
|
||||
GLOB_RECURSE _cfg_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
config/protos/*.proto
|
||||
api/domain/SecurityMetadataCollection.proto)
|
||||
file(
|
||||
GLOB_RECURSE _service_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
api/services/*.proto)
|
||||
file(
|
||||
GLOB_RECURSE _non_cfg_srcs
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
*.proto)
|
||||
list(REMOVE_ITEM _non_cfg_srcs ${_service_srcs} ${_cfg_srcs})
|
||||
|
||||
file(
|
||||
GLOB_RECURSE _cfg_defaults
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CONFIG_DEFAULTS_PATH})
|
||||
|
||||
set(_cfg_defaults)
|
||||
|
||||
foreach(cfg_path ${CONFIG_DEFAULTS_PATH})
|
||||
file(
|
||||
GLOB_RECURSE cfg_files
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${cfg_path})
|
||||
list(APPEND _cfg_defaults ${cfg_files})
|
||||
endforeach()
|
||||
|
||||
set(${cfg_srcs} ${_cfg_srcs} PARENT_SCOPE)
|
||||
set(${non_cfg_srcs} ${_non_cfg_srcs} PARENT_SCOPE)
|
||||
set(${service_srcs} ${_service_srcs} PARENT_SCOPE)
|
||||
set(${cfg_defaults} ${_cfg_defaults} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_cpp_sources dest)
|
||||
set(${dest}
|
||||
api/core/ApiClientInterop.cpp
|
||||
api/core/ApiServerInterop.cpp
|
||||
api/public/ApiServer.cpp
|
||||
api/public/ClientChannel.cpp
|
||||
api/public/QuickbusClientChannel.cpp
|
||||
api/public/ServerChannel.cpp
|
||||
api/public/ServiceContext.cpp
|
||||
api/test/ApiTests.cpp
|
||||
api/test/HelloServiceServer.cpp
|
||||
config/ConfigCheck.cpp
|
||||
config/ConfigDownloader.cpp
|
||||
config/ConfigErrorCollector.cpp
|
||||
config/ConfigPropertyEvaluator.cpp
|
||||
config/ConfigValueQueue.cpp
|
||||
config/ConfigurationException.cpp
|
||||
config/ConfigurationState.cpp
|
||||
config/PreprocessInputStream.cpp
|
||||
config/ConfigLog.cpp
|
||||
config/config.cpp
|
||||
config/tests/HTTPServer.cpp
|
||||
config/tests/config_ref_tests.cpp
|
||||
config/tests/config_tests.cpp
|
||||
config/text_format/text_format.cpp
|
||||
domain_model/Security.cpp
|
||||
domain_model/SecurityTests.cpp
|
||||
domain_model/sod.cpp
|
||||
domain_model/tests/domain_tests.cpp
|
||||
expression/BooleanGrammar.cpp
|
||||
expression/ExpressionEvaluator.cpp
|
||||
expression/ParserExceptions.cpp
|
||||
expression/Value.cpp
|
||||
expression/tests/expression_parser_tests.cpp
|
||||
logging/LoggerHub.cpp
|
||||
logging/Sink.cpp
|
||||
logging/logging.cpp
|
||||
logging/tests/logging_tests.cpp
|
||||
md/Diag/MDPeriodicDumper.cpp
|
||||
md/Diag/ShmDumper.cpp
|
||||
md/MBOProcessor.cpp
|
||||
md/MBOServiceServer.cpp
|
||||
md/MDClient.cpp
|
||||
md/MDConsumer.cpp
|
||||
md/MDConsumerHandle.cpp
|
||||
md/MDConsumerInterop.cpp
|
||||
md/MDProducer.cpp
|
||||
md/MDProducerHandle.cpp
|
||||
md/MarketDataError.cpp
|
||||
md/MarketDataGateway.cpp
|
||||
md/MarketDataRegistrationFactory.cpp
|
||||
md/MemorySegmentUtils.cpp
|
||||
md/PlatformLoader.cpp
|
||||
md/PriceSize.cpp
|
||||
md/Product.cpp
|
||||
md/SecurityCache.cpp
|
||||
md/SecurityDB.cpp
|
||||
md/SecurityMapper.cpp
|
||||
md/SecurityMarketState.cpp
|
||||
md/SecurityOracle.cpp
|
||||
md/SecurityStore.cpp
|
||||
md/Shm/FixedSecurity.cpp
|
||||
md/SyntheticSecurityService.cpp
|
||||
md/cme/MDP3Utils.cpp
|
||||
md/common.cpp
|
||||
md/ice/ICEUtils.cpp
|
||||
md/relay/QueryServer.cpp
|
||||
md/relay/RelayClient.cpp
|
||||
md/relay/RelayRecorder.cpp
|
||||
md/service/MarketDataServiceServer.cpp
|
||||
md/test/Co2ManagedTestHelper.cpp
|
||||
md/test/Co2TestInstrument.cpp
|
||||
md/test/mbo_tests.cpp
|
||||
md/test/md2_tests.cpp
|
||||
md/test/md_test_utils.cpp
|
||||
md/test/synthetic_book_merge_tests.cpp
|
||||
os/os.cpp
|
||||
os/tests/os_tests.cpp
|
||||
quickbus/core/LocalNode.cpp
|
||||
quickbus/core/Quickbus.cpp
|
||||
quickbus/core/SubscriptionID.cpp
|
||||
quickbus/core/TableID.cpp
|
||||
quickbus/message_model/Update.cpp
|
||||
quickbus/message_model/merge_updates.cpp
|
||||
quickbus/network/QBConnection.cpp
|
||||
quickbus/network/QBConnectionManager.cpp
|
||||
quickbus/network/endpoint_description.cpp
|
||||
quickbus/pubsub/TablePublisher.cpp
|
||||
quickbus/pubsub/TableSubscriber.cpp
|
||||
quickbus/pubsub/tests/qb_pubsub_tests.cpp
|
||||
quickbus/routing/INode.cpp
|
||||
quickbus/routing/NodeID.cpp
|
||||
quickbus/routing/Router.cpp
|
||||
quickbus/rpc/RPCClient.cpp
|
||||
quickbus/rpc/RPCServer.cpp
|
||||
quickbus/rpc/RPCSessionID.cpp
|
||||
quickbus/rpc/rpc_utils.cpp
|
||||
quickbus/rpc/tests/qb_rpc_tests.cpp
|
||||
quickbus/tests/quickbus_tests.cpp
|
||||
testing/catch_test_runner.cpp
|
||||
utils/AuthSessionManager.cpp
|
||||
utils/AuthToken.cpp
|
||||
utils/Dispatcher.cpp
|
||||
utils/FileUtils.cpp
|
||||
utils/GrowableSPSCQueue.cpp
|
||||
utils/HTTPStream.cpp
|
||||
utils/MathUtils.cpp
|
||||
utils/PBUtils.cpp
|
||||
utils/Puid.cpp
|
||||
utils/SecureLogon.cpp
|
||||
utils/SharedMemory.cpp
|
||||
utils/Uuid.cpp
|
||||
utils/datetime.cpp
|
||||
utils/download.cpp
|
||||
utils/file_utils.cpp
|
||||
utils/init_spark_lib.cpp
|
||||
utils/is_unittest_environment.cpp
|
||||
utils/sftp.cpp
|
||||
utils/stats.cpp
|
||||
utils/tests/AuthTokenTests.cpp
|
||||
utils/tests/MathUtilsTests.cpp
|
||||
utils/tests/SingleWriterConcurrentVectorTests.cpp
|
||||
utils/thread_manager.cpp
|
||||
PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "lib/config_defaults.h"
|
||||
#include "lib/config_proto_files.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#include <d2d1.h>
|
||||
#else
|
||||
@@ -566,7 +566,7 @@ void ConfigurationState::generate_all_config_proto(
|
||||
&bts_config_dp, config_message, message_desc, ++field_number);
|
||||
}
|
||||
} else {
|
||||
#ifdef _WIN32
|
||||
#ifdef WIN32
|
||||
// on linux the linker might throw away config protos that
|
||||
// are not used in sparkd. On windows we build a dll so that
|
||||
// should not happen
|
||||
|
||||
@@ -19,7 +19,7 @@ SymbolList {
|
||||
# symbol: "ES"
|
||||
# symbol: "FYT"
|
||||
# symbol: "FOB"
|
||||
symbol: "GC"
|
||||
# symbol: "GC"
|
||||
# symbol: "GE"
|
||||
# symbol: "HE"
|
||||
# symbol: "HG"
|
||||
@@ -37,7 +37,7 @@ SymbolList {
|
||||
# symbol: "NUB"
|
||||
# symbol: "RB"
|
||||
# symbol: "RBT"
|
||||
symbol: "SI"
|
||||
# symbol: "SI"
|
||||
# symbol: "SOM"
|
||||
# symbol: "SR1"
|
||||
# symbol: "SR3"
|
||||
@@ -84,11 +84,6 @@ SymbolLists
|
||||
key: "DERIBIT"
|
||||
symbol: @SymbolList.symbol
|
||||
}
|
||||
list
|
||||
{
|
||||
key: "FTX"
|
||||
symbol: @SymbolList.symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,10 +141,5 @@ Symbols {
|
||||
option: @SymbolLists.list[DERIBIT].symbol
|
||||
spread: @SymbolLists.list[DERIBIT].symbol
|
||||
}
|
||||
ftx {
|
||||
future: @SymbolLists.list[FTX].symbol
|
||||
option: @SymbolLists.list[FTX].symbol
|
||||
spread: @SymbolLists.list[FTX].symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ message JetFIX {
|
||||
optional uint32 window_duration_msecs = 345
|
||||
[ default = 1000 ]; // leave it alone
|
||||
|
||||
optional uint32 max_connection_attempts = 346 [ default = 3 ];
|
||||
optional uint32 max_connection_attempts = 346 [ default = 10 ];
|
||||
optional bool auto_fix_seq_num = 347 [ default = false ];
|
||||
optional bool use_ilink3 = 348 [ default = false ];
|
||||
}
|
||||
|
||||
@@ -23,5 +23,4 @@ message Symbols {
|
||||
optional SecurityExchangeList ice = 30;
|
||||
optional SecurityExchangeList simice = 40;
|
||||
optional SecurityExchangeList deribit = 50;
|
||||
optional SecurityExchangeList ftx = 60;
|
||||
}
|
||||
@@ -33,32 +33,17 @@ std::string descriptor(api::Security const &sec) {
|
||||
return "No descriptor for non glbx / ice exchange";
|
||||
}
|
||||
|
||||
api::SecurityType security_type(api::Security const &security) {
|
||||
switch (security.Contract_case()) {
|
||||
case api::Security::ContractCase::kFuture:
|
||||
api::SecurityType security_type(api::Security const &sec) {
|
||||
if (sec.has_future())
|
||||
return api::SecurityType::SECURITYTYPE_FUTURE;
|
||||
case api::Security::ContractCase::kOption:
|
||||
else if (sec.has_option())
|
||||
return api::SecurityType::SECURITYTYPE_OPTION;
|
||||
case api::Security::ContractCase::kSpot:
|
||||
return api::SecurityType::SECURITYTYPE_STOCK;
|
||||
case api::Security::ContractCase::kSpread:
|
||||
else if (sec.has_spread())
|
||||
return api::SecurityType::SECURITYTYPE_SPREAD;
|
||||
case api::Security::ContractCase::kSynthetic:
|
||||
else if (sec.has_synthetic())
|
||||
return api::SecurityType::SECURITYTYPE_SYNTHETIC;
|
||||
case api::Security::ContractCase::CONTRACT_NOT_SET:
|
||||
else
|
||||
return api::SecurityType::SECURITYTYPE_UNSET;
|
||||
}
|
||||
return api::SecurityType::SECURITYTYPE_UNSET;
|
||||
// if (sec.has_future())
|
||||
// return api::SecurityType::SECURITYTYPE_FUTURE;
|
||||
// else if (sec.has_option())
|
||||
// return api::SecurityType::SECURITYTYPE_OPTION;
|
||||
// else if (sec.has_spread())
|
||||
// return api::SecurityType::SECURITYTYPE_SPREAD;
|
||||
// else if (sec.has_synthetic())
|
||||
// return api::SecurityType::SECURITYTYPE_SYNTHETIC;
|
||||
// else
|
||||
// return api::SecurityType::SECURITYTYPE_UNSET;
|
||||
}
|
||||
|
||||
boost::gregorian::date smallest_leg(
|
||||
|
||||
@@ -14,7 +14,6 @@ enum Venue {
|
||||
VENUE_ICE = 306;
|
||||
VENUE_SIMICE = 3;
|
||||
VENUE_DERIBIT = 400;
|
||||
VENUE_FTX = 410;
|
||||
}
|
||||
|
||||
enum SecurityType {
|
||||
@@ -103,10 +102,6 @@ message DeribitExchangeData {
|
||||
int64 exchange_id = 10;
|
||||
string security_desc = 20;
|
||||
}
|
||||
message FTXExchangeData {
|
||||
int64 exchange_id = 10;
|
||||
string security_desc = 20;
|
||||
}
|
||||
message CBOECFEExchangeData {
|
||||
int64 exchange_id = 10;
|
||||
string security_desc = 20;
|
||||
@@ -142,9 +137,6 @@ message OptionContract {
|
||||
PutOrCall call_put = 5;
|
||||
}
|
||||
|
||||
message SpotContract{
|
||||
}
|
||||
|
||||
message ContractLeg {
|
||||
Security security = 10;
|
||||
double quantity = 20;
|
||||
@@ -197,7 +189,6 @@ message Security {
|
||||
oneof Contract {
|
||||
FutureContract future = 100;
|
||||
OptionContract option = 101;
|
||||
SpotContract spot = 102;
|
||||
SpreadContract spread = 110;
|
||||
SyntheticContract synthetic = 120;
|
||||
}
|
||||
@@ -207,7 +198,6 @@ message Security {
|
||||
CBOECFEExchangeData cfe = 220;
|
||||
ICEExchangeData ice = 230;
|
||||
DeribitExchangeData deribit = 240;
|
||||
FTXExchangeData ftx = 250;
|
||||
}
|
||||
}
|
||||
message SecurityList {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
#include <bits/stdint-uintn.h>
|
||||
#endif
|
||||
#include <cstdint>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
#include "OutFIX.h"
|
||||
|
||||
namespace bts {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
#include "AsyncReader.h"
|
||||
|
||||
#include "IConnection.h"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
#include "IConnection.h"
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
#include "JetFIXGateway.h"
|
||||
|
||||
namespace bts {
|
||||
|
||||
@@ -34,7 +34,7 @@ struct LogRec {
|
||||
};
|
||||
GCC_DIAG_RESTORE()
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
// static_assert(sizeof(LogRec) == 256, "LogRec should be 128 bytes");
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <fmt/ostream.h>
|
||||
#include <iostream>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace bts {
|
||||
namespace log {
|
||||
@@ -13,12 +12,7 @@ template <class Tuple, std::size_t... Is>
|
||||
std::string format_tuple(
|
||||
const char *msg_template, Tuple const &t, std::index_sequence<Is...>) {
|
||||
try {
|
||||
using ctx = fmt::format_context;
|
||||
std::vector<fmt::basic_format_arg<ctx>> fmt_args;
|
||||
(fmt_args.push_back(fmt::detail::make_arg<ctx>(std::get<Is>(t))), ...);
|
||||
return fmt::vformat(
|
||||
msg_template,
|
||||
fmt::basic_format_args<ctx>(fmt_args.data(), fmt_args.size()));
|
||||
return fmt::format(msg_template, std::get<Is>(t)...);
|
||||
} catch (fmt::format_error const &e) {
|
||||
return fmt::format(
|
||||
"Bad log message template: '{}' Error: '{}'", msg_template, e.what());
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
#include <syslog.h>
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace log {
|
||||
|
||||
struct InitSysLog {
|
||||
InitSysLog() {
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
openlog("spark", 0, LOG_USER);
|
||||
#endif
|
||||
}
|
||||
@@ -72,7 +72,7 @@ Sink console_sink(LoggingConfig const &) {
|
||||
}
|
||||
|
||||
Sink syslog_sink(LoggingConfig const &cfg) {
|
||||
#ifdef _WIN32
|
||||
#ifdef WIN32
|
||||
return null_sink();
|
||||
#else
|
||||
auto f = formatter(cfg);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#include "lib/utils/bts_chrono.h"
|
||||
#include "lib/logging/logging.h"
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
|
||||
namespace bts {
|
||||
int logging_tests;
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#pragma once
|
||||
#ifdef SPARK_ENABLE_CCAPI
|
||||
#include "lib/api/domain/Venue.pb.h"
|
||||
#include "lib/md/MarketDataListenerID.h"
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <fmt/format.h>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
class CCApiCorrelationID {
|
||||
public:
|
||||
static std::string fmt_market_depth(
|
||||
api::domain::Venue venue,
|
||||
std::string desc,
|
||||
MarketDataListenerID listener_id);
|
||||
|
||||
static std::optional<
|
||||
std::tuple<api::domain::Venue, std::string, MarketDataListenerID>>
|
||||
parse_market_depth(const std::string &corr_id_str);
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Definition
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
inline std::string CCApiCorrelationID::fmt_market_depth(
|
||||
api::domain::Venue venue,
|
||||
std::string desc,
|
||||
MarketDataListenerID listener_id) {
|
||||
return fmt::format(
|
||||
"{}.{}.{}", api::domain::Venue_Name(venue), desc, listener_id);
|
||||
}
|
||||
|
||||
inline std::optional<
|
||||
std::tuple<api::domain::Venue, std::string, MarketDataListenerID>>
|
||||
CCApiCorrelationID::parse_market_depth(const std::string &corr_id_str) {
|
||||
std::vector<std::string> parts;
|
||||
boost::algorithm::split(parts, corr_id_str, [](auto c) { return c == '.'; });
|
||||
if (parts.size() != 3) {
|
||||
return std::nullopt;
|
||||
}
|
||||
api::domain::Venue venue;
|
||||
if (!api::domain::Venue_Parse(parts.at(0), &venue)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
auto sec_desc = parts.at(1);
|
||||
auto listener_id = MarketDataListenerID{
|
||||
static_cast<std::uint32_t>(std::stoul(parts.at(2)))};
|
||||
return std::make_tuple(venue, sec_desc, listener_id);
|
||||
}
|
||||
|
||||
} // namespace bts::md
|
||||
#endif
|
||||
+206
-147
@@ -1,184 +1,243 @@
|
||||
#ifdef SPARK_ENABLE_CCAPI
|
||||
#include "CCApiListenerAdaptor.h"
|
||||
#include "lib/api/md/MarketDataConfig.pb.h"
|
||||
#include "lib/domain/BUY_SELL.h"
|
||||
#include "lib/domain/SecurityID.h"
|
||||
#include "lib/logging/logging.h"
|
||||
#include "lib/md/CCApiCorrelationID.h"
|
||||
#include "lib/md/CCApiDepthWalker.h"
|
||||
#include "lib/md/CCApiSecurityParser.h"
|
||||
#include "lib/md/IMarketDataListener.h"
|
||||
#include "lib/md/MarketDataListenerData.h"
|
||||
#include "lib/persistence/IDGenerator.h"
|
||||
#include "lib/utils/ContainsKey.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
using namespace bts::domain;
|
||||
using std::string;
|
||||
using std::unique_ptr;
|
||||
using std::unordered_map;
|
||||
using std::vector;
|
||||
static bool parse_depth_msg(domain::Book &book, const ccapi::Message &msg) {
|
||||
if (msg.getType() != ccapi::Message::Type::MARKET_DATA_EVENTS_MARKET_DEPTH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The market data arrives in the following order:
|
||||
// * bid levels (by price descending)
|
||||
// * ask levels (by price ascending)
|
||||
CCApiDepthWalker bid_walker{
|
||||
"BID_PRICE", "BID_SIZE", &book[bts::domain::Side::Buy]};
|
||||
CCApiDepthWalker ask_walker{
|
||||
"ASK_PRICE", "ASK_SIZE", &book[bts::domain::Side::Sell]};
|
||||
const auto &levels = msg.getElementList();
|
||||
for (const auto &level : levels) {
|
||||
// Each level has 2 entries, either:
|
||||
// ["BID_PRICE", "BID_SIZE"], or
|
||||
// ["ASK_PRICE", "ASK_SIZE"]
|
||||
const auto &props = level.getNameValueMap();
|
||||
for (const auto &[name, value] : props) {
|
||||
bid_walker.parse_field(name, value) ||
|
||||
ask_walker.parse_field(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
// validate the book
|
||||
bts_assert(bid_walker.price_idx == bid_walker.qty_idx);
|
||||
bts_assert(ask_walker.price_idx == ask_walker.qty_idx);
|
||||
bts_assert(book.is_sorted());
|
||||
bts_assert(book[BUY].count_populated() == bid_walker.price_idx);
|
||||
bts_assert(book[SELL].count_populated() == ask_walker.price_idx);
|
||||
return true;
|
||||
}
|
||||
|
||||
static domain::Book parse_depth_msg(const ccapi::Message &msg) {
|
||||
domain::Book book;
|
||||
parse_depth_msg(book, msg);
|
||||
return book;
|
||||
}
|
||||
|
||||
static void parse_securities_msg(
|
||||
const ccapi::Message &msg,
|
||||
std::unordered_map<std::string, std::unique_ptr<domain::Security>>
|
||||
&securities,
|
||||
std::vector<const domain::Security *> &added_secs,
|
||||
std::vector<std::pair<const domain::Security *, const domain::Security *>>
|
||||
&changed_secs,
|
||||
std::vector<const domain::Security *> &all_secs) {
|
||||
// std::vector<domain::Security
|
||||
auto new_secs = CCApiSecurityParser::parse(msg.getElementList());
|
||||
for (const auto &sec : new_secs) {
|
||||
const auto &sym = sec.security_common.symbol;
|
||||
bts_assert(!sym.empty());
|
||||
auto it = securities.find(sym);
|
||||
if (it == securities.end()) {
|
||||
auto sec_ptr = std::make_unique<domain::Security>(sec);
|
||||
added_secs.push_back(sec_ptr.get());
|
||||
all_secs.push_back(sec_ptr.get());
|
||||
securities[sym] = std::move(sec_ptr);
|
||||
bts_assert(added_secs.back() != nullptr);
|
||||
bts_assert(added_secs.back()->security_common.symbol == sym);
|
||||
continue;
|
||||
}
|
||||
changed_secs.push_back({it->second.get(), &sec});
|
||||
}
|
||||
// auto added_msg = fmt::join(added_secs)
|
||||
std::vector<std::string> added_sec_syms;
|
||||
for (const auto *s : added_secs) {
|
||||
added_sec_syms.push_back(s->security_common.symbol);
|
||||
}
|
||||
std::vector<std::string> changed_sec_syms;
|
||||
for (const auto &[old_s, new_s] : changed_secs) {
|
||||
added_sec_syms.push_back(fmt::format(
|
||||
"{} -> {}", old_s->security_common.symbol,
|
||||
new_s->security_common.symbol));
|
||||
}
|
||||
LOG(md, Info, "CCApi securities update. added: {}; changed: {}",
|
||||
fmt::to_string(fmt::join(added_sec_syms, ", ")),
|
||||
fmt::to_string(fmt::join(changed_sec_syms, ", ")));
|
||||
}
|
||||
|
||||
struct CCApiListenerAdaptor::PImpl {
|
||||
PImpl(
|
||||
IMarketDataListener *const listener,
|
||||
persistence::IDGenerator *const sec_id_store)
|
||||
: listener(listener), sec_id_store(sec_id_store) {}
|
||||
std::unordered_map<std::string, std::unique_ptr<domain::Security>>
|
||||
securities;
|
||||
std::unordered_map<std::uint32_t, IMarketDataListener *const> listeners;
|
||||
MarketDataListenerID sec_id_counter{900'000};
|
||||
|
||||
IMarketDataListener *const listener;
|
||||
|
||||
persistence::IDGenerator *const sec_id_store;
|
||||
unordered_map<SecurityID, unique_ptr<Security>> securities;
|
||||
|
||||
void on_instruments(const ccapi::Message &msg, api::domain::Venue venue) {
|
||||
vector<const Security *> all_secs;
|
||||
auto new_secs = CCApiSecurityParser::parse(msg.getElementList());
|
||||
for (const auto &sec : new_secs) {
|
||||
const auto &desc = sec.security_common.desc;
|
||||
bts_assert(!desc.empty());
|
||||
auto sec_id = SecurityID{
|
||||
sec_id_store->get_or_add(api::domain::Venue_Name(venue), desc)};
|
||||
if (CONTAINS_KEY(securities, sec_id)) {
|
||||
// don't replace existing secs (in case code downstream relies on
|
||||
// ptr equality)
|
||||
continue;
|
||||
}
|
||||
auto sec_ptr = std::make_unique<Security>(sec);
|
||||
sec_ptr->security_common.id.value() = sec_id_store->get_or_add(
|
||||
api::domain::Venue_Name(venue), sec_ptr->security_common.desc);
|
||||
all_secs.push_back(sec_ptr.get());
|
||||
securities[sec_id] = std::move(sec_ptr);
|
||||
}
|
||||
listener->on_securities(all_secs);
|
||||
void on_instruments(
|
||||
const ccapi::Message &msg, IMarketDataListener &listener) {
|
||||
std::vector<const domain::Security *> added_secs;
|
||||
std::vector<std::pair<const domain::Security *, const domain::Security *>>
|
||||
changed_secs;
|
||||
std::vector<const domain::Security *> all_secs;
|
||||
parse_securities_msg(msg, securities, added_secs, changed_secs, all_secs);
|
||||
listener.on_securities(all_secs);
|
||||
}
|
||||
|
||||
void on_instruments(const ccapi::Message &msg, const string &corr_id) {
|
||||
// Correlation ID is the Venue
|
||||
api::domain::Venue venue;
|
||||
if (!api::domain::Venue_Parse(corr_id, &venue)) {
|
||||
LOG(md, Error, "Failed to parse venue from ccapi correlation id '{}'",
|
||||
corr_id);
|
||||
return;
|
||||
}
|
||||
on_instruments(msg, venue);
|
||||
}
|
||||
|
||||
void on_book(const ccapi::Message &msg, SecurityID sec_id) {
|
||||
if (msg.getType() !=
|
||||
ccapi::Message::Type::MARKET_DATA_EVENTS_MARKET_DEPTH) {
|
||||
return;
|
||||
}
|
||||
|
||||
Book book;
|
||||
book.set_security_id(sec_id);
|
||||
// The market data arrives in the following order:
|
||||
// * bid levels (by price descending)
|
||||
// * ask levels (by price ascending)
|
||||
CCApiDepthWalker bid_walker{"BID_PRICE", "BID_SIZE", &book[BUY]};
|
||||
CCApiDepthWalker ask_walker{"ASK_PRICE", "ASK_SIZE", &book[SELL]};
|
||||
const auto &levels = msg.getElementList();
|
||||
for (const auto &level : levels) {
|
||||
// Each level has 2 entries, either:
|
||||
// ["BID_PRICE", "BID_SIZE"], or
|
||||
// ["ASK_PRICE", "ASK_SIZE"]
|
||||
const auto &props = level.getNameValueMap();
|
||||
for (const auto &[name, value] : props) {
|
||||
bid_walker.parse_field(name, value) ||
|
||||
ask_walker.parse_field(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
// validate the book
|
||||
bts_assert(bid_walker.price_idx == bid_walker.qty_idx);
|
||||
bts_assert(ask_walker.price_idx == ask_walker.qty_idx);
|
||||
bts_assert(book.is_sorted());
|
||||
bts_assert(book[BUY].count_populated() == bid_walker.price_idx);
|
||||
bts_assert(book[SELL].count_populated() == ask_walker.price_idx);
|
||||
listener->on_book(book);
|
||||
}
|
||||
|
||||
void on_book(const ccapi::Message &msg, const string &corr_id) {
|
||||
// Correlation ID is a formatted string:
|
||||
// "<venue>.<sec_desc>.<listener_id>"
|
||||
const auto corr_id_res = CCApiCorrelationID::parse_market_depth(corr_id);
|
||||
bts_assert(corr_id_res.has_value());
|
||||
const auto [venue, sec_desc, listener_id] = *corr_id_res;
|
||||
LOG(md, Diag, "listener_id: {}", listener_id);
|
||||
const auto sec_id =
|
||||
sec_id_store->get_or_add(api::domain::Venue_Name(venue), sec_desc);
|
||||
on_book(msg, SecurityID{sec_id});
|
||||
}
|
||||
|
||||
SecurityID get_sec_id(
|
||||
const api::domain::Venue venue, const string &sec_desc) {
|
||||
const auto sec_id =
|
||||
sec_id_store->get_or_add(api::domain::Venue_Name(venue), sec_desc);
|
||||
return SecurityID{sec_id};
|
||||
void on_book(const ccapi::Message &msg, IMarketDataListener &listener) {
|
||||
auto book = parse_depth_msg(msg);
|
||||
listener.on_book(book);
|
||||
}
|
||||
};
|
||||
|
||||
CCApiListenerAdaptor::CCApiListenerAdaptor(
|
||||
IMarketDataListener *const listener,
|
||||
persistence::IDGenerator *const sec_id_store)
|
||||
: me_(std::make_unique<PImpl>(listener, sec_id_store)) {}
|
||||
CCApiListenerAdaptor::CCApiListenerAdaptor() : me_(std::make_unique<PImpl>()) {}
|
||||
|
||||
CCApiListenerAdaptor::~CCApiListenerAdaptor() = default;
|
||||
|
||||
bool CCApiListenerAdaptor::empty() const { return me_->listeners.empty(); }
|
||||
|
||||
void CCApiListenerAdaptor::register_listener(
|
||||
IMarketDataListener *const listener, MarketDataListenerID id) {
|
||||
bts_assert_msgf(
|
||||
me_->listeners.find(id.value()) == me_->listeners.end(),
|
||||
"MarketDataListener w/ id '{}' already registered", id);
|
||||
me_->listeners.insert({id.value(), listener});
|
||||
}
|
||||
|
||||
void CCApiListenerAdaptor::unregister_listener(MarketDataListenerID id) {
|
||||
me_->listeners.erase(id.value());
|
||||
}
|
||||
|
||||
static const char *Message_Type_Name(ccapi::Message::Type t) {
|
||||
switch (t) {
|
||||
case ccapi::Message::Type::UNKNOWN:
|
||||
return "UNKNOWN";
|
||||
case ccapi::Message::Type::AUTHORIZATION_SUCCESS:
|
||||
return "AUTHORIZATION_SUCCESS";
|
||||
case ccapi::Message::Type::AUTHORIZATION_FAILURE:
|
||||
return "AUTHORIZATION_FAILURE";
|
||||
case ccapi::Message::Type::MARKET_DATA_EVENTS_MARKET_DEPTH:
|
||||
return "MARKET_DATA_EVENTS_MARKET_DEPTH";
|
||||
case ccapi::Message::Type::MARKET_DATA_EVENTS_TRADE:
|
||||
return "MARKET_DATA_EVENTS_TRADE";
|
||||
case ccapi::Message::Type::MARKET_DATA_EVENTS_AGG_TRADE:
|
||||
return "MARKET_DATA_EVENTS_AGG_TRADE";
|
||||
case ccapi::Message::Type::EXECUTION_MANAGEMENT_EVENTS_ORDER_UPDATE:
|
||||
return "EXECUTION_MANAGEMENT_EVENTS_ORDER_UPDATE";
|
||||
case ccapi::Message::Type::EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE:
|
||||
return "EXECUTION_MANAGEMENT_EVENTS_PRIVATE_TRADE";
|
||||
case ccapi::Message::Type::SUBSCRIPTION_STARTED:
|
||||
return "SUBSCRIPTION_STARTED";
|
||||
case ccapi::Message::Type::SUBSCRIPTION_FAILURE:
|
||||
return "SUBSCRIPTION_FAILURE";
|
||||
case ccapi::Message::Type::SESSION_CONNECTION_UP:
|
||||
return "SESSION_CONNECTION_UP";
|
||||
case ccapi::Message::Type::SESSION_CONNECTION_DOWN:
|
||||
return "SESSION_CONNECTION_DOWN";
|
||||
case ccapi::Message::Type::INCORRECT_STATE_FOUND:
|
||||
return "INCORRECT_STATE_FOUND";
|
||||
case ccapi::Message::Type::CREATE_ORDER:
|
||||
return "CREATE_ORDER";
|
||||
case ccapi::Message::Type::CANCEL_ORDER:
|
||||
return "CANCEL_ORDER";
|
||||
case ccapi::Message::Type::GET_ORDER:
|
||||
return "GET_ORDER";
|
||||
case ccapi::Message::Type::GET_OPEN_ORDERS:
|
||||
return "GET_OPEN_ORDERS";
|
||||
case ccapi::Message::Type::CANCEL_OPEN_ORDERS:
|
||||
return "CANCEL_OPEN_ORDERS";
|
||||
case ccapi::Message::Type::GET_ACCOUNTS:
|
||||
return "GET_ACCOUNTS";
|
||||
case ccapi::Message::Type::GET_ACCOUNT_BALANCES:
|
||||
return "GET_ACCOUNT_BALANCES";
|
||||
case ccapi::Message::Type::GET_ACCOUNT_POSITIONS:
|
||||
return "GET_ACCOUNT_POSITIONS";
|
||||
case ccapi::Message::Type::GET_RECENT_TRADES:
|
||||
return "GET_RECENT_TRADES";
|
||||
case ccapi::Message::Type::GET_RECENT_AGG_TRADES:
|
||||
return "GET_RECENT_AGG_TRADES";
|
||||
case ccapi::Message::Type::GET_INSTRUMENT:
|
||||
return "GET_INSTRUMENT";
|
||||
case ccapi::Message::Type::GET_INSTRUMENTS:
|
||||
return "GET_INSTRUMENTS";
|
||||
case ccapi::Message::Type::RESPONSE_ERROR:
|
||||
return "RESPONSE_ERROR";
|
||||
case ccapi::Message::Type::REQUEST_FAILURE:
|
||||
return "REQUEST_FAILURE";
|
||||
case ccapi::Message::Type::GENERIC_ERROR:
|
||||
return "GENERIC_ERROR";
|
||||
case ccapi::Message::Type::CUSTOM:
|
||||
return "CUSTOM";
|
||||
case ccapi::Message::Type::FIX:
|
||||
return "FIX";
|
||||
case ccapi::Message::Type::FIX_FAILURE:
|
||||
return "FIX_FAILURE";
|
||||
case ccapi::Message::Type::GENERIC_PUBLIC_REQUEST:
|
||||
return "GENERIC_PUBLIC_REQUEST";
|
||||
case ccapi::Message::Type::GENERIC_PUBLIC_SUBSCRIPTION:
|
||||
return "GENERIC_PUBLIC_SUBSCRIPTION";
|
||||
case ccapi::Message::Type::GENERIC_PRIVATE_REQUEST:
|
||||
return "GENERIC_PRIVATE_REQUEST";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
bool CCApiListenerAdaptor::processEvent(
|
||||
const ccapi::Event &event, ccapi::Session *) {
|
||||
LOG(md, Diag, "Received ccapi event: {}", event.toString());
|
||||
switch (event.getType()) {
|
||||
case ccapi::Event::Type::SESSION_STATUS:
|
||||
case ccapi::Event::Type::SUBSCRIPTION_STATUS:
|
||||
case ccapi::Event::Type::REQUEST_STATUS:
|
||||
// No processing needed
|
||||
return true;
|
||||
// one-time callback representing the reply to a ccapi 'REQUEST'
|
||||
// Note: the GET_INSTRUMENTS msg arrives in an event of this type
|
||||
case ccapi::Event::Type::RESPONSE:
|
||||
// stream of callbacks representing the reply to a ccapi 'SUBSCRIBE'
|
||||
// Note: the MARKET_DATA_EVENTS_MARKET_DEPTH msg arrives in an event of this
|
||||
// type
|
||||
case ccapi::Event::Type::SUBSCRIPTION_DATA:
|
||||
break;
|
||||
case ccapi::Event::Type::UNKNOWN:
|
||||
case ccapi::Event::Type::AUTHORIZATION_STATUS:
|
||||
case ccapi::Event::Type::FIX:
|
||||
case ccapi::Event::Type::FIX_STATUS:
|
||||
LOG(md, Error, "Unexpected ccapi event type '{}'",
|
||||
ccapi::Event::typeToString(event.getType()));
|
||||
break;
|
||||
}
|
||||
|
||||
LOG(md, Error, "Received ccapi event: {}", event.toString());
|
||||
const auto &msgs = event.getMessageList();
|
||||
for (const auto &msg : msgs) {
|
||||
const auto &corr_ids = msg.getCorrelationIdList();
|
||||
for (const auto &corr_id : corr_ids) {
|
||||
switch (msg.getType()) {
|
||||
case ccapi::Message::Type::GET_INSTRUMENTS: {
|
||||
// This message should only arrive with a RESPONSE event
|
||||
bts_assert(event.getType() == ccapi::Event::Type::RESPONSE);
|
||||
me_->on_instruments(msg, corr_id);
|
||||
break;
|
||||
MarketDataListenerID listener_id{
|
||||
static_cast<std::uint32_t>(std::stoul(corr_id))};
|
||||
auto listener_it = me_->listeners.find(listener_id.value());
|
||||
if (listener_it == me_->listeners.end()) {
|
||||
LOG(md, Warn,
|
||||
"Received event associated w/ unknown correlationId '{}'",
|
||||
corr_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto &listener = *listener_it->second;
|
||||
switch (msg.getType()) {
|
||||
case ccapi::Message::Type::GET_INSTRUMENTS:
|
||||
me_->on_instruments(msg, listener);
|
||||
break;
|
||||
case ccapi::Message::Type::MARKET_DATA_EVENTS_MARKET_DEPTH: {
|
||||
// This message should only arrive with a SUBSCRIPTION_DATA event
|
||||
bts_assert(
|
||||
event.getType() == ccapi::Event::Type::SUBSCRIPTION_DATA);
|
||||
me_->on_book(msg, corr_id);
|
||||
me_->on_book(msg, listener);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(md, Warn, "Unexpected ccapi message type '{}'",
|
||||
ccapi::Message::typeToString(msg.getType()));
|
||||
std::string msg_type_name = Message_Type_Name(msg.getType());
|
||||
LOG(md, Warn, "Unexpected CCApi event type '{}'", msg_type_name);
|
||||
break;
|
||||
}
|
||||
// switch (event.getType()) {
|
||||
// case ccapi::Event::Type::UNKNOWN:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -1,33 +1,28 @@
|
||||
#pragma once
|
||||
#ifdef SPARK_ENABLE_CCAPI
|
||||
#include "lib/api/domain/Venue.pb.h"
|
||||
|
||||
#include "lib/md/IMarketDataListener.h"
|
||||
#include "lib/md/MarketDataListenerID.h"
|
||||
#include <ccapi_cpp/ccapi_event_handler.h>
|
||||
#include <memory>
|
||||
|
||||
namespace bts::api::md {
|
||||
class MarketDataConfig;
|
||||
}
|
||||
|
||||
namespace bts::persistence {
|
||||
class IDGenerator;
|
||||
}
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
class IMarketDataListener;
|
||||
|
||||
class CCApiListenerAdaptor : public ccapi::EventHandler {
|
||||
public:
|
||||
CCApiListenerAdaptor(
|
||||
IMarketDataListener *const listener,
|
||||
persistence::IDGenerator *const sec_id_store);
|
||||
|
||||
CCApiListenerAdaptor();
|
||||
~CCApiListenerAdaptor();
|
||||
|
||||
MarketDataListenerID register_listener(IMarketDataListener *const listener);
|
||||
|
||||
void register_listener(
|
||||
IMarketDataListener *const listener, MarketDataListenerID id);
|
||||
|
||||
void unregister_listener(MarketDataListenerID id);
|
||||
|
||||
bool processEvent(
|
||||
const ccapi::Event &event, ccapi::Session *session) override;
|
||||
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me_;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifdef SPARK_ENABLE_CCAPI
|
||||
#include "CCApiRequestor.h"
|
||||
#include "lib/logging/logging.h"
|
||||
#include <optional>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
struct CCApiRequestor::PImpl {
|
||||
ccapi::Request req;
|
||||
ccapi::EventHandler *handler;
|
||||
ccapi::SessionOptions opts;
|
||||
ccapi::SessionConfigs cfgs;
|
||||
std::optional<ccapi::Session> session;
|
||||
};
|
||||
|
||||
CCApiRequestor::CCApiRequestor(
|
||||
ccapi::EventHandler *const handler,
|
||||
ccapi::SessionOptions opts,
|
||||
ccapi::SessionConfigs cfgs)
|
||||
: me_(std::make_unique<PImpl>()) {
|
||||
// Store 'opts' and 'cfgs' in PImpl for diagnostic purposes
|
||||
me_->opts = std::move(opts);
|
||||
me_->cfgs = std::move(cfgs);
|
||||
me_->handler = handler;
|
||||
}
|
||||
|
||||
CCApiRequestor::~CCApiRequestor() { me_->session->stop(); }
|
||||
|
||||
void CCApiRequestor::request(ccapi::Request &req) {
|
||||
LOG(md, Info, "Making ccapi request: {}", req.toString());
|
||||
if (!me_->session) {
|
||||
me_->session.emplace(me_->opts, me_->cfgs, me_->handler);
|
||||
}
|
||||
me_->session->sendRequest(req);
|
||||
}
|
||||
|
||||
} // namespace bts::md
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#ifdef SPARK_ENABLE_CCAPI
|
||||
#include <ccapi_cpp/ccapi_event_handler.h>
|
||||
#include <ccapi_cpp/ccapi_session.h>
|
||||
#include <ccapi_cpp/ccapi_session_options.h>
|
||||
#include <memory>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
class CCApiRequestor {
|
||||
public:
|
||||
explicit CCApiRequestor(
|
||||
ccapi::EventHandler *const handler,
|
||||
ccapi::SessionOptions opts,
|
||||
ccapi::SessionConfigs cfgs);
|
||||
|
||||
~CCApiRequestor();
|
||||
|
||||
void request(ccapi::Request &req);
|
||||
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me_;
|
||||
};
|
||||
|
||||
} // namespace bts::md::ftx
|
||||
#endif
|
||||
@@ -1,91 +0,0 @@
|
||||
#ifdef SPARK_ENABLE_CCAPI
|
||||
#include "CCApiSession.h"
|
||||
#include "lib/api/md/DepthStreamConfig.pb.h"
|
||||
#include "lib/md/CCApiCorrelationID.h"
|
||||
#include "lib/md/CCApiListenerAdaptor.h"
|
||||
#include "lib/md/MarketDataListenerData.h"
|
||||
#include "lib/md/MarketDataRegistrationFactory.h"
|
||||
#include "lib/persistence/IDGenerator.h"
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <ccapi_cpp/ccapi_event_dispatcher.h>
|
||||
#include <ccapi_cpp/ccapi_request.h>
|
||||
#include <ccapi_cpp/ccapi_session.h>
|
||||
#include <ccapi_cpp/ccapi_session_configs.h>
|
||||
#include <ccapi_cpp/ccapi_session_options.h>
|
||||
#include <ccapi_cpp/ccapi_subscription.h>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
struct CCApiSession::PImpl {
|
||||
PImpl(
|
||||
const MarketDataListenerData listener_data,
|
||||
bts::persistence::IDGenerator *const sec_id_store)
|
||||
: listener_data(listener_data), sec_id_store(sec_id_store),
|
||||
ccapi_dispatcher(
|
||||
static_cast<int>(listener_data.cfg.num_dispatcher_threads())),
|
||||
ccapi_listener(listener_data.listener, sec_id_store),
|
||||
ccapi_session(
|
||||
ccapi_opts, ccapi_cfgs, &ccapi_listener, &ccapi_dispatcher) {}
|
||||
|
||||
MarketDataListenerData listener_data;
|
||||
bts::persistence::IDGenerator *sec_id_store;
|
||||
|
||||
ccapi::SessionOptions ccapi_opts;
|
||||
ccapi::SessionConfigs ccapi_cfgs;
|
||||
|
||||
// Dispatches ccapi callbacks
|
||||
ccapi::EventDispatcher ccapi_dispatcher;
|
||||
|
||||
// Handles ccapi sec/md callbacks
|
||||
CCApiListenerAdaptor ccapi_listener;
|
||||
|
||||
// Manages ccapi connection to exchanges
|
||||
ccapi::Session ccapi_session;
|
||||
|
||||
void request_securities(api::domain::Venue venue) {
|
||||
auto venue_name = api::domain::Venue_Name(venue);
|
||||
auto venue_name_lower = boost::algorithm::to_lower_copy(venue_name);
|
||||
// The 'venue' in the request must be lower-case (ccapi expects this). The
|
||||
// correlation id, however, should remain unchanged (in the callback, we
|
||||
// parse the venue with 'api::domain::Venue_Parse')
|
||||
ccapi::Request req(
|
||||
ccapi::Request::Operation::GET_INSTRUMENTS, venue_name_lower);
|
||||
req.setCorrelationId(venue_name);
|
||||
ccapi_session.sendRequest(req);
|
||||
}
|
||||
|
||||
void subscribe_md(const api::md::DepthStreamConfig &ds) {
|
||||
const auto opts =
|
||||
fmt::format("{}={}", CCAPI_MARKET_DEPTH_MAX, ds.num_levels());
|
||||
auto venue_name = bts::api::domain::Venue_Name(ds.venue());
|
||||
boost::algorithm::to_lower(venue_name);
|
||||
for (const auto &symbol : ds.symbols()) {
|
||||
const auto corr_id = CCApiCorrelationID::fmt_market_depth(
|
||||
ds.venue(), symbol, listener_data.id);
|
||||
ccapi::Subscription sub(
|
||||
venue_name, symbol, CCAPI_MARKET_DEPTH, opts, corr_id);
|
||||
ccapi_session.subscribe(sub);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CCApiSession::CCApiSession(
|
||||
MarketDataListenerData listener_data,
|
||||
bts::persistence::IDGenerator *sec_id_store)
|
||||
: me_(std::make_unique<PImpl>(std::move(listener_data), sec_id_store)) {
|
||||
|
||||
std::unordered_set<api::domain::Venue> venues;
|
||||
for (auto ds : me_->listener_data.cfg.depth_streams()) {
|
||||
// Limit one sec request per Venue
|
||||
if (venues.insert(ds.venue()).second) {
|
||||
me_->request_securities(ds.venue());
|
||||
}
|
||||
me_->subscribe_md(ds);
|
||||
}
|
||||
}
|
||||
|
||||
CCApiSession::~CCApiSession() { me_->ccapi_session.stop(); }
|
||||
|
||||
} // namespace bts::md
|
||||
#endif
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
#ifdef SPARK_ENABLE_CCAPI
|
||||
#include "lib/api/domain/Venue.pb.h"
|
||||
#include <memory>
|
||||
|
||||
namespace ccapi {
|
||||
class Session;
|
||||
}
|
||||
|
||||
namespace bts::persistence {
|
||||
class IDGenerator;
|
||||
}
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
struct MarketDataListenerData;
|
||||
|
||||
class CCApiSession {
|
||||
public:
|
||||
explicit CCApiSession(
|
||||
MarketDataListenerData listener_data,
|
||||
bts::persistence::IDGenerator *sec_id_store);
|
||||
|
||||
CCApiSession(const CCApiSession &) = delete;
|
||||
CCApiSession(CCApiSession &&) = default;
|
||||
CCApiSession &operator=(const CCApiSession &) = delete;
|
||||
CCApiSession &operator=(CCApiSession &&) = default;
|
||||
|
||||
~CCApiSession();
|
||||
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me_;
|
||||
};
|
||||
|
||||
} // namespace bts::md
|
||||
#endif
|
||||
@@ -60,7 +60,7 @@ std::string print_book(
|
||||
auto a = ask[x - 1];
|
||||
if (!os::is_nan(a.price())) {
|
||||
snprintf(
|
||||
buffer, 512, "%5s %14s | %14.7f %5.5f\n", "", "", a.price(),
|
||||
buffer, 512, "%5s %14s | %14.7f %5d\n", "", "", a.price(),
|
||||
a.size());
|
||||
ss << buffer;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ std::string print_book(
|
||||
for (uint32_t x = 0; x < COCONUT_MAX_DEPTH; ++x) {
|
||||
auto b = bid[x];
|
||||
if (!os::is_nan(b.price())) {
|
||||
snprintf(buffer, 512, "%5.5f %14.7f | \n", b.size(), b.price());
|
||||
snprintf(buffer, 512, "%5d %14.7f | \n", b.size(), b.price());
|
||||
ss << buffer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@
|
||||
#include "MDProducerHandle.h"
|
||||
#include "lib/domain_model/Security.h"
|
||||
#include "lib/domain_model/SecurityKey.h"
|
||||
#include "lib/utils/OSTREAM_FMT_IMPL.h"
|
||||
#include "lib/utils/TimeStamp.h"
|
||||
|
||||
#include <btree/map.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -171,5 +169,3 @@ class MBOProcessor {
|
||||
namespace std {
|
||||
std::ostream &operator<<(std::ostream &os, const bts::md::inc::Update &);
|
||||
}
|
||||
|
||||
OSTREAM_FMT_IMPL(bts::md::inc::Update);
|
||||
@@ -613,8 +613,7 @@ class MDConsumerImpl {
|
||||
|
||||
for (auto &s : symbols) {
|
||||
if (s.type() == SECURITYTYPE_FUTURE ||
|
||||
s.type() == SECURITYTYPE_OPTION ||
|
||||
s.type() == api::SECURITYTYPE_STOCK) {
|
||||
s.type() == SECURITYTYPE_OPTION) {
|
||||
_instances.push_back(make_shared<MDConsumerInst>(
|
||||
s.symbol(), s.type(), s.exchange(), shared, platform));
|
||||
}
|
||||
@@ -784,7 +783,7 @@ class MDConsumerImpl {
|
||||
// recurse to find details
|
||||
map<security_key, SecurityPtr> leg_map;
|
||||
for (auto &leg : fill_leg_details(legs, depth + 1)) {
|
||||
leg_map.insert(make_pair(leg->id(), std::move(leg)));
|
||||
leg_map.insert(make_pair(leg->id(), move(leg)));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -218,7 +218,6 @@ class BTS_EXPORT MDConsumerHandle {
|
||||
switch (_type) {
|
||||
case HANDLETYPE_VOID:
|
||||
bts_assert_msg(false, "Handle not initialized");
|
||||
break;
|
||||
case HANDLETYPE_DEPTH:
|
||||
return convert_security(book.cdata->security);
|
||||
case HANDLETYPE_BBO:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if defined(EXPORT_MD_CONSUMER)
|
||||
#ifdef _WIN32
|
||||
#include "MDConsumer.h"
|
||||
#include "SecurityCache.h"
|
||||
#include "UserSymbol.h"
|
||||
|
||||
@@ -134,7 +134,7 @@ MDProducer::MDProducer(Platform platform, MDProducerFlags flags)
|
||||
: _mutex(new std::mutex()), _producers(), _id_recorder(),
|
||||
_platform(platform), _flags(flags),
|
||||
_smapper(flags & MDProducerFlags::SecurityMapper) {}
|
||||
#ifndef _WIN32
|
||||
#ifndef WIN32
|
||||
MDProducer::MDProducer(
|
||||
Platform platform, SecurityIDRecorder recorder, MDProducerFlags flags)
|
||||
: _mutex(new std::mutex()), _producers(),
|
||||
@@ -173,7 +173,7 @@ MDProducerImpl &MDProducer::get_producer(
|
||||
} else {
|
||||
newp.reset(new MDProducerImpl(symbol, type, exchange, _platform, _flags));
|
||||
}
|
||||
_producers.push_back(std::move(newp));
|
||||
_producers.push_back(move(newp));
|
||||
return *_producers.back();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +1,145 @@
|
||||
#ifdef SPARK_ENABLE_CCAPI
|
||||
#include "lib/md/CCApiListenerAdaptor.h"
|
||||
#include <ccapi_cpp/ccapi_macro.h>
|
||||
#include "MarketDataGateway.h"
|
||||
#include "lib/api/domain/Venue.pb.h"
|
||||
#include "lib/api/md/DepthStreamConfig.pb.h"
|
||||
#include "lib/api/md/MarketDataConfig.pb.h"
|
||||
#include "MarketDataRegistration.h"
|
||||
#include "lib/api/md/MarketDataSubscriptionParams.pb.h"
|
||||
#include "lib/api/md/binance/BinanceMarketDataSubscriptionParams.pb.h"
|
||||
#include "lib/core/ProtoPrinter.h"
|
||||
#include "lib/domain/Venue.h"
|
||||
#include "lib/logging/logging.h"
|
||||
#include "lib/md/CCApiSession.h"
|
||||
#include "lib/md/CompositeMarketDataListener.h"
|
||||
#include "lib/md/IMarketDataListener.h"
|
||||
#include "lib/md/MarketDataListenerData.h"
|
||||
#include "lib/md/MarketDataListenerID.h"
|
||||
#include "lib/md/MarketDataRegistration.h"
|
||||
#include "lib/md/MarketDataRegistrationError.h"
|
||||
#include "lib/md/MarketDataRegistrationFactory.h"
|
||||
#include "lib/persistence/IDGenerator.h"
|
||||
#include "lib/md/binance/BinanceDepthStreamSiteKey.h"
|
||||
#include "lib/md/binance/BinanceDiffDepthSubscription.h"
|
||||
#include "lib/md/binance/BinanceDiffDepthUpdate.h"
|
||||
#include "lib/utils/ContainsKey.h"
|
||||
#include "lib/utils/bts_assert.h"
|
||||
|
||||
#include <ccapi_cpp/ccapi_session.h>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
static void _validate(
|
||||
const api::md::DepthStreamConfig &ds,
|
||||
std::uint32_t index,
|
||||
vector<string> &errors) {
|
||||
if (!api::domain::Venue_IsValid(ds.venue())) {
|
||||
errors.push_back(fmt::format(
|
||||
"DepthStreamConfig at index {} 'venue' is invalid", index));
|
||||
}
|
||||
if (ds.num_levels() == 0) {
|
||||
errors.push_back(fmt::format(
|
||||
"DepthStreamConfig at index {} 'num_levels' is 0", index));
|
||||
}
|
||||
if (ds.symbols().empty()) {
|
||||
errors.push_back(fmt::format(
|
||||
"DepthStreamConfig at index {} 'symbols' is empty", index));
|
||||
}
|
||||
}
|
||||
|
||||
static void _validate(
|
||||
const api::md::MarketDataConfig &cfg, vector<string> errs) {
|
||||
if (cfg.depth_streams().empty()) {
|
||||
errs.push_back("MarketDataConfig 'depth_streams' is empty");
|
||||
}
|
||||
std::uint32_t ds_idx = 0;
|
||||
for (const auto &ds : cfg.depth_streams()) {
|
||||
_validate(ds, ds_idx++, errs);
|
||||
}
|
||||
}
|
||||
|
||||
struct MarketDataGateway::PImpl {
|
||||
MarketDataRegistrationFactory registration_factory;
|
||||
bts::persistence::IDGenerator &sec_id_store =
|
||||
bts::persistence::IDGenerator::insance();
|
||||
std::unordered_map<MarketDataListenerID, CCApiSession> sessions;
|
||||
std::unordered_map<
|
||||
binance::BinanceDepthStreamSiteKey,
|
||||
binance::BinanceDiffDepthSubscription>
|
||||
binance_subs;
|
||||
std::unordered_map<MarketDataListenerID, MarketDataListenerData>
|
||||
registered_listeners;
|
||||
|
||||
private:
|
||||
ccapi::SessionOptions ccapi_opts_;
|
||||
ccapi::SessionConfigs ccapi_cfgs_;
|
||||
std::optional<ccapi::EventDispatcher> ccapi_dispatcher_;
|
||||
std::optional<ccapi::Session> ccapi_session_;
|
||||
std::optional<CCApiListenerAdaptor> ccapi_listener_;
|
||||
|
||||
public:
|
||||
CCApiListenerAdaptor &ccapi_listener() {
|
||||
if (!ccapi_listener_) {
|
||||
return ccapi_listener_.emplace();
|
||||
}
|
||||
return *ccapi_listener_;
|
||||
}
|
||||
|
||||
ccapi::Session &ccapi_session() {
|
||||
if (!ccapi_session_) {
|
||||
if (!ccapi_dispatcher_) {
|
||||
ccapi_dispatcher_.emplace(2);
|
||||
}
|
||||
ccapi_session_.emplace(
|
||||
ccapi_opts_, ccapi_cfgs_, &ccapi_listener(), &*ccapi_dispatcher_);
|
||||
}
|
||||
return *ccapi_session_;
|
||||
}
|
||||
//////////////////////////////////////////////////
|
||||
// Binance
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void subscribe_binance(
|
||||
const api::md::binance::BinanceMarketDataSubscriptionParams &sub,
|
||||
IMarketDataListener *listener) {
|
||||
std::vector<binance::BinanceDiffDepthSubscription *> new_subs;
|
||||
for (const auto &depth_stream : sub.depth_streams()) {
|
||||
md::binance::BinanceDepthStreamSiteKey site_key(depth_stream);
|
||||
auto [sub_it, is_new_sub] = binance_subs.try_emplace(
|
||||
site_key, md::binance::BinanceDepthStreamParams{depth_stream});
|
||||
if (is_new_sub) {
|
||||
new_subs.push_back(&sub_it->second);
|
||||
continue;
|
||||
}
|
||||
auto &sub = sub_it->second;
|
||||
// add symbols to piggy back on existing subscription rather than
|
||||
// create a new one
|
||||
for (const auto &symbol : depth_stream.symbols()) {
|
||||
sub.add_listener(symbol, listener);
|
||||
}
|
||||
}
|
||||
for (auto *sub : new_subs) {
|
||||
sub->connect();
|
||||
}
|
||||
}
|
||||
|
||||
void unsubscribe_binance(
|
||||
const api::md::binance::BinanceMarketDataSubscriptionParams &sub,
|
||||
IMarketDataListener *listener) {
|
||||
for (const auto &depth_stream : sub.depth_streams()) {
|
||||
md::binance::BinanceDepthStreamSiteKey site_key(depth_stream);
|
||||
auto sub_it = binance_subs.find(site_key);
|
||||
bts_assert(sub_it != binance_subs.end());
|
||||
auto &sub = sub_it->second;
|
||||
for (const auto &symbol : depth_stream.symbols()) {
|
||||
bts_assert(sub.remove_listener(symbol, listener));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// FTX
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void subscribe_ftx(
|
||||
const api::md::ftx::FTXMarketDataSubscriptionParams ¶ms,
|
||||
IMarketDataListener *listener,
|
||||
MarketDataListenerID listener_id) {
|
||||
if (params.depth_streams().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bts_assert(params.depth_streams().size() == 1);
|
||||
auto &depth_stream = params.depth_streams().at(0);
|
||||
std::vector<std::string> symbols;
|
||||
|
||||
for (const auto &symbol : depth_stream.symbols()) {
|
||||
symbols.push_back(symbol);
|
||||
}
|
||||
|
||||
ccapi_listener().register_listener(listener, listener_id);
|
||||
auto opts = fmt::format(
|
||||
"{}={}", CCAPI_MARKET_DEPTH_MAX, depth_stream.num_levels());
|
||||
for (const auto &symbol : symbols) {
|
||||
std::string corr_id = fmt::format("{}", listener_id);
|
||||
ccapi::Subscription sub(
|
||||
"binance", symbol, CCAPI_MARKET_DEPTH, opts, corr_id);
|
||||
ccapi_session().subscribe(sub);
|
||||
}
|
||||
}
|
||||
|
||||
void unsubscribe_ftx(MarketDataListenerID listener_id) {
|
||||
bts_assert_msg(
|
||||
ccapi_listener_.has_value(),
|
||||
"Ignoring request to unsubscribe from FTX market data. "
|
||||
"CCApiListenerAdaptor not created.");
|
||||
ccapi_listener_->unregister_listener(listener_id);
|
||||
if (ccapi_listener_->empty()) {
|
||||
ccapi_session_.reset();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MarketDataGateway::MarketDataGateway()
|
||||
@@ -68,35 +148,72 @@ MarketDataGateway::MarketDataGateway()
|
||||
MarketDataGateway::~MarketDataGateway() = default;
|
||||
|
||||
MarketDataRegistration MarketDataGateway::subscribe(
|
||||
const api::md::MarketDataConfig &cfg,
|
||||
IMarketDataListener *listener) noexcept {
|
||||
const MarketDataSubscription &sub, IMarketDataListener *listener) noexcept {
|
||||
auto reg = me_->registration_factory.create();
|
||||
bts_assert(reg.listener_id.has_value());
|
||||
bts_assert(me_->sessions.find(*reg.listener_id) == me_->sessions.end());
|
||||
bts_assert(
|
||||
me_->registered_listeners.find(*reg.listener_id) ==
|
||||
me_->registered_listeners.end());
|
||||
LOG(md, bts::Info, "MarketDataGateway subscribing to data.\n{}\n",
|
||||
core::ProtoPrinterFactory::create(&cfg));
|
||||
core::ProtoPrinter<api::md::MarketDataSubscriptionParams>(
|
||||
&sub.params()));
|
||||
|
||||
vector<string> cfg_errs;
|
||||
_validate(cfg, cfg_errs);
|
||||
if (!cfg_errs.empty()) {
|
||||
return MarketDataRegistration{
|
||||
{MarketDataRegistrationError::Type::CONFIG_ERROR,
|
||||
fmt::to_string(fmt::join(cfg_errs, "\n"))}};
|
||||
}
|
||||
|
||||
MarketDataListenerData listener_data;
|
||||
auto &listener_data = me_->registered_listeners[*reg.listener_id];
|
||||
listener_data.id = *reg.listener_id;
|
||||
listener_data.listener = listener;
|
||||
listener_data.cfg = cfg;
|
||||
me_->sessions.try_emplace(
|
||||
listener_data.id, listener_data, &me_->sec_id_store);
|
||||
listener_data.subscription = sub;
|
||||
|
||||
switch (sub.venue()) {
|
||||
case api::domain::Venue::BINANCE:
|
||||
bts_assert(
|
||||
sub.params().VenueParams_case() ==
|
||||
api::md::MarketDataSubscriptionParams::kBinance);
|
||||
me_->subscribe_binance(sub.params().binance(), listener);
|
||||
break;
|
||||
case api::domain::Venue::FTX:
|
||||
bts_assert(
|
||||
sub.params().VenueParams_case() ==
|
||||
api::md::MarketDataSubscriptionParams::kFtx);
|
||||
LOG(md, bts::Info, "MarketDataGateway subscribing to data.\n{}\n",
|
||||
core::ProtoPrinter<api::md::MarketDataSubscriptionParams>(
|
||||
&sub.params()));
|
||||
me_->subscribe_ftx(sub.params().ftx(), listener, listener_data.id);
|
||||
break;
|
||||
default:
|
||||
return MarketDataRegistration{
|
||||
MarketDataListenerID{0},
|
||||
MarketDataRegstrationError::Type::NOT_IMPLEMENTED};
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
void MarketDataGateway::unsubscribe(MarketDataListenerID id) {
|
||||
LOG(md, bts::Info, "Unsubscribing listener {}", id);
|
||||
bts_assert(CONTAINS_KEY(me_->sessions, id));
|
||||
me_->sessions.erase(id);
|
||||
bts_assert(CONTAINS_KEY(me_->registered_listeners, id));
|
||||
auto &ld = me_->registered_listeners[id];
|
||||
auto *listener = ld.listener;
|
||||
bts_assert(listener);
|
||||
auto &sub = ld.subscription;
|
||||
|
||||
switch (sub.venue()) {
|
||||
case api::domain::Venue::BINANCE:
|
||||
bts_assert(
|
||||
sub.params().VenueParams_case() ==
|
||||
api::md::MarketDataSubscriptionParams::kBinance);
|
||||
me_->unsubscribe_binance(sub.params().binance(), listener);
|
||||
break;
|
||||
case api::domain::Venue::FTX:
|
||||
bts_assert(
|
||||
sub.params().VenueParams_case() ==
|
||||
api::md::MarketDataSubscriptionParams::kFtx);
|
||||
me_->unsubscribe_ftx(id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
me_->registered_listeners.erase(id);
|
||||
}
|
||||
|
||||
} // namespace bts::md
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#pragma once
|
||||
#include "MarketDataListenerID.h"
|
||||
#include "MarketDataRegistrationFactory.h"
|
||||
#include "MarketDataSubscription.h"
|
||||
#include "lib/domain/SecurityID.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace bts::api::md {
|
||||
class MarketDataConfig;
|
||||
}
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
@@ -21,7 +25,7 @@ class MarketDataGateway {
|
||||
* @return MarketDataRegistration
|
||||
*/
|
||||
MarketDataRegistration subscribe(
|
||||
const api::md::MarketDataConfig &, IMarketDataListener *) noexcept;
|
||||
const MarketDataSubscription &, IMarketDataListener *) noexcept;
|
||||
|
||||
void unsubscribe(MarketDataListenerID id);
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#pragma once
|
||||
#include "lib/api/md/MarketDataConfig.pb.h"
|
||||
#include "lib/domain/SecurityID.h"
|
||||
#include "lib/md/IMarketDataListener.h"
|
||||
#include "lib/md/MarketDataListenerID.h"
|
||||
#include "lib/md/MarketDataSubscription.h"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
struct MarketDataListenerData {
|
||||
MarketDataListenerID id;
|
||||
IMarketDataListener *listener;
|
||||
api::md::MarketDataConfig cfg;
|
||||
MarketDataSubscription subscription;
|
||||
};
|
||||
|
||||
} // namespace bts::md
|
||||
@@ -8,25 +8,10 @@ namespace bts::md {
|
||||
|
||||
class MarketDataRegistration {
|
||||
public:
|
||||
MarketDataRegistration() = default;
|
||||
explicit MarketDataRegistration(MarketDataListenerID listener_id);
|
||||
explicit MarketDataRegistration(MarketDataRegistrationError error);
|
||||
// will have a value when there is no error
|
||||
std::optional<MarketDataListenerID> listener_id;
|
||||
// domain::Venue venue = domain::Venue::Glbx;
|
||||
MarketDataRegistrationError error = {};
|
||||
MarketDataRegstrationError error = {};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Definition
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
inline MarketDataRegistration::MarketDataRegistration(
|
||||
MarketDataListenerID listener_id)
|
||||
: listener_id(listener_id), error() {}
|
||||
|
||||
inline MarketDataRegistration::MarketDataRegistration(
|
||||
MarketDataRegistrationError error)
|
||||
: listener_id(std::nullopt), error(error) {}
|
||||
|
||||
} // namespace bts::md
|
||||
@@ -1,10 +1,9 @@
|
||||
#pragma once
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
struct MarketDataRegistrationError {
|
||||
struct MarketDataRegstrationError {
|
||||
enum class Type {
|
||||
NO_ERROR = 0,
|
||||
NETWORK_ERROR = 1,
|
||||
@@ -15,8 +14,7 @@ struct MarketDataRegistrationError {
|
||||
// Any error that occurred on our end. As this error type is vague, the
|
||||
// accompanying error message should provide adequate information and
|
||||
// context
|
||||
INTERNAL_ERROR = 3,
|
||||
CONFIG_ERROR = 4
|
||||
INTERNAL_ERROR = 3
|
||||
};
|
||||
|
||||
Type error_type{Type::NO_ERROR};
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
#include "lib/api/domain/Venue.pb.h"
|
||||
#include "lib/api/md/MarketDataSubscriptionParams.pb.h"
|
||||
#include "lib/api/md/deribit/DeribitMarketDataSubscriptionParams.pb.h"
|
||||
#include "lib/api/md/glbx/GlbxMarketDataSubscriptionParams.pb.h"
|
||||
#include <variant>
|
||||
|
||||
namespace bts::md {
|
||||
|
||||
class MarketDataSubscription {
|
||||
public:
|
||||
api::domain::Venue venue() const;
|
||||
|
||||
MarketDataSubscription() = default;
|
||||
explicit MarketDataSubscription(
|
||||
api::md::MarketDataSubscriptionParams params);
|
||||
|
||||
MarketDataSubscription(const MarketDataSubscription &) = default;
|
||||
MarketDataSubscription(MarketDataSubscription &&) = default;
|
||||
MarketDataSubscription &operator=(const MarketDataSubscription &) = default;
|
||||
MarketDataSubscription &operator=(MarketDataSubscription &&) = default;
|
||||
|
||||
const api::md::MarketDataSubscriptionParams ¶ms() const;
|
||||
|
||||
private:
|
||||
api::md::MarketDataSubscriptionParams params_{};
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Definition
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
inline MarketDataSubscription::MarketDataSubscription(
|
||||
api::md::MarketDataSubscriptionParams params)
|
||||
: params_(std::move(params)) {}
|
||||
|
||||
inline const api::md::MarketDataSubscriptionParams &
|
||||
MarketDataSubscription::params() const {
|
||||
return params_;
|
||||
}
|
||||
|
||||
inline api::domain::Venue MarketDataSubscription::venue() const {
|
||||
switch (params_.VenueParams_case()) {
|
||||
case api::md::MarketDataSubscriptionParams::VenueParamsCase::kBinance:
|
||||
return api::domain::Venue::BINANCE;
|
||||
case api::md::MarketDataSubscriptionParams::VenueParamsCase::kDeribit:
|
||||
return api::domain::Venue::DERIBIT;
|
||||
case api::md::MarketDataSubscriptionParams::VenueParamsCase::kFtx:
|
||||
return api::domain::Venue::FTX;
|
||||
case api::md::MarketDataSubscriptionParams::VenueParamsCase::kGlbx:
|
||||
return api::domain::Venue::GLBX;
|
||||
case api::md::MarketDataSubscriptionParams::VenueParamsCase::kHuobi:
|
||||
return api::domain::Venue::HUOBI;
|
||||
default:
|
||||
return api::domain::Venue::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bts::md
|
||||
@@ -235,30 +235,6 @@ size_t get_system_md_symbols(
|
||||
&result);
|
||||
}
|
||||
}
|
||||
{
|
||||
if (exchange == api::VENUE_FTX || exchange == api::VENUE_UNSET) {
|
||||
auto const &e = config::get<config::system_symbols::Symbols>().ftx();
|
||||
if (type == api::SECURITYTYPE_FUTURE ||
|
||||
type == api::SECURITYTYPE_UNSET) {
|
||||
add_symbols_to_result(
|
||||
e.future(), api::VENUE_FTX, api::SECURITYTYPE_FUTURE, &result);
|
||||
}
|
||||
if (type == api::SECURITYTYPE_OPTION ||
|
||||
type == api::SECURITYTYPE_UNSET) {
|
||||
add_symbols_to_result(
|
||||
e.option(), api::VENUE_FTX, api::SECURITYTYPE_OPTION, &result);
|
||||
}
|
||||
if (type == api::SECURITYTYPE_STOCK ||
|
||||
type == api::SECURITYTYPE_UNSET) {
|
||||
add_symbols_to_result(
|
||||
e.option(), api::VENUE_FTX, api::SECURITYTYPE_STOCK, &result);
|
||||
}
|
||||
if (type == api::SECURITYTYPE_SPREAD ||
|
||||
type == api::SECURITYTYPE_UNSET)
|
||||
add_symbols_to_result(
|
||||
e.spread(), api::VENUE_FTX, api::SECURITYTYPE_SPREAD, &result);
|
||||
}
|
||||
}
|
||||
for (const auto &u : result) {
|
||||
LOG(md, Info, "get_system_md_symbols loaded sym: {} exch: {} type: {}",
|
||||
u.symbol(), Venue_Name(u.exchange()), SecurityType_Name(u.type()));
|
||||
|
||||
Loaded 100 of 360 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user