Compare commits
88
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11e6d25001 | ||
|
|
83d66ae9d7 | ||
|
|
e5e74b7b42 | ||
|
|
6ce2fb2cc5 | ||
|
|
9d63a004ec | ||
|
|
ccd53d71ea | ||
|
|
74a0235227 | ||
|
|
42bb101b43 | ||
|
|
c53561c6ef | ||
|
|
3701a70bd9 | ||
|
|
df56de3dd2 | ||
|
|
c9a418ce4b | ||
|
|
aaad404507 | ||
|
|
45acaa20b7 | ||
|
|
96a08500fb | ||
|
|
510e7b0050 | ||
|
|
2ab76c753e | ||
|
|
a02c6b77d4 | ||
|
|
6a289a5561 | ||
|
|
fddd310a03 | ||
|
|
d2a2d5fb37 | ||
|
|
4b76442a8f | ||
|
|
09b863f2ab | ||
|
|
dd221aba10 | ||
|
|
5ef862b026 | ||
|
|
cc43e9d3a4 | ||
|
|
b6eb727bc9 | ||
|
|
8ace69ab74 | ||
|
|
dc88b4ee10 | ||
|
|
dee32dead4 | ||
|
|
b2e022505f | ||
|
|
ac9b3ec365 | ||
|
|
ed89da7f38 | ||
|
|
a334d9be88 | ||
|
|
aee56569d1 | ||
|
|
7fdd3f6b1b | ||
|
|
3e1949d94f | ||
|
|
4cb3dbc313 | ||
|
|
0268bd476f | ||
|
|
2511b0d966 | ||
|
|
92456649df | ||
|
|
ec32078dd5 | ||
|
|
6bcce832ac | ||
|
|
85529b2232 | ||
|
|
c3cb8995bf | ||
|
|
ab2f0f975e | ||
|
|
2e133ea182 | ||
|
|
30615f3429 | ||
|
|
61371804a2 | ||
|
|
02d82e39bc | ||
|
|
50188e6688 | ||
|
|
5137785f7f | ||
|
|
def021612c | ||
|
|
217c5be131 | ||
|
|
a75441cd07 | ||
|
|
78eb096d6f | ||
|
|
2b66f46db1 | ||
|
|
ae3029d9ed | ||
|
|
d4a0603933 | ||
|
|
db6e96cf00 | ||
|
|
371db4afd2 | ||
|
|
08484a0954 | ||
|
|
39db44ed63 | ||
|
|
b4dca8e23f | ||
|
|
b4bf06d17a | ||
|
|
8c17705f02 | ||
|
|
551f26e5f3 | ||
|
|
f4adf35e49 | ||
|
|
90128863d9 | ||
|
|
300831c97a | ||
|
|
f3f6a82d9a | ||
|
|
7c8a41b2b7 | ||
|
|
408114c1f6 | ||
|
|
5c9be0bfb9 | ||
|
|
c0f970ab89 | ||
|
|
25e1804286 | ||
|
|
3c84dc48f6 | ||
|
|
9ae20f0c4d | ||
|
|
e8a72e7bd9 | ||
|
|
e99e2d817a | ||
|
|
7f4468c812 | ||
|
|
6206cbc425 | ||
|
|
21e50745e2 | ||
|
|
990e21e387 | ||
|
|
357be39db3 | ||
|
|
68e04cb3f5 | ||
|
|
b4a5d5c832 | ||
|
|
242fd758f4 |
No files matched your search
@@ -9,7 +9,7 @@
|
||||
]
|
||||
},
|
||||
"fable": {
|
||||
"version": "4.24.0",
|
||||
"version": "4.0.6",
|
||||
"commands": [
|
||||
"fable"
|
||||
]
|
||||
@@ -27,4 +27,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,12 +90,6 @@ RUN apt-get update && apt-get install -y libpcap0.8-dev
|
||||
# Databento (deps)
|
||||
RUN apt-get update && apt-get -y install libzstd-dev
|
||||
|
||||
# Docker in Docker
|
||||
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; \
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"dockerFile": "Dockerfile",
|
||||
// Creates local dir to mount to HOME in docker
|
||||
"initializeCommand": "mkdir -p ${localEnv:HOME}/.bts/devcontainer-mounts/${devcontainerId}",
|
||||
"hostRequirements": {
|
||||
"memory": "8gb",
|
||||
"storage": "10gb"
|
||||
"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
|
||||
@@ -12,20 +17,34 @@
|
||||
// example, if 8000-8003 is taken, go with 9000-9003, then 10000-10003, etc.
|
||||
"runArgs": [
|
||||
"--shm-size",
|
||||
"8gb"
|
||||
"2gb",
|
||||
"-p",
|
||||
"8000:8000",
|
||||
"-p",
|
||||
"8001:8001",
|
||||
"-p",
|
||||
"8002:8002",
|
||||
"-p",
|
||||
"8003:8003",
|
||||
"-p",
|
||||
"12345:12345"
|
||||
],
|
||||
"mounts": [
|
||||
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
|
||||
"source=${localEnv:HOME}/.bts/devcontainer-mounts/${devcontainerId},target=/home/bts,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",
|
||||
"xaver.clang-format"
|
||||
"ms-vscode.cpptools"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
# This file defines the global default configuration for docker deployments.
|
||||
# It is tracked in source control. For temporary modifications, please create
|
||||
# a separate file called ".env.local" (it's in .gitignore, so won't be tracked).
|
||||
# If a variable is defined in both files, the value in .env.local will be used.
|
||||
#
|
||||
# About the deployment procedure:
|
||||
# We use Docker Compose to build images and launch containers for various services
|
||||
# that make up our software suite:
|
||||
# - sparkd
|
||||
# - TODO: pubsub
|
||||
# - TODO: md-publisher
|
||||
# - TODO: webapp (DSQA on the web)
|
||||
# - TODO: api-server (websocket based)
|
||||
# From inside a devcontainer, you can launch all services in separate containers
|
||||
# on your machine by running:
|
||||
#
|
||||
# tools/deploy.sh
|
||||
#
|
||||
# This script builds release versions for each service, packaged (generally) in
|
||||
# self-contained directories. Next, it runs a few "docker compose" commands to
|
||||
# build docker images loaded with the self-contained binaries from the previous
|
||||
# step, and start containers with those images to run each service. To view the
|
||||
# commands that deploy.sh runs internally (without actually running them), run:
|
||||
#
|
||||
# tools/deploy.sh --dry-run
|
||||
#
|
||||
# For additional information/help, run:
|
||||
#
|
||||
# tools/deploy.sh --help
|
||||
#
|
||||
|
||||
### Sparkd ###
|
||||
# The internal image for sparkd to use. For more info, view:
|
||||
# src/server/sparkd/Dockerfile
|
||||
SPARKD__IMAGE=sparkd
|
||||
# The config dir for this service to use
|
||||
SPARKD__CONFIG_DIR=src/server/sparkd/configurations/dev
|
||||
# Mount a specific volume or dir to "~/sparkdata/data" inside the docker.
|
||||
# Defaults to a volume named "sparkd_<config_port>" (e.g., sparkd_8000).
|
||||
# SPARKD__DATA_DIR=/home/bts/sparkdata/data
|
||||
SPARKD__SOURCE_DIR=install/sparkd-release-gcc
|
||||
SPARKD__RUNTIME_CONF_DIR=/home/ubuntu/8000/sparkdata/conf/
|
||||
SPARKD__CONFIG_PORT=8000
|
||||
SPARKD__QUICKBUS_PORT=8001
|
||||
SPARKD__SIM_FIX_PORT=8002
|
||||
SPARKD__SHM_SIZE=4gb
|
||||
|
||||
# TODO: add config for other services (pubsub, md-publisher, webapp, api-server, etc.)
|
||||
@@ -59,4 +59,3 @@ trace_data/
|
||||
.devcontainer/
|
||||
*.Generated.cs
|
||||
*.lst
|
||||
.env.local
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[submodule "externals"]
|
||||
path = externals
|
||||
url = https://bitbucket.org/bluetradesys/externals.git
|
||||
url = git@bitbucket.org:bluetradesys/externals.git
|
||||
[submodule "vcpkg"]
|
||||
path = vcpkg
|
||||
url = https://github.com/microsoft/vcpkg.git
|
||||
Vendored
+12
-183
@@ -31,39 +31,7 @@
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "/home/bts/spark/build/sparkd-debug-clang/server/sparkd",
|
||||
"args": [
|
||||
"run"
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "/home/bts/spark/build/sparkd-debug-clang/server",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
},
|
||||
{
|
||||
"name": "spreader tests2",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "/home/bts/spark/build/sparkd-debug-clang/server/sparkd",
|
||||
"args": [
|
||||
"test",
|
||||
"[spreader2]"
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "/home/bts/spark/build/sparkd-debug-clang/server",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
},
|
||||
{
|
||||
"name": "spreader tests",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "/home/bts/spark/build/sparkd-debug-clang/server/sparkd",
|
||||
"args": [
|
||||
"test",
|
||||
"[spreader]"
|
||||
],
|
||||
"args": ["run"],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "/home/bts/spark/build/sparkd-debug-clang/server",
|
||||
"environment": [],
|
||||
@@ -123,18 +91,6 @@
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Spark (Skip Build)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"windows": {
|
||||
"program": "Spark.exe",
|
||||
"cwd": "build/Debug/bin/net7.0-windows",
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Spark (Parameterized)",
|
||||
"type": "coreclr",
|
||||
@@ -152,139 +108,22 @@
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Spark Test",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"windows": {
|
||||
"preLaunchTask": "Build Spark (Debug)",
|
||||
"program": "Spark.Console.exe",
|
||||
"cwd": "build/Debug/bin/net7.0",
|
||||
"args": [
|
||||
"test",
|
||||
"${input:sparkTest}"
|
||||
]
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Spark Test (Skip Build)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"windows": {
|
||||
"program": "Spark.Console.exe",
|
||||
"cwd": "build/Debug/bin/net7.0",
|
||||
"args": [
|
||||
"test",
|
||||
"${input:sparkTest}"
|
||||
]
|
||||
},
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Sparkd",
|
||||
"type": "cppdbg",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "Build Sparkd (Debug | Clang)",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"preLaunchTask": "Build Sparkd (Debug)",
|
||||
"program": "${workspaceFolder}/build/sparkd-debug-clang/server/sparkd",
|
||||
"args": [
|
||||
"run"
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/build/sparkd-debug-clang/server",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Sparkd (Skip Build)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "${workspaceFolder}/build/sparkd-debug-clang/server/sparkd",
|
||||
"args": [
|
||||
"run"
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/build/sparkd-debug-clang/server",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Sparkd Test",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"preLaunchTask": "Build Sparkd (Debug)",
|
||||
"program": "${workspaceFolder}/build/sparkd-debug-clang/server/sparkd",
|
||||
"args": [
|
||||
"test",
|
||||
"${input:sparkdTest}",
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/build/sparkd-debug-clang/server",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Sparkd Test (Skip Build)",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "",
|
||||
"linux": {
|
||||
"program": "${workspaceFolder}/build/sparkd-debug-clang/server/sparkd",
|
||||
"args": [
|
||||
"test",
|
||||
"${input:sparkdTest}",
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/build/sparkd-debug-clang/server",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"program": "sparkd",
|
||||
},
|
||||
"args": [
|
||||
"run"
|
||||
],
|
||||
"cwd": "build/sparkd-debug-clang/server",
|
||||
"stopAtEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
@@ -315,15 +154,5 @@
|
||||
"description": "Config Server URL",
|
||||
"default": "http://localhost:8000/config",
|
||||
},
|
||||
{
|
||||
"id": "sparkTest",
|
||||
"type": "promptString",
|
||||
"description": "Test to run",
|
||||
},
|
||||
{
|
||||
"id": "sparkdTest",
|
||||
"type": "promptString",
|
||||
"description": "Test to run",
|
||||
},
|
||||
]
|
||||
}
|
||||
Vendored
+1
-103
@@ -641,21 +641,6 @@
|
||||
"color": "terminal.ansiGreen",
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Run Spark (Skip Build)",
|
||||
"type": "process",
|
||||
"command": "",
|
||||
"windows": {
|
||||
"command": "Spark.exe",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build/${input:buildConfiguration}/bin/net7.0-windows"
|
||||
},
|
||||
},
|
||||
"icon": {
|
||||
"id": "run",
|
||||
"color": "terminal.ansiGreen",
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "Run Spark Config Query",
|
||||
"dependsOn": "Build Spark",
|
||||
@@ -699,24 +684,6 @@
|
||||
"color": "terminal.ansiGreen",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "Run Sparkd (Skip Build)",
|
||||
"type": "process",
|
||||
"command": "",
|
||||
"linux": {
|
||||
"command": "sparkd",
|
||||
},
|
||||
"args": [
|
||||
"run"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build/${input:sparkdCmakePreset}/server"
|
||||
},
|
||||
"icon": {
|
||||
"id": "run",
|
||||
"color": "terminal.ansiGreen",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "Run Sparkd Config Query",
|
||||
"dependsOn": "Build Sparkd",
|
||||
@@ -738,65 +705,6 @@
|
||||
"color": "terminal.ansiGreen",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "Test Spark (Debug)",
|
||||
"dependsOn": "Build Spark (Debug)",
|
||||
"type": "process",
|
||||
"icon": {
|
||||
"id": "coverage",
|
||||
"color": "terminal.ansiYellow",
|
||||
},
|
||||
"command": "",
|
||||
"windows": {
|
||||
"command": "Spark.Console.exe",
|
||||
"args": [
|
||||
"test",
|
||||
"${input:sparkTest}"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build/Debug/bin/net7.0",
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "Test Sparkd",
|
||||
"dependsOn": "Build Sparkd",
|
||||
"type": "process",
|
||||
"command": "",
|
||||
"linux": {
|
||||
"command": "sparkd",
|
||||
},
|
||||
"args": [
|
||||
"test",
|
||||
"${input:sparkdTest}",
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build/${input:sparkdCmakePreset}/server"
|
||||
},
|
||||
"icon": {
|
||||
"id": "coverage",
|
||||
"color": "terminal.ansiYellow",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "Test Sparkd (Skip Build)",
|
||||
"type": "process",
|
||||
"command": "",
|
||||
"linux": {
|
||||
"command": "sparkd",
|
||||
},
|
||||
"args": [
|
||||
"test",
|
||||
"${input:sparkdTest}",
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/build/${input:sparkdCmakePreset}/server"
|
||||
},
|
||||
"icon": {
|
||||
"id": "coverage",
|
||||
"color": "terminal.ansiYellow",
|
||||
},
|
||||
},
|
||||
{
|
||||
"label": "View DataStreamQueryAnalyzer Logs (Last Run)",
|
||||
"type": "process",
|
||||
@@ -915,16 +823,6 @@
|
||||
"id": "sparkdConfigQuery",
|
||||
"type": "promptString",
|
||||
"description": "Config Type(s)"
|
||||
},
|
||||
{
|
||||
"id": "sparkTest",
|
||||
"type": "promptString",
|
||||
"description": "Test to run",
|
||||
},
|
||||
{
|
||||
"id": "sparkdTest",
|
||||
"type": "promptString",
|
||||
"description": "Test to run",
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
+7
-18
@@ -1,10 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
project(spark)
|
||||
include(GNUInstallDirs)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/GitVersion.cmake)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
get_version_from_git()
|
||||
if(WIN32)
|
||||
set(platform "windows")
|
||||
else()
|
||||
@@ -52,6 +49,8 @@ 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")
|
||||
set(SPARK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/$<CONFIG>")
|
||||
|
||||
if(BUILD_SPARKD)
|
||||
# Note: All macros that begin w/ 'CCAPI' are ccapi's macros (defined and/or
|
||||
@@ -90,15 +89,9 @@ else()
|
||||
add_compile_definitions(BINANCE_US_PRICE_STATS_PATH="/api/v3/ticker/24hr")
|
||||
|
||||
# ** Binance USDS Futures **
|
||||
add_compile_definitions(CCAPI_BINANCE_USDS_FUTURES_URL_REST_BASE="https://fapi.binance.com")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_INSTRUMENTS_PATH="/fapi/v1/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_PRICE_STATS_PATH="/fapi/v1/ticker/24hr")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_USER_DATA_PATH="/api/v3/userDataStream")
|
||||
|
||||
# ** Binance Coin Futures **
|
||||
add_compile_definitions(CCAPI_BINANCE_COIN_FUTURES_URL_REST_BASE="https://dapi.binance.com")
|
||||
add_compile_definitions(BINANCE_COIN_FUTURES_INSTRUMENTS_PATH="/dapi/v1/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_COIN_FUTURES_PRICE_STATS_PATH="/dapi/v1/ticker/24hr")
|
||||
add_compile_definitions(CCAPI_BINANCE_USDS_FUTURES_URL_REST_BASE="https://dapi.binance.com")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_INSTRUMENTS_PATH="/dapi/v1/exchangeInfo")
|
||||
add_compile_definitions(BINANCE_USDS_FUTURES_PRICE_STATS_PATH="/dapi/v1/ticker/24hr")
|
||||
|
||||
# ** Deribit **
|
||||
add_compile_definitions(DERIBIT_INSTRUMENT_PATH="/api/v2/public/get_instrument")
|
||||
@@ -118,7 +111,6 @@ else()
|
||||
|
||||
# subdirs
|
||||
if (BUILD_SPARKD)
|
||||
add_subdirectory(src/lib_binance_execution)
|
||||
add_subdirectory(src/server/sparkd)
|
||||
add_subdirectory(src/data_files)
|
||||
endif()
|
||||
@@ -155,14 +147,11 @@ else()
|
||||
|
||||
install(
|
||||
DIRECTORY "${CMAKE_BINARY_DIR}/server/plugins"
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
DESTINATION "${SPARK_INSTALL_PREFIX}/bin")
|
||||
install(
|
||||
FILES
|
||||
"${SPARK_LIB}/libACE-5.7.5.so"
|
||||
"${SPARK_LIB}/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0"
|
||||
"${SPARK_LIB}/libonixs-fix-engine.so.4.10.1"
|
||||
"${SPARK_LIB}/libonixs-fix-engine.so.4"
|
||||
"${SPARK_LIB}/libonixs-fix-engine.so"
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
DESTINATION "${SPARK_INSTALL_PREFIX}/bin")
|
||||
endif()
|
||||
endif()
|
||||
+11
-3
@@ -26,7 +26,6 @@
|
||||
"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",
|
||||
@@ -62,7 +61,7 @@
|
||||
},
|
||||
"CMAKE_CXX_STANDARD": "20",
|
||||
"CMAKE_INSTALL_RPATH": ".",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/install/${presetName}/sparkd",
|
||||
"CMAKE_EXE_LINKER_FLAGS": "-Wno-undef",
|
||||
"EXTERNALS_ROOT": "${sourceDir}/externals/linux",
|
||||
"BUILD_SDK": {
|
||||
@@ -303,7 +302,16 @@
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Linux"
|
||||
},
|
||||
"hidden": true
|
||||
"hidden": true,
|
||||
"targets": [
|
||||
"data_files_dir",
|
||||
"admin_web_app_bundle",
|
||||
"install",
|
||||
"libspark",
|
||||
"rapidjson_project",
|
||||
"server_layout",
|
||||
"sparkd"
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
@@ -14,34 +14,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spark_test", "src\client\sp
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spark.Console", "src\client\Spark.Console\Spark.Console.csproj", "{89D666E6-B500-498F-B026-4D167F68ADFC}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{267F81EF-A8AB-49FD-9F56-D7EC3C1F7C7C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataStreamSuite", "DataStreamSuite", "{C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamCore", "src\DataStreamSuite\DataStreamCore\DataStreamCore.csproj", "{EF26A475-6101-4C9C-A717-D60BB92A2302}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedStreams", "src\DataStreamSuite\SharedStreams\SharedStreams.csproj", "{911B08A3-515A-441D-84C8-8A43740B5FC1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PubSub", "src\DataStreamSuite\PubSub\PubSub.csproj", "{14140310-2233-430A-821B-F3058A25234B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaseUtilities", "src\DataStreamSuite\BaseUtilities\BaseUtilities.csproj", "{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExpressionCore", "src\DataStreamSuite\ExpressionCore\ExpressionCore.csproj", "{6F22DB96-6EAB-4034-99D9-287021C36F01}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArithmeticExpressions", "src\DataStreamSuite\ArithmeticExpressions\ArithmeticExpressions.csproj", "{A5C33956-A41F-49B3-A41D-1082CBA59D02}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamExpressions", "src\DataStreamSuite\DataStreamExpressions\DataStreamExpressions.csproj", "{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.ColumnSortExpressions", "src\DataStreamSuite\Bts.ColumnSortExpressions\Bts.ColumnSortExpressions.csproj", "{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColumnMapExpressions", "src\DataStreamSuite\ColumnMapExpressions\ColumnMapExpressions.csproj", "{B945A183-2174-4ACB-B289-8A5C546656FE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooleanExpressions", "src\DataStreamSuite\BooleanExpressions\BooleanExpressions.csproj", "{9F6D7DE8-185B-4C1D-B809-3314D092DF28}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.ColumnExpressions", "src\DataStreamSuite\Bts.ColumnExpressions\Bts.ColumnExpressions.csproj", "{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStream", "src\DataStreamSuite\DataStream\DataStream.csproj", "{39AEA075-6457-46C0-8821-1158BE6EFA57}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@@ -98,102 +70,6 @@ Global
|
||||
{89D666E6-B500-498F-B026-4D167F68ADFC}.Release|x64.Build.0 = Release|x64
|
||||
{89D666E6-B500-498F-B026-4D167F68ADFC}.RelWithDebInfo|x64.ActiveCfg = Debug|x64
|
||||
{89D666E6-B500-498F-B026-4D167F68ADFC}.RelWithDebInfo|x64.Build.0 = Debug|x64
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302}.Release|x64.Build.0 = Release|Any CPU
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{14140310-2233-430A-821B-F3058A25234B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{14140310-2233-430A-821B-F3058A25234B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{14140310-2233-430A-821B-F3058A25234B}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{14140310-2233-430A-821B-F3058A25234B}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{14140310-2233-430A-821B-F3058A25234B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{14140310-2233-430A-821B-F3058A25234B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{14140310-2233-430A-821B-F3058A25234B}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{14140310-2233-430A-821B-F3058A25234B}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57}.Release|x64.Build.0 = Release|Any CPU
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -204,19 +80,4 @@ Global
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{C09ED521-D2DF-40BC-A76F-EB3CB870B2F6} = {267F81EF-A8AB-49FD-9F56-D7EC3C1F7C7C}
|
||||
{EF26A475-6101-4C9C-A717-D60BB92A2302} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{911B08A3-515A-441D-84C8-8A43740B5FC1} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{14140310-2233-430A-821B-F3058A25234B} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{43146EA8-6FCC-46B8-88B0-42F9BB5E6E0A} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{6F22DB96-6EAB-4034-99D9-287021C36F01} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{A5C33956-A41F-49B3-A41D-1082CBA59D02} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{2FE745C3-1EDF-4421-8CD7-A63EE0C1AE43} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{FDA791E0-2B91-4AD5-B91D-CF920A4C4E38} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{B945A183-2174-4ACB-B289-8A5C546656FE} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{39AEA075-6457-46C0-8821-1158BE6EFA57} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{9F6D7DE8-185B-4C1D-B809-3314D092DF28} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,48 +0,0 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
function(get_version_from_git)
|
||||
find_package(Git QUIET)
|
||||
if(NOT Git_FOUND)
|
||||
message(WARNING "Git not found")
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --tags --always
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_TAG
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE GIT_RESULT
|
||||
)
|
||||
|
||||
if(NOT GIT_RESULT EQUAL 0)
|
||||
message(WARNING "Failed to get git tag")
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_SHORT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
set(PROJECT_VERSION_BUILD_METADATA ${GIT_COMMIT_SHORT_HASH})
|
||||
set(PROJECT_VERSION_BUILD_METADATA ${GIT_COMMIT_SHORT_HASH} PARENT_SCOPE)
|
||||
|
||||
string(REGEX REPLACE "^v" "" CLEAN_TAG "${GIT_TAG}")
|
||||
if(CLEAN_TAG MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)(-.*)?$")
|
||||
set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
set(PROJECT_VERSION_MAJOR ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2})
|
||||
set(PROJECT_VERSION_MINOR ${CMAKE_MATCH_2} PARENT_SCOPE)
|
||||
set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3})
|
||||
set(PROJECT_VERSION_PATCH ${CMAKE_MATCH_3} PARENT_SCOPE)
|
||||
|
||||
set(PROJECT_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
|
||||
set(PROJECT_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}" PARENT_SCOPE)
|
||||
set(PROJECT_VERSION_FULL "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}+${GIT_COMMIT_SHORT_HASH}")
|
||||
set(PROJECT_VERSION_FULL "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}+${GIT_COMMIT_SHORT_HASH}" PARENT_SCOPE)
|
||||
else()
|
||||
message(WARNING "Tag '${CLEAN_TAG}' does not match semver format")
|
||||
endif()
|
||||
endfunction()
|
||||
@@ -1,49 +0,0 @@
|
||||
include_guard(DIRECTORY)
|
||||
|
||||
function(protobuf_generate_fs)
|
||||
set(_options)
|
||||
set(_one_value_args TARGET_NAME OUT_DIR PROTOC)
|
||||
set(_multi_value_args PROTO_INCLUDE_DIRS PROTO_SOURCES)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
|
||||
if (NOT DEFINED _ARGS_TARGET_NAME)
|
||||
set(_ARGS_TARGET_NAME "${PROJECT_NAME}_generate_fs_protos")
|
||||
endif()
|
||||
if (NOT DEFINED _ARGS_PROTOC)
|
||||
set(_ARGS_PROTOC "${SPARK_BIN}/protoc")
|
||||
endif()
|
||||
|
||||
set(_proto_include_cli_args)
|
||||
foreach(_dir ${_ARGS_PROTO_INCLUDE_DIRS})
|
||||
list(APPEND _proto_include_cli_args -I ${_dir})
|
||||
endforeach()
|
||||
|
||||
set(_outputs)
|
||||
foreach(_proto_source ${_ARGS_PROTO_SOURCES})
|
||||
# get_filename_component(_abs_proto_source ${_proto_source} ABSOLUTE)
|
||||
get_filename_component(_proto_source_we ${_proto_source} NAME_WE)
|
||||
# get_filename_component(_proto_source_dir ${_proto_source} DIRECTORY)
|
||||
list(APPEND _outputs ${_ARGS_OUT_DIR}/${_proto_source_we}.fable.fs)
|
||||
endforeach()
|
||||
|
||||
set(_venv_exec ${CMAKE_SOURCE_DIR}/tools/venv_exec.sh)
|
||||
set(_plugin_py ${CMAKE_SOURCE_DIR}/src/lib/api/service_compiler/plugin.py)
|
||||
set(_template_fs ${CMAKE_SOURCE_DIR}/src/lib/api/service_compiler/templates/fs/fable.fs)
|
||||
add_custom_command(
|
||||
OUTPUT ${_outputs}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${_venv_exec}
|
||||
${_ARGS_PROTOC}
|
||||
--plugin=protoc-gen-service=${_plugin_py}
|
||||
--service_out=lang=fs,strip_out_path=1:${_ARGS_OUT_DIR}
|
||||
${_proto_include_cli_args}
|
||||
${_ARGS_PROTO_SOURCES}
|
||||
DEPENDS
|
||||
${_venv_exec}
|
||||
${_plugin_py}
|
||||
${_template_fs}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json
|
||||
${_ARGS_PROTO_SOURCES}
|
||||
)
|
||||
add_custom_target(${_ARGS_TARGET_NAME} ALL DEPENDS "${_outputs}")
|
||||
endfunction()
|
||||
@@ -1,33 +0,0 @@
|
||||
include_guard(DIRECTORY)
|
||||
|
||||
function(protobuf_generate_js)
|
||||
set(_options)
|
||||
set(_one_value_args TARGET_NAME OUTPUT)
|
||||
set(_multi_value_args PROTO_INCLUDE_DIRS PROTO_SOURCES)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
|
||||
if (NOT DEFINED _ARGS_TARGET_NAME)
|
||||
set(_ARGS_TARGET_NAME "${PROJECT_NAME}_generate_js_protos")
|
||||
endif()
|
||||
|
||||
set(_proto_include_cli_args)
|
||||
foreach(_dir ${_ARGS_PROTO_INCLUDE_DIRS})
|
||||
list(APPEND _proto_include_cli_args -p ${_dir})
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_ARGS_OUTPUT}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND npx
|
||||
--no-install pbjs
|
||||
-t json-module
|
||||
-w commonjs
|
||||
-o ${_ARGS_OUTPUT}
|
||||
${_proto_include_cli_args}
|
||||
${_ARGS_PROTO_SOURCES}
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json
|
||||
${_ARGS_PROTO_SOURCES}
|
||||
)
|
||||
add_custom_target(${_ARGS_TARGET_NAME} ALL DEPENDS ${_ARGS_OUTPUT})
|
||||
endfunction()
|
||||
@@ -1,49 +0,0 @@
|
||||
include_guard(DIRECTORY)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/TernaryOperator.cmake)
|
||||
|
||||
function(sym_link_dir)
|
||||
set(_options)
|
||||
set(_one_value_args TARGET_NAME SOURCE DEST COMMENT)
|
||||
set(_multi_value_args)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
add_custom_command(
|
||||
OUTPUT ${_ARGS_DEST}
|
||||
COMMAND ln ARGS -sf ${_ARGS_SOURCE} ${_ARGS_DEST}
|
||||
)
|
||||
set_ternary(_comment _ARGS_COMMENT "${_ARGS_COMMENT}" "linking dir ${_ARGS_SOURCE} -> ${_ARGS_DEST}")
|
||||
add_custom_target(
|
||||
${_ARGS_TARGET_NAME} ALL
|
||||
DEPENDS ${_ARGS_DEST}
|
||||
COMMENT "${_comment}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
function(sym_link_file)
|
||||
set(_options)
|
||||
set(_one_value_args SOURCE DEST INSTALL_DEST)
|
||||
set(_multi_value_args)
|
||||
cmake_parse_arguments(_ARGS "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN})
|
||||
file(
|
||||
CREATE_LINK
|
||||
${_ARGS_SOURCE}
|
||||
${_ARGS_DEST}
|
||||
SYMBOLIC
|
||||
)
|
||||
if (DEFINED _ARGS_INSTALL_DEST)
|
||||
install(
|
||||
FILES
|
||||
${_ARGS_SOURCE}
|
||||
DESTINATION ${_ARGS_INSTALL_DEST}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(sym_link_local_lib LIB_NAME)
|
||||
set(_lib_file_name "${CMAKE_SHARED_LIBRARY_PREFIX}${LIB_NAME}.so")
|
||||
file(
|
||||
CREATE_LINK
|
||||
"${CMAKE_BINARY_DIR}/src/lib_${LIB_NAME}/${_lib_file_name}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_lib_file_name}"
|
||||
SYMBOLIC
|
||||
)
|
||||
endfunction()
|
||||
@@ -1,9 +0,0 @@
|
||||
include_guard(GLOBAL)
|
||||
|
||||
macro(set_ternary RESULT CONDITION TRUE_VALUE FALSE_VALUE)
|
||||
if(${CONDITION})
|
||||
set(${RESULT} ${TRUE_VALUE})
|
||||
else()
|
||||
set(${RESULT} ${FALSE_VALUE})
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef BTS_SPARK_VERSION_H
|
||||
#define BTS_SPARK_VERSION_H
|
||||
|
||||
#define BTS_SPARK_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
|
||||
#define BTS_SPARK_VERSION_MINOR @PROJECT_VERSION_MINOR@
|
||||
#define BTS_SPARK_VERSION_PATCH @PROJECT_VERSION_PATCH@
|
||||
#define BTS_SPARK_VERSION_BUILD_METADATA @PROJECT_VERSION_BUILD_METADATA@
|
||||
#define BTS_SPARK_VERSION "@PROJECT_VERSION@"
|
||||
#define BTS_SPARK_VERSION_FULL "@PROJECT_VERSION_FULL@"
|
||||
|
||||
#endif
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
services:
|
||||
sparkd:
|
||||
volumes:
|
||||
- ${SPARKD__DATA_DIR:-sparkd_data}:/home/bts/sparkdata/data
|
||||
build:
|
||||
dockerfile: src/server/sparkd/Dockerfile
|
||||
args:
|
||||
- IMAGE=${SPARKD__IMAGE}
|
||||
- SOURCE_DIR=${SPARKD__SOURCE_DIR}
|
||||
- CONFIG_DIR=${SPARKD__CONFIG_DIR}
|
||||
shm_size: "${SPARKD__SHM_SIZE:-512mb}"
|
||||
command: >
|
||||
sh -c "
|
||||
echo bts | sudo -S chown -R bts:bts /home/bts/sparkdata/data
|
||||
if [ -e "/home/bts/sparkdata/data/logging.sparkd/log" ]; then
|
||||
mv "/home/bts/sparkdata/data/logging.sparkd/log" "/home/bts/sparkdata/data/logging.sparkd/log_$(date '+%Y%m%d-%H%M')"
|
||||
fi
|
||||
if [ -e "/home/bts/sparkdata/conf/.env.local" ]; then
|
||||
echo 'Sourcing /home/bts/sparkdata/conf/.env.local'
|
||||
set -a
|
||||
. /home/bts/sparkdata/conf/.env.local
|
||||
set +a
|
||||
fi
|
||||
./sparkd run"
|
||||
env_file:
|
||||
- .env
|
||||
- ${SPARKD__CONFIG_DIR}/.env
|
||||
ports:
|
||||
- "${SPARKD__CONFIG_PORT}:${SPARKD__CONFIG_PORT}"
|
||||
- "${SPARKD__QUICKBUS_PORT}:${SPARKD__QUICKBUS_PORT}"
|
||||
- "${SPARKD__SIM_FIX_PORT}:${SPARKD__SIM_FIX_PORT}"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: "${SPARKD__MEMORY:-4gb}"
|
||||
sparkd-symbols:
|
||||
volumes:
|
||||
- ${SPARKD__DATA_DIR:-sparkd_data}:/home/bts/sparkdata/data
|
||||
- ${SPARKD__RUNTIME_CONF_DIR:-sparkd_conf}:/home/bts/sparkdata/conf
|
||||
build:
|
||||
dockerfile: src/server/sparkd/Dockerfile
|
||||
args:
|
||||
- IMAGE=${SPARKD__IMAGE}
|
||||
- SOURCE_DIR=${SPARKD__SOURCE_DIR}
|
||||
- CONFIG_DIR=${SPARKD__CONFIG_DIR}
|
||||
shm_size: "${SPARKD__SHM_SIZE:-512mb}"
|
||||
command: >
|
||||
sh -c "
|
||||
echo bts | sudo -S chown -R bts:bts /home/bts/sparkdata/data
|
||||
if [ -e "/home/bts/sparkdata/data/logging.sparkd/log" ]; then
|
||||
mv "/home/bts/sparkdata/data/logging.sparkd/log" "/home/bts/sparkdata/data/logging.sparkd/log_$(date '+%Y%m%d-%H%M')"
|
||||
fi
|
||||
ls -alh /home/bts/sparkdata/conf/
|
||||
cat /home/bts/sparkdata/conf/.env.local
|
||||
if [ -e "/home/bts/sparkdata/conf/.env.local" ]; then
|
||||
echo 'Sourcing /home/bts/sparkdata/conf/.env.local'
|
||||
set -a
|
||||
. /home/bts/sparkdata/conf/.env.local
|
||||
set +a
|
||||
fi
|
||||
./sparkd run"
|
||||
env_file:
|
||||
- .env
|
||||
- ${SPARKD__CONFIG_DIR}/.env
|
||||
ports:
|
||||
- "${SPARKD__CONFIG_PORT}:${SPARKD__CONFIG_PORT}"
|
||||
- "${SPARKD__QUICKBUS_PORT}:${SPARKD__QUICKBUS_PORT}"
|
||||
- "${SPARKD__SIM_FIX_PORT}:${SPARKD__SIM_FIX_PORT}"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: "${SPARKD__MEMORY:-4gb}"
|
||||
|
||||
sparkd-tail:
|
||||
image: bluetradingsystems/linux_dotnet7
|
||||
volumes:
|
||||
- type: volume
|
||||
read_only: true
|
||||
source: sparkd_data
|
||||
target: /home/bts/sparkdata/data/logging.sparkd
|
||||
volume:
|
||||
subpath: logging.sparkd
|
||||
command: ["tail", "-f", "/home/bts/sparkdata/data/logging.sparkd/log"]
|
||||
|
||||
sparkd-ping-test:
|
||||
depends_on:
|
||||
- sparkd
|
||||
profiles:
|
||||
- ping-test
|
||||
build:
|
||||
context: .
|
||||
dockerfile_inline: |
|
||||
FROM bluetradingsystems/linux_dotnet7
|
||||
USER "root"
|
||||
RUN apt-get update && apt-get -y install iputils-ping
|
||||
command: [ "ping", "sparkd" ]
|
||||
|
||||
volumes:
|
||||
sparkd_data:
|
||||
name: "sparkd_${SPARKD__CONFIG_PORT:-8000}"
|
||||
@@ -1,38 +0,0 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update && apt-get install -y pkg-config
|
||||
RUN apt-get update && apt-get install -y locales
|
||||
RUN apt-get update && apt-get install -y ca-certificates
|
||||
RUN apt-get update && apt-get install -y libssh2-1-dev
|
||||
RUN apt-get update && apt-get install -y software-properties-common
|
||||
RUN apt-get update && apt-get install -y sudo
|
||||
|
||||
# GCC
|
||||
ARG gcc_major=13
|
||||
RUN add-apt-repository ppa:ubuntu-toolchain-r/test \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y g++-$gcc_major
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y dotnet7
|
||||
|
||||
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"
|
||||
|
||||
USER bts
|
||||
WORKDIR /home/bts
|
||||
Submodule
+1
Submodule docker/linux added at 56c61231f3.
Submodule
+1
Submodule docker/windows added at de7d40c09d.
+1
-1
Submodule externals updated: 959b63f2f6...8069cc893f.
@@ -1,20 +1,11 @@
|
||||
astroid==2.7.3
|
||||
autopep8==1.5.7
|
||||
blinker==1.9.0
|
||||
boto3==1.37.9
|
||||
botocore==1.37.9
|
||||
certifi==2023.5.7
|
||||
charset-normalizer==3.1.0
|
||||
click==8.1.8
|
||||
colorama==0.4.4
|
||||
Flask==3.1.0
|
||||
idna==3.4
|
||||
isort==5.9.3
|
||||
itsdangerous==2.2.0
|
||||
Jinja2==3.1.6
|
||||
jmespath==1.0.1
|
||||
lazy-object-proxy==1.6.0
|
||||
MarkupSafe==3.0.2
|
||||
mccabe==0.6.1
|
||||
platformdirs==2.3.0
|
||||
protobuf==4.21.12
|
||||
@@ -23,14 +14,9 @@ pycodestyle==2.7.0
|
||||
pycparser==2.20
|
||||
pylint==2.10.2
|
||||
PyMeta3==0.5.1
|
||||
python-dateutil==2.9.0.post0
|
||||
python-dotenv==1.0.1
|
||||
requests==2.31.0
|
||||
s3transfer==0.11.4
|
||||
six==1.17.0
|
||||
termcolor==1.1.0
|
||||
toml==0.10.2
|
||||
urllib3==2.0.3
|
||||
Werkzeug==3.1.3
|
||||
wrapt==1.12.1
|
||||
yapf==0.31.0
|
||||
@@ -18,11 +18,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.57" />
|
||||
<PackageReference Include="Microsoft.Data.Analysis" Version="0.21.1" />
|
||||
<PackageReference Include="MongoDB.Bson" Version="2.23.1" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.23.1" />
|
||||
<PackageReference Include="Parquet.Net" Version="5.0.1" />
|
||||
<PackageReference Include="System.Data.SQLite" Version="1.0.118" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,32 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using System;
|
||||
using BCG;
|
||||
using System.Collections.Generic;
|
||||
using Bts.DataStreamExpressions;
|
||||
|
||||
// All this does is take in a dsl expression, parse it and fire the data that come out of running it.
|
||||
// So for example, if an expresison is passed
|
||||
[DataStreamUserRespresentation("dsl")]
|
||||
public class DSLStream : ViewStream {
|
||||
private readonly string _dsl;
|
||||
public DSLStream(string dsl) {
|
||||
Log.Gen.info($"DSLStream.cons dsl: {dsl}");
|
||||
_dsl = dsl;
|
||||
ViewStream rs = build_stream(dsl);
|
||||
rs = rs ?? new LiteralStream("error", $"msg:invalid dsl \"{dsl}\"");
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
static ViewStream? build_stream(string stream_expression) {
|
||||
try {
|
||||
var exp = DataStreamExpressionsInterpreter.Evaluate(stream_expression);
|
||||
var rv = exp.getView(new Dictionary<string, StatementExpression>(0));
|
||||
return rv;
|
||||
|
||||
} catch (Exception ex) {
|
||||
Log.Gen.error($"Could not build stream: {stream_expression} ex: {ex}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using System;
|
||||
|
||||
public class NullFilterStream : ViewStream {
|
||||
public NullFilterStream(ViewStream parent_str, string col_name)
|
||||
: this(parent_str, col_name, true) { }
|
||||
public NullFilterStream(ViewStream parent_str, string col_name, bool filter_out_doublenans = false) {
|
||||
ViewStream rs = new FilterStream(parent_str,
|
||||
r => {
|
||||
bool is_dbnull = r.is_null(col_name);
|
||||
if (is_dbnull) {
|
||||
return false;
|
||||
}
|
||||
if (r.schema[col_name].type_code() == TypeCode.Double) {
|
||||
return !Double.IsNaN(r.get<double>(col_name));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,102 +1,102 @@
|
||||
// using System;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using System.Text;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
// namespace BCG
|
||||
// {
|
||||
namespace BCG
|
||||
{
|
||||
|
||||
// public class AverageGroupsStream : ViewStream
|
||||
// {
|
||||
// public AverageGroupsStream(ViewStream input, string colToAverage, string keyColumn)
|
||||
// {
|
||||
public class AverageGroupsStream : ViewStream
|
||||
{
|
||||
public AverageGroupsStream(ViewStream input, string colToAverage, string keyColumn)
|
||||
{
|
||||
|
||||
// myColToAverage = colToAverage;
|
||||
// myInput = input;
|
||||
// myKeyColumn = keyColumn;
|
||||
// }
|
||||
myColToAverage = colToAverage;
|
||||
myInput = input;
|
||||
myKeyColumn = keyColumn;
|
||||
}
|
||||
|
||||
// private ViewStream myInput;
|
||||
// private string myColToAverage;
|
||||
// private BlueTableSchema mySchema;
|
||||
// private string myKeyColumn;
|
||||
private ViewStream myInput;
|
||||
private string myColToAverage;
|
||||
private BlueTableSchema mySchema;
|
||||
private string myKeyColumn;
|
||||
|
||||
// protected override void myOnFirstSubscriber()
|
||||
// {
|
||||
// myInput.onChange += new ChangeDelegate(myInput_onChange);
|
||||
// }
|
||||
// protected override void myOnLastSubscriber()
|
||||
// {
|
||||
// myInput.onChange -= myInput_onChange;
|
||||
// }
|
||||
// private void myInput_onChange(object newValue)
|
||||
// {
|
||||
// if (mySchema == null)
|
||||
// myBuildSchema(((DataPacket)newValue).schema);
|
||||
protected override void myOnFirstSubscriber()
|
||||
{
|
||||
myInput.onChange += new ChangeDelegate(myInput_onChange);
|
||||
}
|
||||
protected override void myOnLastSubscriber()
|
||||
{
|
||||
myInput.onChange -= myInput_onChange;
|
||||
}
|
||||
private void myInput_onChange(object newValue)
|
||||
{
|
||||
if (mySchema == null)
|
||||
myBuildSchema(((DataPacket)newValue).schema);
|
||||
|
||||
// IBlueRowCollection newRows = myEvaluate((DataPacket)newValue);
|
||||
IBlueRowCollection newRows = myEvaluate((DataPacket)newValue);
|
||||
|
||||
// if (myLastValue == null)
|
||||
// myFireEvent(new DataPacket(newRows, newRows, new BlueTable(mySchema)));
|
||||
// else
|
||||
// {
|
||||
// IBlueRowCollection added, deleted;
|
||||
// BlueDataUtility.computeDifferences(newRows, ((DataPacket) myLastValue).newRows, out deleted, out added);
|
||||
// myFireEvent(new DataPacket(newRows, added, deleted));
|
||||
// }
|
||||
// }
|
||||
if (myLastValue == null)
|
||||
myFireEvent(new DataPacket(newRows, newRows, new BlueTable(mySchema)));
|
||||
else
|
||||
{
|
||||
IBlueRowCollection added, deleted;
|
||||
BlueDataUtility.computeDifferences(newRows, ((DataPacket) myLastValue).newRows, out deleted, out added);
|
||||
myFireEvent(new DataPacket(newRows, added, deleted));
|
||||
}
|
||||
}
|
||||
|
||||
// private void myBuildSchema(IBlueTableSchema schema)
|
||||
// {
|
||||
// List<ColumnInfo> columns = new List<ColumnInfo>();
|
||||
private void myBuildSchema(IBlueTableSchema schema)
|
||||
{
|
||||
List<ColumnInfo> columns = new List<ColumnInfo>();
|
||||
|
||||
// foreach (ColumnInfo ci in schema.columnInfo)
|
||||
// columns.Add(ci);
|
||||
foreach (ColumnInfo ci in schema.columnInfo)
|
||||
columns.Add(ci);
|
||||
|
||||
// columns.Add(new ColumnInfo("average_"+myColToAverage, columns.Count, typeof(double)));
|
||||
// mySchema = new BlueTableSchema("average_of_" + schema.tableName, columns.ToArray());
|
||||
// }
|
||||
columns.Add(new ColumnInfo("average_"+myColToAverage, columns.Count, typeof(double)));
|
||||
mySchema = new BlueTableSchema("average_of_" + schema.tableName, columns.ToArray());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// private IBlueRowCollection myEvaluate(DataPacket packet)
|
||||
// {
|
||||
private IBlueRowCollection myEvaluate(DataPacket packet)
|
||||
{
|
||||
|
||||
// IDictionary<string, double> colToRunningTotal = new Dictionary<string, double>();
|
||||
// IDictionary<string, int> colToCount = new Dictionary<string, int>();
|
||||
// IDictionary<string, IBlueRow> colToLastRow = new Dictionary<string, IBlueRow>();
|
||||
IDictionary<string, double> colToRunningTotal = new Dictionary<string, double>();
|
||||
IDictionary<string, int> colToCount = new Dictionary<string, int>();
|
||||
IDictionary<string, IBlueRow> colToLastRow = new Dictionary<string, IBlueRow>();
|
||||
|
||||
// foreach (IBlueRow r in packet.newRows)
|
||||
// {
|
||||
// double thisVal = Convert.ToDouble(r[myColToAverage]);
|
||||
foreach (IBlueRow r in packet.newRows)
|
||||
{
|
||||
double thisVal = Convert.ToDouble(r[myColToAverage]);
|
||||
|
||||
// string keyVal = r[myKeyColumn].ToString();
|
||||
// if (!colToCount.ContainsKey(keyVal))
|
||||
// {
|
||||
// colToRunningTotal[keyVal] = thisVal;
|
||||
// colToCount[keyVal] = 1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// colToRunningTotal[keyVal] += thisVal;
|
||||
// colToCount[keyVal] += 1;
|
||||
// }
|
||||
// colToLastRow[keyVal] = r;
|
||||
// }
|
||||
string keyVal = r[myKeyColumn].ToString();
|
||||
if (!colToCount.ContainsKey(keyVal))
|
||||
{
|
||||
colToRunningTotal[keyVal] = thisVal;
|
||||
colToCount[keyVal] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
colToRunningTotal[keyVal] += thisVal;
|
||||
colToCount[keyVal] += 1;
|
||||
}
|
||||
colToLastRow[keyVal] = r;
|
||||
}
|
||||
|
||||
// BlueTable result = new BlueTable(mySchema);
|
||||
// foreach (string key in colToCount.Keys)
|
||||
// {
|
||||
// object[] values = new object[mySchema.columnInfo.Length];
|
||||
BlueTable result = new BlueTable(mySchema);
|
||||
foreach (string key in colToCount.Keys)
|
||||
{
|
||||
object[] values = new object[mySchema.columnInfo.Length];
|
||||
|
||||
// colToLastRow[key].CopyTo(values, 0);
|
||||
// values[values.Length - 1] = packet.newRows.Count > 0 ? colToRunningTotal[key] / packet.newRows.Count : 0.0;
|
||||
// result.addRow(new BlueRow(mySchema, values));
|
||||
// }
|
||||
colToLastRow[key].CopyTo(values, 0);
|
||||
values[values.Length - 1] = packet.newRows.Count > 0 ? colToRunningTotal[key] / packet.newRows.Count : 0.0;
|
||||
result.addRow(new BlueRow(mySchema, values));
|
||||
}
|
||||
|
||||
// return result;
|
||||
// }
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
[DataStreamUserRespresentation("Average")]
|
||||
public class AverageNonIncGroupsStream : ViewStream {
|
||||
public AverageNonIncGroupsStream(ViewStream parent_stream, string inp_col_name, params string[] group_by_cols) {
|
||||
NonIncGroupByStream rs = new NonIncGroupByStream(parent_stream, () => group_by_cols,
|
||||
(g_rows) => _find_mean(inp_col_name, g_rows));
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
private List<IBlueRow> _find_mean(string inp_col_name, List<IBlueRow> g_rows) {
|
||||
IBlueRow inp_row = g_rows.ElementAt(0);
|
||||
IEnumerable<double> inp_vals = BlueDataUtility.get_colvalues<double>(g_rows, inp_col_name);
|
||||
double sum = 0.0;
|
||||
inp_vals.ToList().ForEach(d => sum += d);
|
||||
string out_col_name = $"average_{inp_col_name}";
|
||||
double average = sum / inp_vals.Count();
|
||||
IBlueTableSchema schema_out = inp_row.schema.add_column(TypeCode.Double, out_col_name);
|
||||
MutableBlueRow out_row = new MutableBlueRow(schema_out, inp_row);
|
||||
out_row.setValue(out_col_name, average);
|
||||
List<IBlueRow> rv = new List<IBlueRow>();
|
||||
rv.Add(out_row);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using ZstdSharp.Unsafe;
|
||||
|
||||
public enum GroupByBundleOp {
|
||||
Mean,
|
||||
Median,
|
||||
Mode,
|
||||
StdDev,
|
||||
Max,
|
||||
Min,
|
||||
First,
|
||||
Last,
|
||||
Sum
|
||||
}
|
||||
public class GroupByBundle {
|
||||
public readonly List<Tuple<string, GroupByBundleOp>> operations;
|
||||
|
||||
public static GroupByBundle parse(string text) {
|
||||
// text is inp_col: op, inp_col: op, inp_col:op
|
||||
List<Tuple<string, GroupByBundleOp>> rv = new List<Tuple<string, GroupByBundleOp>>();
|
||||
string[] calcs = text.Split(',');
|
||||
foreach (string c in calcs) {
|
||||
string[] toks = c.Split(':');
|
||||
string inp_col = toks[0].Trim();
|
||||
string op_txt = toks[1].Trim();
|
||||
GroupByBundleOp op = Enum.Parse<GroupByBundleOp>(op_txt, true);
|
||||
rv.Add(Tuple.Create(inp_col, op));
|
||||
}
|
||||
return new GroupByBundle(rv);
|
||||
}
|
||||
|
||||
public GroupByBundle(List<Tuple<string, GroupByBundleOp>> operations_) {
|
||||
operations = operations_;
|
||||
}
|
||||
|
||||
public static IBlueRow group_by(List<IBlueRow> rows, GroupByBundle parameters) {
|
||||
if (rows.Count() == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IBlueRow ir = rows.ElementAt(0);
|
||||
IBlueTableSchema in_schema = ir.schema;
|
||||
IBlueTableSchema out_schema = in_schema;
|
||||
IDictionary<string, Tuple<string, GroupByBundleOp>> out_col_map =
|
||||
new Dictionary<string, Tuple<string, GroupByBundleOp>>();
|
||||
foreach (var t in parameters.operations) {
|
||||
string out_col_name = $"{t.Item1}_{t.Item2}".ToLower();
|
||||
out_schema = out_schema.add_column(TypeCode.Double, out_col_name);
|
||||
out_col_map[out_col_name] = t;
|
||||
}
|
||||
MutableBlueRow or = new MutableBlueRow(out_schema, ir);
|
||||
foreach (var kv in out_col_map) {
|
||||
string out_col_name = kv.Key;
|
||||
string in_col_name = kv.Value.Item1;
|
||||
GroupByBundleOp op = kv.Value.Item2;
|
||||
IEnumerable<double> col_vals = BlueDataUtility.get_colvalues<double>(rows, in_col_name);
|
||||
double comp_res = compute_op(col_vals, op);
|
||||
or.setValue(out_col_name, comp_res);
|
||||
}
|
||||
return or;
|
||||
}
|
||||
|
||||
public static double compute_op(IEnumerable<double> col_vals, GroupByBundleOp op) {
|
||||
switch (op) {
|
||||
case GroupByBundleOp.Max:
|
||||
return col_vals.Max<double>();
|
||||
case GroupByBundleOp.Min:
|
||||
return col_vals.Min<double>();
|
||||
case GroupByBundleOp.Mean:
|
||||
return col_vals.Sum() / col_vals.Count();
|
||||
case GroupByBundleOp.Sum:
|
||||
return col_vals.Sum();
|
||||
case GroupByBundleOp.First:
|
||||
return col_vals.First();
|
||||
case GroupByBundleOp.Last:
|
||||
return col_vals.Last();
|
||||
default:
|
||||
// TODO
|
||||
Log.assert(false);
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,6 @@ namespace BCG {
|
||||
}
|
||||
|
||||
public MaxStream(ViewStream stream, string outputCol)
|
||||
: this(new AddColumnsStream(stream, "fake_col: 0"), outputCol, new string[] { "fake_col" }) { }
|
||||
: this(new AddColumnsStream(stream, "fakeCol=0"), outputCol, new string[] { "fakeCol" }) { }
|
||||
}
|
||||
}
|
||||
+15
-66
@@ -1,40 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
|
||||
using bts;
|
||||
using bts.SilverPine;
|
||||
|
||||
namespace BCG {
|
||||
[DataStreamUserRespresentation("aggregate")]
|
||||
public class NonIncGroupByStream : ViewStream {
|
||||
private class DelNonIncGroupByEvaluator : INonIncGroupByEvaluator {
|
||||
Func<string[]> _groupby_cols_func;
|
||||
Func<List<IBlueRow>, List<IBlueRow>> _evaluate_func;
|
||||
public DelNonIncGroupByEvaluator(Func<string[]> groupby_cols_func,
|
||||
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func) {
|
||||
_groupby_cols_func = groupby_cols_func;
|
||||
_evaluate_func = evaluate_func;
|
||||
}
|
||||
public IBlueRowCollection evaluate(IDictionary<int, List<IBlueRow>> grouped_rows) {
|
||||
BlueTable rv = null;
|
||||
foreach (var kv in grouped_rows) {
|
||||
List<IBlueRow> g_rows = kv.Value;
|
||||
List<IBlueRow> out_rows = _evaluate_func.Invoke(g_rows);
|
||||
if (out_rows != null && out_rows.Count > 0) {
|
||||
rv = rv ?? new BlueTable(out_rows.ElementAt(0).schema);
|
||||
}
|
||||
rv.addRows(out_rows);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public string[] get_group_by_cols() {
|
||||
return _groupby_cols_func();
|
||||
}
|
||||
|
||||
}
|
||||
namespace BCG
|
||||
{
|
||||
public class NonIncGroupByStream : ViewStream
|
||||
{
|
||||
private ViewStream _main_stream;
|
||||
private INonIncGroupByEvaluator _groupby_func;
|
||||
private BlueRowHasher _row_hasher;
|
||||
@@ -42,47 +15,24 @@ namespace BCG {
|
||||
private Stopwatch _timer = new();
|
||||
private int _n_total_fires = 0, _n_expensive_fires = 0;
|
||||
|
||||
public NonIncGroupByStream(ViewStream main_stream, INonIncGroupByEvaluator groupby_func) {
|
||||
public NonIncGroupByStream(ViewStream main_stream, INonIncGroupByEvaluator groupby_func)
|
||||
{
|
||||
_main_stream = main_stream;
|
||||
_groupby_func = groupby_func;
|
||||
_groupby_cols = _groupby_func.get_group_by_cols();
|
||||
_row_hasher = new BlueRowHasher(_groupby_cols == null ? 0 : _groupby_cols.Length);
|
||||
_row_hasher = new BlueRowHasher(_groupby_cols.Length);
|
||||
}
|
||||
|
||||
public NonIncGroupByStream(ViewStream main_stream, Func<string[]> groupby_cols_func,
|
||||
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func)
|
||||
: this(main_stream, new DelNonIncGroupByEvaluator(groupby_cols_func, evaluate_func)) { }
|
||||
|
||||
public NonIncGroupByStream(ViewStream parent_str, string groupby_col, string standard_group_by_text, string optional_sort_col = null) {
|
||||
GroupByBundle std_group_by = GroupByBundle.parse(standard_group_by_text);
|
||||
Func<string[]> groupby_cols_func = () => {
|
||||
return String.IsNullOrEmpty(groupby_col) ? null : new string[] { groupby_col };
|
||||
};
|
||||
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func = (group_rows) => {
|
||||
if (!String.IsNullOrEmpty(optional_sort_col))
|
||||
group_rows.Sort((r1, r2) => BlueDataUtility.compare_rows(r2, r1, optional_sort_col));
|
||||
IBlueRow rv = GroupByBundle.group_by(group_rows, std_group_by);
|
||||
return new IBlueRow[] { rv }.ToList();
|
||||
};
|
||||
ViewStream rs = new NonIncGroupByStream(parent_str, groupby_cols_func, evaluate_func);
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
public NonIncGroupByStream(ViewStream parent_str, string standard_group_by_text) :
|
||||
this(parent_str, String.Empty, standard_group_by_text) {
|
||||
}
|
||||
|
||||
|
||||
protected override void myOnFirstSubscriber() { _main_stream.onChange += _main_stream_onchange; }
|
||||
|
||||
protected override void myOnLastSubscriber() { _main_stream.onChange -= _main_stream_onchange; }
|
||||
|
||||
private void _main_stream_onchange(object nv) {
|
||||
private void _main_stream_onchange(object nv)
|
||||
{
|
||||
DataPacket dp = nv as DataPacket;
|
||||
///grouping together
|
||||
_timer.Restart();
|
||||
IDictionary<int, List<IBlueRow>> grouped_rows = (_groupby_cols == null || _groupby_cols.Length == 0) ?
|
||||
new Dictionary<int, List<IBlueRow>>() { { 0, dp.newRows.to_list() } } :
|
||||
BlueDataUtility.group_together(dp.newRows, _groupby_cols, ref _row_hasher);
|
||||
IDictionary<int, List<IBlueRow>> grouped_rows = BlueDataUtility.group_together (dp.newRows, _groupby_cols, ref _row_hasher);
|
||||
_timer.Stop();
|
||||
var groupElapsedMs = _timer.ElapsedMilliseconds;
|
||||
if (groupElapsedMs >= 50) {
|
||||
@@ -94,15 +44,14 @@ namespace BCG {
|
||||
IBlueRowCollection total_state = _groupby_func.evaluate(grouped_rows);
|
||||
_timer.Stop();
|
||||
var applyElapsedMs = _timer.ElapsedMilliseconds;
|
||||
_n_total_fires++;
|
||||
if (applyElapsedMs >= 50) {
|
||||
_n_total_fires++;
|
||||
if (applyElapsedMs >= 50)
|
||||
{
|
||||
_n_expensive_fires++;
|
||||
Log.DataFlow.info(
|
||||
$"Time to evaluate {grouped_rows.Count} groups {_timer.ElapsedMilliseconds}ms, ratio {_n_expensive_fires}/{_n_total_fires}");
|
||||
}
|
||||
// TODO,
|
||||
if (total_state != null)
|
||||
myFireEvent(new DataPacket(total_state, total_state, myLastValue == null ? new BlueTable(total_state.schema) : (myLastValue as DataPacket).newRows));
|
||||
}
|
||||
myFireEvent(new DataPacket(total_state, total_state, myLastValue == null ? new BlueTable(total_state.schema) : (myLastValue as DataPacket).newRows));
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
-56
@@ -1,16 +1,15 @@
|
||||
using bts;
|
||||
using bts.collections;
|
||||
|
||||
using mbts;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace BCG {
|
||||
public class NonIncJoinBookkeeper : IDisposable {
|
||||
namespace BCG
|
||||
{
|
||||
public class NonIncJoinBookkeeper : IDisposable
|
||||
{
|
||||
public Action on_new_data;
|
||||
private readonly NonIncJoinSpec _join_spec;
|
||||
private readonly int _join_position;
|
||||
@@ -27,71 +26,41 @@ namespace BCG {
|
||||
|
||||
private int[] _join_col_indices = null,
|
||||
_data_col_indices = null;
|
||||
|
||||
public NonIncJoinBookkeeper(NonIncJoinSpec the_join_spec, int join_position, int start_index_in_output, BlueRowHasher row_hasher) {
|
||||
|
||||
public NonIncJoinBookkeeper(NonIncJoinSpec the_join_spec, int join_position, int start_index_in_output, BlueRowHasher row_hasher)
|
||||
{
|
||||
_join_spec = the_join_spec;
|
||||
_join_position = join_position;
|
||||
_start_index_in_output = start_index_in_output;
|
||||
_row_hasher = row_hasher;
|
||||
_is_left_most = _join_position == 0;
|
||||
_is_tag_along = _join_spec.join_col_names.Length == 0;
|
||||
}
|
||||
|
||||
private bool _filled_missing_data = false;
|
||||
private void _fill_missing_data(DataPacket dp) {
|
||||
if (_filled_missing_data)
|
||||
return;
|
||||
Func<string[], bool> null_or_empty = (str_arr) => {
|
||||
if (str_arr == null || str_arr.Length == 0)
|
||||
return true;
|
||||
foreach (string s in str_arr) {
|
||||
if (!String.IsNullOrEmpty(s)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
Func<string[], string[]> remove_bad_cols = (col_names) => {
|
||||
HashSet<string> schema_col_map = new HashSet<string>(dp.schema.columnNames);
|
||||
List<string> cols_list = new List<string>(col_names);
|
||||
cols_list.RemoveWhere(c => !schema_col_map.Contains(c));
|
||||
return cols_list.ToArray();
|
||||
};
|
||||
if (null_or_empty(_join_spec.data_col_names)) {
|
||||
_join_spec.data_col_names = dp.schema.columnNames;
|
||||
}
|
||||
_join_spec.data_col_names = remove_bad_cols(_join_spec.data_col_names);
|
||||
if (null_or_empty(_join_spec.data_col_names)) {
|
||||
_join_spec.data_col_names = dp.schema.columnNames;
|
||||
}
|
||||
if (null_or_empty(_join_spec.projected_col_names)) {
|
||||
_join_spec.projected_col_names = _join_spec.data_col_names;
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
_join_spec.stream.onChange += _on_stream_cb;
|
||||
}
|
||||
|
||||
public void _on_stream_cb(object dp_obj) {
|
||||
Log.Gen.info($"NonIncJoinBookkeeper._on_stream_cb dp_obj: {dp_obj}");
|
||||
public void _on_stream_cb(object dp_obj)
|
||||
{
|
||||
var timer = Stopwatch.StartNew();
|
||||
DataPacket dp = (DataPacket)dp_obj;
|
||||
_fill_missing_data(dp);
|
||||
if (_schema == null) {
|
||||
if (_schema == null)
|
||||
{
|
||||
_schema = dp.schema;
|
||||
_join_col_indices = BlueDataUtility.get_column_indices(_schema, _join_spec.join_col_names);
|
||||
_data_col_indices = BlueDataUtility.get_column_indices(_schema, _join_spec.data_col_names);
|
||||
}
|
||||
|
||||
if (_is_left_most) {
|
||||
if (_is_left_most)
|
||||
{
|
||||
_row_list.Clear();
|
||||
foreach (IBlueRow r in dp.newRows)
|
||||
_row_list.Add(new Pair<int, IBlueRow>(_row_hasher.get_hash(r, _join_col_indices), r));
|
||||
} else {
|
||||
_row_list.Add(new Pair<int, IBlueRow>(_row_hasher.get_hash(r, _join_col_indices), r));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_is_tag_along)
|
||||
_solitary_row = BlueDataUtility.extractRow(dp.newRows, 0);
|
||||
else {
|
||||
else
|
||||
{
|
||||
_row_map.Clear();
|
||||
foreach (IBlueRow r in dp.newRows)
|
||||
_row_map[_row_hasher.get_hash(r, _join_col_indices)] = r;
|
||||
@@ -110,25 +79,31 @@ namespace BCG {
|
||||
|
||||
public bool is_ready { get { return _schema != null; } }
|
||||
|
||||
public void constribute_cols_to_schema(List<ColumnInfo> cis) {
|
||||
public void constribute_cols_to_schema(List<ColumnInfo> cis)
|
||||
{
|
||||
for (int i = 0; i < _join_spec.data_col_names.Length; i++)
|
||||
cis.Add(new ColumnInfo(_join_spec.projected_col_names[i], cis.Count, _schema[_join_spec.data_col_names[i]].colType));
|
||||
}
|
||||
|
||||
public List<Pair<int, IBlueRow>> get_list() { return _row_list; }
|
||||
|
||||
public void copy_master_row_to_output_row(int row_index, object[] output_row) {
|
||||
public void copy_master_row_to_output_row(int row_index, object[] output_row)
|
||||
{
|
||||
IBlueRow this_row = _row_list[row_index].second;
|
||||
BlueDataUtility.copy_to_row(this_row, _data_col_indices, output_row, _start_index_in_output);
|
||||
}
|
||||
|
||||
public void copy_matching_row_to_output_row(int row_hash, object[] output_row) {
|
||||
if (_is_tag_along) {
|
||||
public void copy_matching_row_to_output_row(int row_hash, object[] output_row)
|
||||
{
|
||||
if (_is_tag_along)
|
||||
{
|
||||
if (_solitary_row != null)
|
||||
BlueDataUtility.copy_to_row(_solitary_row, _data_col_indices, output_row, _start_index_in_output);
|
||||
else
|
||||
copy_dbnull_to_output_row(output_row);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
IBlueRow this_row = null;
|
||||
if (_row_map.TryGetValue(row_hash, out this_row))
|
||||
BlueDataUtility.copy_to_row(this_row, _data_col_indices, output_row, _start_index_in_output);
|
||||
@@ -137,7 +112,8 @@ namespace BCG {
|
||||
}
|
||||
}
|
||||
|
||||
private void copy_dbnull_to_output_row(object[] output_row) {
|
||||
private void copy_dbnull_to_output_row(object[] output_row)
|
||||
{
|
||||
for (int i = 0; i < _data_col_indices.Length; i++)
|
||||
output_row[i + _start_index_in_output] = DBNull.Value;
|
||||
}
|
||||
|
||||
@@ -3,63 +3,63 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using mbts;
|
||||
|
||||
namespace BCG {
|
||||
// this a collection of data, theres no joining logic in here
|
||||
public class NonIncJoinSpec {
|
||||
namespace BCG
|
||||
{
|
||||
public class NonIncJoinSpec
|
||||
{
|
||||
public ViewStream stream;
|
||||
// join col names are the names on which the streams are joined (for equality),
|
||||
// data col names are the names in the original stream
|
||||
// projected col names are their new names, ie if its x:l_x, then x is in the
|
||||
// data_col_names and l_x in projected cols
|
||||
public string[] join_col_names, data_col_names, projected_col_names;
|
||||
|
||||
public NonIncJoinSpec() { }
|
||||
|
||||
public NonIncJoinSpec(ViewStream the_stream, string[] the_join_col_names, string[] the_data_col_names)
|
||||
: this(the_stream, the_join_col_names, the_data_col_names, the_data_col_names) { }
|
||||
: this (the_stream, the_join_col_names, the_data_col_names, the_data_col_names)
|
||||
{ }
|
||||
|
||||
public NonIncJoinSpec(ViewStream the_stream, string[] the_join_col_names, string[] the_data_col_names, string[] the_projected_col_names) {
|
||||
public NonIncJoinSpec(ViewStream the_stream, string[] the_join_col_names, string[] the_data_col_names, string[] the_projected_col_names)
|
||||
{
|
||||
stream = the_stream;
|
||||
join_col_names = the_join_col_names;
|
||||
data_col_names = the_data_col_names;
|
||||
projected_col_names = the_projected_col_names;
|
||||
}
|
||||
|
||||
public static NonIncJoinSpec[] from_triplet(params Triplet<ViewStream, string, string>[] join_specs) {
|
||||
public static NonIncJoinSpec[] from_triplet(params Triplet<ViewStream, string, string>[] join_specs)
|
||||
{
|
||||
List<NonIncJoinSpec> rv = new List<NonIncJoinSpec>();
|
||||
foreach (Triplet<ViewStream, string, string> r in join_specs) {
|
||||
string[] keys = String.IsNullOrEmpty(r.second) ? new string[] { } : r.second.Split(' ');
|
||||
foreach (Triplet<ViewStream, string, string> r in join_specs)
|
||||
{
|
||||
string[] keys = String.IsNullOrEmpty (r.second) ? new string[] {} : r.second.Split(' ');
|
||||
string[] visible_cols = r.third.Split(' ');
|
||||
List<string> data_col_names = new List<string>(), mapped_col_names = new List<string>();
|
||||
foreach (string s in visible_cols) {
|
||||
foreach (string s in visible_cols)
|
||||
{
|
||||
string[] toks = s.Split(':');
|
||||
if (toks.Length == 1) {
|
||||
if (toks.Length == 1)
|
||||
{
|
||||
data_col_names.Add(toks[0]);
|
||||
mapped_col_names.Add(toks[0]);
|
||||
} else if (toks.Length == 2) {
|
||||
}
|
||||
else if (toks.Length == 2)
|
||||
{
|
||||
data_col_names.Add(toks[0]);
|
||||
mapped_col_names.Add(toks[1]);
|
||||
}
|
||||
}
|
||||
rv.Add(new NonIncJoinSpec(r.first, keys, data_col_names.ToArray(), mapped_col_names.ToArray()));
|
||||
rv.Add (new NonIncJoinSpec (r.first, keys, data_col_names.ToArray (), mapped_col_names.ToArray()));
|
||||
}
|
||||
return rv.ToArray();
|
||||
}
|
||||
|
||||
public override string ToString() {
|
||||
Func<string[], string> arr_txt = (a) => {
|
||||
string rv = "";
|
||||
foreach (string s in a) {
|
||||
rv += "{s} ";
|
||||
}
|
||||
rv = rv.Trim();
|
||||
return rv;
|
||||
};
|
||||
string rv = $"stream: {stream} join_col_names: {arr_txt(join_col_names)} data_col_names: {arr_txt(data_col_names)} projected_col_names: {arr_txt(projected_col_names)}";
|
||||
return rv;
|
||||
return rv.ToArray ();
|
||||
}
|
||||
}
|
||||
|
||||
//[DataStreamUserRespresentation("ninctest")]
|
||||
//public class NonIncJoinTestStream : ViewStream
|
||||
//{
|
||||
// public NonIncJoinTestStream (string key_cols, string data_cols)
|
||||
// {
|
||||
// NonIncJoinSpec.from_triplet(new Triplet<ViewStream, string, string>(null, key_cols, data_cols));
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -6,9 +6,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace BCG {
|
||||
namespace BCG
|
||||
{
|
||||
[DataStreamUserRespresentation("fastJoin")]
|
||||
public class NonIncJoinStream : ViewStream, BCG.Utilities.General.IWorker {
|
||||
public class NonIncJoinStream : ViewStream, BCG.Utilities.General.IWorker
|
||||
{
|
||||
private readonly NonIncJoinSpec[] _join_specs;
|
||||
private readonly INonIncJoinInlineMapper _output_mapper;
|
||||
private readonly BlueRowHasher _row_hasher;
|
||||
@@ -26,19 +28,24 @@ namespace BCG {
|
||||
{
|
||||
new Triplet<ViewStream, string, string> (left, left_join_cols, left_proj),
|
||||
new Triplet<ViewStream, string, string> (right, right_join_cols, right_proj)
|
||||
}) { }
|
||||
})
|
||||
{ }
|
||||
|
||||
public NonIncJoinStream(params Triplet<ViewStream, string, string>[] join_specs)
|
||||
: this(NonIncJoinSpec.from_triplet(join_specs), null, 0) { }
|
||||
: this(NonIncJoinSpec.from_triplet(join_specs), null, 0)
|
||||
{ }
|
||||
|
||||
public NonIncJoinStream(ViewStreamDatabase vsd, INonIncJoinInlineMapper output_mapper, int throttles_ms,
|
||||
params Triplet<ViewStream, string, string>[] join_specs)
|
||||
: this(vsd, NonIncJoinSpec.from_triplet(join_specs), output_mapper, throttles_ms) { }
|
||||
: this(vsd, NonIncJoinSpec.from_triplet(join_specs), output_mapper, throttles_ms)
|
||||
{ }
|
||||
|
||||
public NonIncJoinStream(NonIncJoinSpec[] join_specs, INonIncJoinInlineMapper output_mapper, int throttles_ms = 0)
|
||||
: this(ViewStreamDatabase.instance, join_specs, output_mapper, throttles_ms) { }
|
||||
: this(ViewStreamDatabase.instance, join_specs, output_mapper, throttles_ms)
|
||||
{ }
|
||||
|
||||
public NonIncJoinStream(ViewStreamDatabase vsd, NonIncJoinSpec[] join_specs, INonIncJoinInlineMapper output_mapper, int throttles_ms = 0) {
|
||||
public NonIncJoinStream(ViewStreamDatabase vsd, NonIncJoinSpec[] join_specs, INonIncJoinInlineMapper output_mapper, int throttles_ms = 0)
|
||||
{
|
||||
_join_specs = join_specs;
|
||||
_output_mapper = output_mapper;
|
||||
_row_hasher = new BlueRowHasher(_join_specs[0].join_col_names.Length);
|
||||
@@ -46,11 +53,12 @@ namespace BCG {
|
||||
_vsd = vsd;
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
protected override void myOnFirstSubscriber()
|
||||
{
|
||||
int data_col_no = 1;
|
||||
for (int jp = 0; jp < _join_specs.Length; jp++) {
|
||||
for (int jp = 0; jp < _join_specs.Length; jp++)
|
||||
{
|
||||
NonIncJoinBookkeeper s = new NonIncJoinBookkeeper(_join_specs[jp], jp, data_col_no, _row_hasher);
|
||||
Log.Gen.info($"NonIncJoinStream.myOnFirstSubscriber jp: {jp} spec: {_join_specs[jp]}");
|
||||
data_col_no += _join_specs[jp].data_col_names.Length;
|
||||
s.on_new_data += _stream_callback;
|
||||
_book_keeping_data.Add(s);
|
||||
@@ -58,11 +66,10 @@ namespace BCG {
|
||||
if (_output_mapper != null)
|
||||
_output_mapper.onMapperChange += _on_mapper_change;
|
||||
_vsd.addWorker(this);
|
||||
foreach (var bkd in _book_keeping_data)
|
||||
bkd.init();
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
protected override void myOnLastSubscriber()
|
||||
{
|
||||
foreach (NonIncJoinBookkeeper d in _book_keeping_data)
|
||||
d.Dispose();
|
||||
if (_output_mapper != null)
|
||||
@@ -70,26 +77,30 @@ namespace BCG {
|
||||
_vsd.removeWorker(this);
|
||||
}
|
||||
|
||||
private void _stream_callback() {
|
||||
Log.Gen.info("NonIncJoinStream._stream_callback received callback");
|
||||
private void _stream_callback()
|
||||
{
|
||||
_is_dirty = true;
|
||||
doWork();
|
||||
}
|
||||
|
||||
private void _on_mapper_change() {
|
||||
private void _on_mapper_change()
|
||||
{
|
||||
_is_dirty = true;
|
||||
doWork();
|
||||
}
|
||||
|
||||
private bool _is_ready() {
|
||||
private bool _is_ready()
|
||||
{
|
||||
bool rv = true;
|
||||
foreach (NonIncJoinBookkeeper d in _book_keeping_data)
|
||||
rv &= d.is_ready;
|
||||
return rv;
|
||||
}
|
||||
|
||||
private void _construct_schema() {
|
||||
if (_output_schema == null) {
|
||||
private void _construct_schema()
|
||||
{
|
||||
if (_output_schema == null)
|
||||
{
|
||||
List<ColumnInfo> cis = new List<ColumnInfo>(new ColumnInfo[] { new ColumnInfo("id", 0, typeof(int)) });
|
||||
foreach (NonIncJoinBookkeeper d in _book_keeping_data)
|
||||
d.constribute_cols_to_schema(cis);
|
||||
@@ -98,23 +109,27 @@ namespace BCG {
|
||||
}
|
||||
|
||||
private int _n_total_fires = 0, _n_expensive_fires = 0;
|
||||
private void _form_and_fire() {
|
||||
Log.Gen.info($"NonIncJoinStream._form_and_fire _is_ready(): {_is_ready()}");
|
||||
if (_is_ready()) {
|
||||
private void _form_and_fire()
|
||||
{
|
||||
if (_is_ready())
|
||||
{
|
||||
_construct_schema();
|
||||
var timer = Stopwatch.StartNew();
|
||||
IList<Pair<int, IBlueRow>> left_row_list = _book_keeping_data[0].get_list();
|
||||
List<object[]> output_rows = new List<object[]>();
|
||||
|
||||
for (int i = 0; i < left_row_list.Count; i++) {
|
||||
for (int i = 0; i < left_row_list.Count; i++)
|
||||
{
|
||||
object[] or = new object[_output_schema.columnInfo.Length];
|
||||
or[0] = i;
|
||||
output_rows.Add(or);
|
||||
}
|
||||
|
||||
for (int ji = 0; ji < _book_keeping_data.Count; ji++) {
|
||||
for (int ji = 0; ji < _book_keeping_data.Count; ji++)
|
||||
{
|
||||
NonIncJoinBookkeeper bk_data = _book_keeping_data[ji];
|
||||
for (int i = 0; i < left_row_list.Count; i++) {
|
||||
for (int i = 0; i < left_row_list.Count; i++)
|
||||
{
|
||||
if (ji == 0)
|
||||
bk_data.copy_master_row_to_output_row(i, output_rows[i]);
|
||||
else
|
||||
@@ -124,20 +139,19 @@ namespace BCG {
|
||||
IBlueRowCollection dp_output_rows = _apply_map(new SequentialIDBlueTable(_output_schema, output_rows));
|
||||
timer.Stop();
|
||||
_n_total_fires++;
|
||||
//if (timer.ElapsedMilliseconds >= 250) {
|
||||
_n_expensive_fires++;
|
||||
string log_msg = $"Join and map time for {_book_keeping_data.Count} "
|
||||
+ $"tables {timer.Elapsed.TotalMilliseconds} msecs, ratio {_n_expensive_fires}/{_n_total_fires}";
|
||||
Log.Gen.info(log_msg);
|
||||
//}
|
||||
var dp_out = BlueDataUtility.build_dp_inc(dp_output_rows, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
//myFireEvent(new DataPacket(dp_output_rows, dp_output_rows, myLastValue == null ? new BlueTable(_output_schema) : (myLastValue as DataPacket).newRows));
|
||||
if (timer.ElapsedMilliseconds >= 250) {
|
||||
_n_expensive_fires++;
|
||||
string log_msg = $"Join and map time for {_book_keeping_data.Count} "
|
||||
+ $"tables {timer.Elapsed} ratio {_n_expensive_fires}/{_n_total_fires}";
|
||||
}
|
||||
myFireEvent(new DataPacket(dp_output_rows, dp_output_rows, myLastValue == null ? new BlueTable(_output_schema) : (myLastValue as DataPacket).newRows));
|
||||
}
|
||||
}
|
||||
|
||||
private IBlueRowCollection _apply_map(IBlueRowCollection unmapped_rows) {
|
||||
if (_output_mapper != null) {
|
||||
private IBlueRowCollection _apply_map(IBlueRowCollection unmapped_rows)
|
||||
{
|
||||
if (_output_mapper != null)
|
||||
{
|
||||
IBlueRowCollection output_rows;
|
||||
var timer = Stopwatch.StartNew();
|
||||
output_rows = _output_mapper.map_rows(unmapped_rows);
|
||||
@@ -146,14 +160,17 @@ namespace BCG {
|
||||
Log.Gen.info($"Time to map {unmapped_rows.Count} rows into {output_rows.Count} rows {timer.Elapsed}");
|
||||
}
|
||||
return output_rows;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return unmapped_rows;
|
||||
}
|
||||
}
|
||||
|
||||
public void doWork() {
|
||||
Log.Gen.info($"NonIncJoinStream.doWork _last_fire_time: {_last_fire_time} _is_dirty: {_is_dirty}");
|
||||
if (DateTime.Now - _last_fire_time >= _throttle_period && _is_dirty) {
|
||||
public void doWork()
|
||||
{
|
||||
if (DateTime.Now - _last_fire_time >= _throttle_period && _is_dirty)
|
||||
{
|
||||
_is_dirty = false;
|
||||
_last_fire_time = DateTime.Now;
|
||||
_form_and_fire();
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
namespace bts {
|
||||
using BCG;
|
||||
using BCG.Utilities.General;
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using ZstdSharp.Unsafe;
|
||||
|
||||
// functon that joins the 2 rows and returns the outputput row. The function
|
||||
// can return a null which means the 2 rows dont need to be joined
|
||||
using JoinFunc = System.Func<BCG.IBlueRow, BCG.IBlueRow, BCG.IBlueRow>;
|
||||
public class ProximityJoinStream : ViewStream, IWorker {
|
||||
private ViewStream _lvs, _rvs;
|
||||
private JoinFunc _join_func;
|
||||
private bool _dirty = false;
|
||||
private Stopwatch _stopwatch = new Stopwatch();
|
||||
private ViewStreamDatabase _vsd = ViewStreamDatabase.instance;
|
||||
public ProximityJoinStream(ViewStream lvs, ViewStream rvs, JoinFunc join_func) {
|
||||
_lvs = lvs;
|
||||
_rvs = rvs;
|
||||
_join_func = join_func;
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_lvs.onChange += _handle_data;
|
||||
_rvs.onChange += _handle_data;
|
||||
_vsd.addWorker(this);
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
_lvs.onChange -= _handle_data;
|
||||
_rvs.onChange -= _handle_data;
|
||||
_vsd.removeWorker(this);
|
||||
}
|
||||
|
||||
private void _handle_data(object dp_obj) {
|
||||
_dirty = true;
|
||||
doWork();
|
||||
}
|
||||
|
||||
public void doWork() {
|
||||
Func<bool> all_data_revcd = () => {
|
||||
return _lvs.rows != null && _rvs.rows != null;
|
||||
};
|
||||
_stopwatch.Start();
|
||||
if (_dirty && all_data_revcd()) {
|
||||
_dirty = false;
|
||||
BlueTable rv = null;
|
||||
foreach (IBlueRow lr in _lvs.rows) {
|
||||
foreach (IBlueRow rr in _rvs.rows) {
|
||||
IBlueRow resr = _join_func(lr, rr);
|
||||
if (resr == null)
|
||||
continue;
|
||||
rv = rv ?? new BlueTable(resr.schema);
|
||||
rv.addRow(resr);
|
||||
}
|
||||
}
|
||||
_stopwatch.Stop();
|
||||
Log.Gen.info($"ProximityJoinStream left_count: {_lvs.rows.Count} right_count: {_rvs.rows.Count} result_count: {rv.Count} time: {_stopwatch.ElapsedMilliseconds} msecs");
|
||||
var dp = BlueDataUtility.build_dp_inc(rv, myLastValue as DataPacket);
|
||||
myFireEvent(dp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Configuration;
|
||||
using System.Reactive.Disposables;
|
||||
|
||||
public class TimeProximityJoinStream : ViewStream {
|
||||
private int _id = 0;
|
||||
|
||||
public TimeProximityJoinStream(ViewStream ls, string l_time_col, ViewStream rs, string r_time_col,
|
||||
string pre_join_period, string post_join_period) :
|
||||
this(ls, l_time_col, rs, r_time_col, TimeBasedFilter.parse_duration(pre_join_period),
|
||||
TimeBasedFilter.parse_duration(post_join_period)) { }
|
||||
|
||||
|
||||
public TimeProximityJoinStream(ViewStream ls, string l_time_col, ViewStream rs, string r_time_col,
|
||||
TimeSpan pre_join_period, TimeSpan post_join_period) {
|
||||
Func<IBlueRow, IBlueRow, IBlueRow> create_row = (lr, rr) => {
|
||||
var id = 0;
|
||||
lock (this) {
|
||||
id = _id++;
|
||||
}
|
||||
IBlueRow rv = BlueDataUtility.create_composite_row(lr, rr, id);
|
||||
return rv;
|
||||
};
|
||||
Func<IBlueRow, IBlueRow, IBlueRow> join_func = (lr, rr) => {
|
||||
DateTime ldt = lr.get_datetime(l_time_col);
|
||||
DateTime rdt = rr.get_datetime(r_time_col);
|
||||
TimeSpan diff = ldt - rdt;
|
||||
if (ldt < rdt) {
|
||||
if (diff.Duration() > pre_join_period) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (diff > post_join_period)
|
||||
return null;
|
||||
}
|
||||
return create_row(lr, rr);
|
||||
};
|
||||
|
||||
ViewStream rstr = new ProximityJoinStream(ls, rs, join_func);
|
||||
mySetRealSource(rstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,9 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Amazon.Runtime.Internal.Util;
|
||||
|
||||
using BCG;
|
||||
using BCG.Utilities;
|
||||
|
||||
using bts;
|
||||
|
||||
namespace BCG {
|
||||
public class LiteralStream : ViewStream {
|
||||
|
||||
@@ -26,34 +22,6 @@ namespace BCG {
|
||||
return rv;
|
||||
}
|
||||
|
||||
//literal("table1", "x:123, y:1.001, z:abc;x:123, y:1.001, z:abc")
|
||||
public LiteralStream(string table_name, string rows) {
|
||||
Func<string, int, IBlueRow> get_row = (json_row, id) => {
|
||||
Dictionary<string, object> map = new Dictionary<string, object>();
|
||||
string[] toks = json_row.Split(',', StringSplitOptions.TrimEntries);
|
||||
//Logger.assert(col_vals.Length == 2);
|
||||
foreach (string t in toks) {
|
||||
var col_vals = t.Split(':', StringSplitOptions.TrimEntries);
|
||||
string col = col_vals[0];
|
||||
string val = col_vals[1];
|
||||
map.Add(col, val);
|
||||
}
|
||||
map["id"] = id;
|
||||
return new BlueRow(map);
|
||||
};
|
||||
string[] row_arr = rows.Split(';', StringSplitOptions.TrimEntries);
|
||||
BlueTable table = null;
|
||||
foreach (string json_string in row_arr) {
|
||||
IBlueRow r = //BlueDataUtility.convert_json_to_row(json_string, table == null ? 0 : table.Count);
|
||||
get_row(json_string, table == null ? 0 : table.Count);
|
||||
table = table ?? new BlueTable(r.schema);
|
||||
table.addRow(r);
|
||||
}
|
||||
ViewStream str = new BlueTableStream(table);
|
||||
str = new SchemaGuesserStream(str);
|
||||
mySetRealSource(str);
|
||||
}
|
||||
|
||||
public LiteralStream(string tableName, string schema, string value) {
|
||||
string[] columns = schema.Split(' ');
|
||||
|
||||
@@ -87,7 +55,7 @@ namespace BCG {
|
||||
mySetRealSource(new BlueRowCollectionStaticStream(t));
|
||||
}
|
||||
|
||||
// public LiteralStream(string schema, string value) : this("literal", schema, value) { }
|
||||
public LiteralStream(string schema, string value) : this("literal", schema, value) { }
|
||||
|
||||
// public LiteralStream(string value) {
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
using BCG;
|
||||
|
||||
using MongoDB.Driver.Core.WireProtocol.Messages;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
// the first arg is all the rows, the second arg is the index of the row that needs mapping, and
|
||||
// the func returns the mapped row (ie mapped version of the index row)
|
||||
using GlobalMap = System.Func<System.Collections.Generic.List<BCG.IBlueRow>, uint, BCG.IBlueRow>;
|
||||
|
||||
namespace bts {
|
||||
// In GlobalMap, each row is mapped with the full view of all rows, ie the map functions for a row
|
||||
// can use the state fo all rows.
|
||||
public class GlobalMapStream : ViewStream {
|
||||
private ViewStream _base_stream;
|
||||
private readonly string _sort_col_name, _group_by_col;
|
||||
private GlobalMap _map_func;
|
||||
public GlobalMapStream(ViewStream base_stream, string sort_col_name, string group_by_col, GlobalMap map_func) {
|
||||
_base_stream = base_stream;
|
||||
_sort_col_name = sort_col_name;
|
||||
_group_by_col = group_by_col;
|
||||
_map_func = map_func;
|
||||
}
|
||||
|
||||
public GlobalMapStream(ViewStream base_stream, string sort_col_name, GlobalMap map_func) :
|
||||
this(base_stream, sort_col_name, null, map_func) {
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_base_stream.onChange += _handle_stream_update;
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
_base_stream.onChange -= _handle_stream_update;
|
||||
}
|
||||
|
||||
void _handle_stream_update(object dp_obj) {
|
||||
DataPacket dp = dp_obj as DataPacket;
|
||||
IDictionary<int, List<IBlueRow>> groups = !String.IsNullOrEmpty(_group_by_col) ?
|
||||
BlueDataUtility.group_together(dp.newRows, new string[] { _group_by_col })
|
||||
:
|
||||
new Dictionary<int, List<IBlueRow>>() { { 0, dp.newRows.to_list() } };
|
||||
BlueTable out_table = null;
|
||||
foreach (var kv in groups) {
|
||||
List<IBlueRow> group_rows = kv.Value;
|
||||
group_rows.Sort((r1, r2) => BlueDataUtility.compare_rows(r2, r1, _sort_col_name));
|
||||
uint i = 0;
|
||||
foreach (IBlueRow r in group_rows) {
|
||||
IBlueRow nr = _map_func(group_rows, i++);
|
||||
out_table = out_table ?? new BlueTable(nr.schema);
|
||||
out_table.addRow(nr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// List<IBlueRow> rows = dp.newRows.to_ienum().ToList();
|
||||
// rows.Sort((r1, r2) => BlueDataUtility.compare_rows(r1, r2, _sort_col_name));
|
||||
// uint i = 0;
|
||||
|
||||
// BlueTable out_table = null;
|
||||
// foreach (IBlueRow r in rows) {
|
||||
// IBlueRow nr = _map_func(rows, i++);
|
||||
// out_table = out_table ?? new BlueTable(nr.schema);
|
||||
// out_table.addRow(nr);
|
||||
// }
|
||||
DataPacket dp_out = BlueDataUtility.build_dp_inc(out_table, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,6 +158,10 @@ namespace bts
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
|
||||
private string _get_next_id() {
|
||||
return _table.Count.ToString();
|
||||
}
|
||||
|
||||
private string _get_next_id()
|
||||
{
|
||||
return _table.Count.ToString();
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using System;
|
||||
using BCG.Utilities.General;
|
||||
|
||||
using BCG;
|
||||
|
||||
namespace bts.SilverPine {
|
||||
namespace BCG {
|
||||
// Keeps adding changing rows to the stream, hence preserving the history
|
||||
// and creating a time series, for example this can be used to make bbo updates
|
||||
// into a time series of prices/qty
|
||||
@@ -40,6 +41,7 @@ namespace bts.SilverPine {
|
||||
}
|
||||
_table.addRows(added_rows);
|
||||
myFireEvent(new DataPacket(_table, added_rows, new BlueTable(_table.schema)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,24 +137,10 @@ namespace bts {
|
||||
HashSet<string> removed_cols = new HashSet<string>();
|
||||
Dictionary<string, string> mapped_to_orig_map = new Dictionary<string, string>();
|
||||
Dictionary<string, string> orig_to_mapped = new Dictionary<string, string>();
|
||||
// by default every col will show up, so if we have the projection as (a:a1)
|
||||
// it will convert a to a1,
|
||||
// examples: if a schema has cols a b c
|
||||
// project(parent_str, "a:aa ") -> aa b c
|
||||
// project(parent_str, "a:aa !c") -> aa b
|
||||
// project(parent_str, "a:aa !") -> aa
|
||||
// project(parent_str, "a:aa b = (aa*aa)!") -> aa b
|
||||
bool hide_all = false;
|
||||
foreach (string p_tok in project_toks) {
|
||||
if (p_tok.StartsWith("!")) {
|
||||
if (p_tok.Length == 1) {
|
||||
// if it is a "blanket "!"=> hide all cols except the one that
|
||||
// are stated explicitly
|
||||
hide_all = true;
|
||||
} else {
|
||||
string removed_col = p_tok.Substring(1);
|
||||
removed_cols.Add(removed_col);
|
||||
}
|
||||
string removed_col = p_tok.Substring(1);
|
||||
removed_cols.Add(removed_col);
|
||||
} else if (p_tok.Contains(":")) {
|
||||
string[] map_toks = p_tok.Split(":");
|
||||
string orig_col = map_toks[0];
|
||||
@@ -169,11 +155,12 @@ namespace bts {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make the new schema
|
||||
List<ColumnInfo> new_cols = new List<ColumnInfo>();
|
||||
foreach (ColumnInfo ci in input_schema.columnInfo) {
|
||||
if (ci.colName == "id") {
|
||||
// if there's a hidden col, other columns will show by default, but if cols are being
|
||||
// projected epxlicitely, than others wil be hidden
|
||||
ColumnInfo nc = new ColumnInfo(ci.colName, new_cols.Count, ci.colType);
|
||||
new_cols.Add(nc);
|
||||
continue;
|
||||
@@ -185,13 +172,12 @@ namespace bts {
|
||||
ColumnInfo nc = new ColumnInfo(mapped_name, new_cols.Count, ci.colType);
|
||||
new_cols.Add(nc);
|
||||
} else {
|
||||
if (hide_all)
|
||||
continue;
|
||||
//if (ci.colName == "id" || removed_cols.Count > 0) {
|
||||
// unless columns are explicitely hidden, all columns show up
|
||||
ColumnInfo nc = new ColumnInfo(ci.colName, new_cols.Count, ci.colType);
|
||||
new_cols.Add(nc);
|
||||
//}
|
||||
if (ci.colName == "id" || removed_cols.Count > 0) {
|
||||
// if there's a hidden col, other columns will show by default, but if cols are being
|
||||
// projected epxlicitely, than others wil be hidden
|
||||
ColumnInfo nc = new ColumnInfo(ci.colName, new_cols.Count, ci.colType);
|
||||
new_cols.Add(nc);
|
||||
}
|
||||
}
|
||||
}
|
||||
IBlueTableSchema new_schema = new BlueTableSchema(input_schema.tableName, new_cols.ToArray());
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SQLite;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
using BCG;
|
||||
using System.Linq;
|
||||
using System.Data.Entity;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SQLite;
|
||||
|
||||
|
||||
namespace bts.SilverPine {
|
||||
|
||||
public static class SQLiteHelper {
|
||||
public static string location = "C:\\Users\\m_tah\\development\\data\\";
|
||||
public static string db_name = "stream_data.db";
|
||||
|
||||
public static DataTable execute_select_query(string connection_string, string query) {
|
||||
// Create a new DataTable to store the results
|
||||
DataTable dataTable = new DataTable();
|
||||
|
||||
// Create and open a SQLite connection using the provided connection string
|
||||
using (SQLiteConnection connection = new SQLiteConnection(connection_string)) {
|
||||
try {
|
||||
connection.Open();
|
||||
|
||||
// Create a SQLite command with the provided query
|
||||
using (SQLiteCommand command = new SQLiteCommand(query, connection)) {
|
||||
// Use SQLiteDataAdapter to fill the DataTable
|
||||
using (SQLiteDataAdapter adapter = new SQLiteDataAdapter(command)) {
|
||||
adapter.Fill(dataTable);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Console.WriteLine("An error occurred: " + ex.Message);
|
||||
}
|
||||
}
|
||||
// Return the populated DataTable
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
public static List<Dictionary<string, object>> ExecuteBulkRead(string connectionString, string query) {
|
||||
var result = new List<Dictionary<string, object>>();
|
||||
|
||||
using (var connection = new SQLiteConnection(connectionString)) {
|
||||
connection.Open();
|
||||
|
||||
// Begin a transaction to optimize read speed
|
||||
using (var transaction = connection.BeginTransaction())
|
||||
using (var command = new SQLiteCommand(query, connection, transaction))
|
||||
using (var reader = command.ExecuteReader()) {
|
||||
while (reader.Read()) {
|
||||
var row = new Dictionary<string, object>();
|
||||
|
||||
for (int i = 0; i < reader.FieldCount; i++) {
|
||||
string columnName = reader.GetName(i);
|
||||
object columnValue = reader.IsDBNull(i) ? null : reader.GetValue(i);
|
||||
row[columnName] = columnValue;
|
||||
}
|
||||
|
||||
result.Add(row);
|
||||
}
|
||||
|
||||
// Commit the transaction
|
||||
transaction.Commit();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<Dictionary<string, object>> get_table(string connectionString, string query) {
|
||||
var result = new List<Dictionary<string, object>>();
|
||||
|
||||
using (var connection = new SQLiteConnection(connectionString)) {
|
||||
try {
|
||||
connection.Open();
|
||||
|
||||
using (var command = new SQLiteCommand(query, connection))
|
||||
using (var reader = command.ExecuteReader()) {
|
||||
while (reader.Read()) {
|
||||
var row = new Dictionary<string, object>();
|
||||
|
||||
for (int i = 0; i < reader.FieldCount; i++) {
|
||||
string columnName = reader.GetName(i);
|
||||
object columnValue = reader.IsDBNull(i) ? null : reader.GetValue(i);
|
||||
row[columnName] = columnValue;
|
||||
}
|
||||
|
||||
result.Add(row);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Console.WriteLine("An error occurred: " + ex.Message);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IEnumerable<Dictionary<string, object>> get_table_2(string connectionString, string query) {
|
||||
using (var connection = new SQLiteConnection(connectionString)) {
|
||||
connection.Open();
|
||||
using (var command = new SQLiteCommand(query, connection))
|
||||
using (var reader = command.ExecuteReader()) {
|
||||
while (reader.Read()) {
|
||||
var row = new Dictionary<string, object>();
|
||||
for (int i = 0; i < reader.FieldCount; i++) {
|
||||
string columnName = reader.GetName(i);
|
||||
object columnValue = reader.IsDBNull(i) ? null : reader.GetValue(i);
|
||||
row[columnName] = columnValue;
|
||||
}
|
||||
yield return row;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SQLite;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
|
||||
|
||||
using BCG;
|
||||
|
||||
[DataStreamUserRespresentation("SQLite")]
|
||||
public class SQLiteStream : ViewStream {
|
||||
private readonly string _connection_string, _query;
|
||||
private Stopwatch _stopwatch = new Stopwatch();
|
||||
|
||||
private SQLiteStream(string connection_string, string query, bool noop) {
|
||||
_connection_string = connection_string;
|
||||
_query = query;
|
||||
}
|
||||
|
||||
public SQLiteStream(string db_name, string query)
|
||||
:
|
||||
this($"Data Source={SQLiteHelper.location}{db_name};Version=3", query, true) { }
|
||||
|
||||
public SQLiteStream(string query)
|
||||
:
|
||||
this(SQLiteHelper.db_name, query) {
|
||||
}
|
||||
|
||||
|
||||
private void _read_from_sqlite_and_fire() {
|
||||
_stopwatch.Start();
|
||||
DataTable dt = SQLiteHelper.execute_select_query(_connection_string, _query);
|
||||
_stopwatch.Stop();
|
||||
Log.Gen.info($"SQLiteStream.ExecuteSelectQuery time to read db: {_stopwatch.ElapsedMilliseconds} msecs");
|
||||
_stopwatch.Restart();
|
||||
#region perf measures
|
||||
// SQLiteHelper.get_table(_connection_string, _query);
|
||||
// _stopwatch.Stop();
|
||||
// Log.Gen.info($"SQLiteStream.get_table time to read db: {_stopwatch.ElapsedMilliseconds} msecs");
|
||||
// _stopwatch.Restart();
|
||||
// SQLiteHelper.ExecuteBulkRead(_connection_string, _query);
|
||||
// _stopwatch.Stop();
|
||||
// Log.Gen.info($"SQLiteStream.ExecuteBulkRead time to read db: {_stopwatch.ElapsedMilliseconds} msecs");
|
||||
// _stopwatch.Restart();
|
||||
// SQLiteHelper.get_table_2(_connection_string, _query);
|
||||
// _stopwatch.Stop();
|
||||
// Log.Gen.info($"SQLiteStream.get_table_2 time to read db: {_stopwatch.ElapsedMilliseconds} msecs");
|
||||
// _stopwatch.Restart();
|
||||
#endregion
|
||||
IBlueRowCollection rows = BCG.BlueDataUtility.toIBlueRowCollection(dt);
|
||||
//IBlueRowCollection rows = new DataTableWrapperTable(dt);
|
||||
_stopwatch.Stop();
|
||||
Log.Gen.info($"SQLiteStream._read_from_sqlite_and_fire time to load into IBlueRowCollection: {_stopwatch.ElapsedMilliseconds} msecs");
|
||||
DataPacket dp = BlueDataUtility.build_dp_inc(rows, myLastValue as DataPacket);
|
||||
myFireEvent(dp);
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_read_from_sqlite_and_fire();
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
// this value will be cleared by the base class
|
||||
// but in this particular stream this behaviour
|
||||
// is not usefull since any new subscribers
|
||||
// would force the query to be recreated
|
||||
//myLastDP = myLastValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,15 +3,12 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using BCG.Utilities;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Data.Analysis;
|
||||
using Parquet;
|
||||
using Parquet.Data;
|
||||
|
||||
|
||||
namespace BCG {
|
||||
namespace BCG
|
||||
{
|
||||
[DataStreamUserRespresentation("CSVSaver")]
|
||||
public class CSVSaverStream : ViewStream, ISideEffectStream {
|
||||
public class CSVSaverStream : ViewStream, ISideEffectStream
|
||||
{
|
||||
private IBlueTableSchema myResultSchema = new BlueTableSchema("CSVResult", new ColumnInfo("id", 0, typeof(int)),
|
||||
new ColumnInfo("fileName", 1, typeof(string)),
|
||||
new ColumnInfo("nWrites", 2, typeof(int)),
|
||||
@@ -23,9 +20,11 @@ namespace BCG {
|
||||
private int myNWrites = 0, myNMaxWrites = Int32.MaxValue;
|
||||
|
||||
public CSVSaverStream(ViewStream vs, string fullyQualifiedFileName)
|
||||
: this(vs, fullyQualifiedFileName, true, Int32.MaxValue, false) { }
|
||||
: this(vs, fullyQualifiedFileName, true, Int32.MaxValue, false)
|
||||
{ }
|
||||
|
||||
public CSVSaverStream(ViewStream vs, string fullyQualifiedFileName, bool overwrite, int nMaxWrites, bool fireResultSnapshot) {
|
||||
public CSVSaverStream(ViewStream vs, string fullyQualifiedFileName, bool overwrite, int nMaxWrites, bool fireResultSnapshot)
|
||||
{
|
||||
myStream = vs;
|
||||
myFullyQualifiedFileName = fullyQualifiedFileName;
|
||||
myOverwrite = overwrite;
|
||||
@@ -37,14 +36,18 @@ namespace BCG {
|
||||
|
||||
protected override void myOnLastSubscriber() { myStream.onChange -= new ChangeDelegate(myHandleChanges); }
|
||||
|
||||
private void myHandleChanges(object newValue) {
|
||||
private void myHandleChanges(object newValue)
|
||||
{
|
||||
IBlueRowCollection totalState = (newValue as DataPacket).newRows;
|
||||
if (totalState.Count > 0 && myNWrites < myNMaxWrites) {
|
||||
if (totalState.Count > 0 && myNWrites < myNMaxWrites)
|
||||
{
|
||||
myNWrites++;
|
||||
int i = 0;
|
||||
StreamWriter writer = new StreamWriter(new FileStream(myGetNewFileName(), FileMode.Create, FileAccess.Write));
|
||||
foreach (IBlueRow r in totalState) {
|
||||
if (i++ == 0) {
|
||||
foreach (IBlueRow r in totalState)
|
||||
{
|
||||
if (i++ == 0)
|
||||
{
|
||||
string header = String.Empty;
|
||||
foreach (string col in r.schema.columnNames)
|
||||
if (col != "id")
|
||||
@@ -56,17 +59,20 @@ namespace BCG {
|
||||
writer.Flush();
|
||||
}
|
||||
writer.Close();
|
||||
if (myFireResultSnapshot) {
|
||||
if (myFireResultSnapshot)
|
||||
{
|
||||
IBlueRow nr = new BlueRow(myResultSchema, 0, myFullyQualifiedFileName, myNWrites, totalState.Count);
|
||||
BlueTable nRows = new BlueTable(myResultSchema);
|
||||
nRows.addRow(nr);
|
||||
myFireEvent(new DataPacket(nRows, nRows, new BlueTable(myLastValue == null ? new BlueTable(myResultSchema) : (myLastValue as DataPacket).newRows)));
|
||||
} else
|
||||
}
|
||||
else
|
||||
myFireEvent(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
private string myGetNewFileName() {
|
||||
private string myGetNewFileName()
|
||||
{
|
||||
string[] tags = myFullyQualifiedFileName.Split('.');
|
||||
if (myOverwrite)
|
||||
return tags[0] + ".csv";
|
||||
@@ -74,11 +80,14 @@ namespace BCG {
|
||||
return tags[0] + "_" + myFormateDateTime(DateTime.Now) + ".csv";
|
||||
}
|
||||
|
||||
private static string myGetCSVRow(IBlueRow r) {
|
||||
private static string myGetCSVRow(IBlueRow r)
|
||||
{
|
||||
string rv = String.Empty;
|
||||
int i = 0;
|
||||
foreach (string col in r.schema.columnNames) {
|
||||
if (col != "id") {
|
||||
foreach (string col in r.schema.columnNames)
|
||||
{
|
||||
if (col != "id")
|
||||
{
|
||||
string colText = String.Empty;
|
||||
if (r[col] != null && r[col] != DBNull.Value)
|
||||
colText = r[col].ToString();
|
||||
@@ -90,7 +99,8 @@ namespace BCG {
|
||||
return rv;
|
||||
}
|
||||
|
||||
private string myFormateDateTime(DateTime dt) {
|
||||
private string myFormateDateTime(DateTime dt)
|
||||
{
|
||||
return
|
||||
string.Format("{0}-{1}-{2}-{3}-{4}-{5}-{6}",
|
||||
dt.Year.ToString("0000"),
|
||||
@@ -104,49 +114,52 @@ namespace BCG {
|
||||
}
|
||||
|
||||
[DataStreamUserRespresentation("CSVReader")]
|
||||
public class CSVReaderStream : ViewStream {
|
||||
private readonly string _file_address;
|
||||
Stopwatch _stopwatch = new Stopwatch();
|
||||
public CSVReaderStream(string fileAddress) {
|
||||
_file_address = fileAddress;
|
||||
public class CSVReaderStream : ViewStream
|
||||
{
|
||||
private IBlueRowCollection myRows;
|
||||
|
||||
public CSVReaderStream(string fileAddress)
|
||||
{
|
||||
myRows = BlueDataUtility.createRowsFromCSVFileWithoutTypes(fileAddress);
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_stopwatch.Start();
|
||||
DataFrame df = DataFrame.LoadCsv(_file_address);
|
||||
_stopwatch.Stop();
|
||||
bts.Log.Gen.info($"CSVReaderStream.myOnFirstSubscriber stream csv load col_count: {df.Columns.Count} rows, time: {_stopwatch.ElapsedMilliseconds} msecs");
|
||||
_stopwatch.Start();
|
||||
IBlueRowCollection rows = BlueDataUtility.createRowsFromCSVFileWithoutTypes(_file_address);
|
||||
_stopwatch.Stop();
|
||||
bts.Log.Gen.info($"CSVReaderStream.myOnFirstSubscriber stream csv load count: {rows.Count} rows, time: {_stopwatch.ElapsedMilliseconds} msecs");
|
||||
DataPacket dp_out = BlueDataUtility.build_dp_inc(rows, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
protected override void myOnFirstSubscriber()
|
||||
{
|
||||
myFireEvent(new DataPacket(myRows, myRows, new BlueTable(myRows.schema)));
|
||||
}
|
||||
}
|
||||
|
||||
[DataStreamUserRespresentation("CSVReaderStreamMapper")]
|
||||
public class CSVReaderStreamMapperStream : ViewStream {
|
||||
public CSVReaderStreamMapperStream(ViewStream stream, string output_schema) {
|
||||
[DataStreamUserRespresentation ("CSVReaderStreamMapper")]
|
||||
public class CSVReaderStreamMapperStream : ViewStream
|
||||
{
|
||||
public CSVReaderStreamMapperStream(ViewStream stream, string output_schema)
|
||||
{
|
||||
mySetRealSource(new MapStream(stream, new CSVReaderStreamMapper(output_schema)));
|
||||
}
|
||||
}
|
||||
|
||||
public class CSVReaderStreamMapper : IStreamMapper {
|
||||
public class CSVReaderStreamMapper : IStreamMapper
|
||||
{
|
||||
private IBlueTableSchema mySchema;
|
||||
private readonly string[] myOutputSchemaStringArray;
|
||||
|
||||
public CSVReaderStreamMapper(string outputSchema) {
|
||||
public CSVReaderStreamMapper(string outputSchema)
|
||||
{
|
||||
myOutputSchemaStringArray = outputSchema.Split(' ');
|
||||
}
|
||||
|
||||
public IBlueTableSchema getOutputSchema(IBlueTableSchema inputSchema) {
|
||||
if (mySchema == null) {
|
||||
public IBlueTableSchema getOutputSchema(IBlueTableSchema inputSchema)
|
||||
{
|
||||
if (mySchema == null)
|
||||
{
|
||||
ColumnInfo[] ci = inputSchema.columnInfo;
|
||||
foreach (string col in myOutputSchemaStringArray) {
|
||||
foreach (string col in myOutputSchemaStringArray)
|
||||
{
|
||||
string colName = col.Substring(0, col.IndexOf('\\')).ToLower();
|
||||
for (int i = 0; i < ci.Length; i++) {
|
||||
if (ci[i].colName.ToLower().Equals(colName)) {
|
||||
for (int i = 0; i < ci.Length; i++)
|
||||
{
|
||||
if (ci[i].colName.ToLower().Equals(colName))
|
||||
{
|
||||
Type t = myGetType(col.Substring(col.IndexOf('\\') + 1));
|
||||
ci[i] = new ColumnInfo(ci[i].colName, i, t);
|
||||
break;
|
||||
@@ -158,52 +171,74 @@ namespace BCG {
|
||||
return mySchema;
|
||||
}
|
||||
|
||||
public IBlueRow map(IBlueRow row) {
|
||||
public IBlueRow map(IBlueRow row)
|
||||
{
|
||||
object[] vals = new object[row.schema.columnInfo.Length];
|
||||
row.Values.CopyTo(vals, 0);
|
||||
for (int i = 0; i < mySchema.columnInfo.Length; i++) {
|
||||
for (int i = 0; i < mySchema.columnInfo.Length; i++)
|
||||
{
|
||||
Type t = mySchema.columnInfo[i].colType;
|
||||
try {
|
||||
try
|
||||
{
|
||||
vals[i] = System.Convert.ChangeType(vals[i], mySchema.columnInfo[i].colType, System.Globalization.CultureInfo.InvariantCulture);
|
||||
} catch {
|
||||
if (t.Equals(typeof(Int16))) {
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (t.Equals(typeof(Int16)))
|
||||
{
|
||||
Int16 result;
|
||||
if (Int16.TryParse((string)vals[i], out result)) {
|
||||
if (Int16.TryParse((string)vals[i], out result))
|
||||
{
|
||||
vals[i] = result;
|
||||
continue;
|
||||
}
|
||||
double r2;
|
||||
if (Double.TryParse((string)vals[i], out r2)) {
|
||||
try {
|
||||
if (Double.TryParse((string)vals[i], out r2))
|
||||
{
|
||||
try
|
||||
{
|
||||
vals[i] = (Int16)r2;
|
||||
continue;
|
||||
} catch { }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
} else if (t.Equals(typeof(Int32))) {
|
||||
}
|
||||
else if (t.Equals(typeof(Int32)))
|
||||
{
|
||||
Int32 result;
|
||||
if (Int32.TryParse((string)vals[i], out result)) {
|
||||
if (Int32.TryParse((string)vals[i], out result))
|
||||
{
|
||||
vals[i] = result;
|
||||
continue;
|
||||
}
|
||||
double r2;
|
||||
if (Double.TryParse((string)vals[i], out r2)) {
|
||||
try {
|
||||
if (Double.TryParse((string)vals[i], out r2))
|
||||
{
|
||||
try
|
||||
{
|
||||
vals[i] = (Int32)r2;
|
||||
continue;
|
||||
} catch { }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
} else if (t.Equals(typeof(Int64))) {
|
||||
}
|
||||
else if (t.Equals(typeof(Int64)))
|
||||
{
|
||||
Int64 result;
|
||||
if (Int64.TryParse((string)vals[i], out result)) {
|
||||
if (Int64.TryParse((string)vals[i], out result))
|
||||
{
|
||||
vals[i] = result;
|
||||
continue;
|
||||
}
|
||||
double r2;
|
||||
if (Double.TryParse((string)vals[i], out r2)) {
|
||||
try {
|
||||
if (Double.TryParse((string)vals[i], out r2))
|
||||
{
|
||||
try
|
||||
{
|
||||
vals[i] = (Int64)r2;
|
||||
continue;
|
||||
} catch { }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
vals[i] = DBNull.Value;
|
||||
@@ -212,7 +247,8 @@ namespace BCG {
|
||||
return new BlueRow(mySchema, vals);
|
||||
}
|
||||
|
||||
private Type myGetType(string type) {
|
||||
private Type myGetType(string type)
|
||||
{
|
||||
type = type.ToLower();
|
||||
if (type.Contains("int"))
|
||||
return typeof(int);
|
||||
|
||||
+24
-33
@@ -1,41 +1,31 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
|
||||
using BCG.Utilities;
|
||||
|
||||
namespace BCG {
|
||||
// if a table needs to be fired, it can be wrapped around this
|
||||
public class BlueTableStream : ViewStream {
|
||||
private IBlueRowCollection _rows;
|
||||
public BlueTableStream(IBlueRowCollection rows) {
|
||||
_rows = rows;
|
||||
namespace BCG
|
||||
{
|
||||
[DataStreamUserRespresentation (false)]
|
||||
public class BlueRowCollectionStaticStream : ViewStream
|
||||
{
|
||||
public BlueRowCollectionStaticStream () {}
|
||||
|
||||
public BlueRowCollectionStaticStream (IBlueRowCollection rows) {loadCollection (rows);}
|
||||
|
||||
public void loadCollection (IBlueRowCollection rows)
|
||||
{
|
||||
myFireEvent (new DataPacket (rows, rows, myLastValue != null ?
|
||||
new BlueTable((myLastValue as DataPacket).newRows) : new BlueTable (rows.schema)));
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
var dp_out = BlueDataUtility.build_dp_inc(_rows, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
}
|
||||
|
||||
[DataStreamUserRespresentation(false)]
|
||||
public class BlueRowCollectionStaticStream : ViewStream {
|
||||
public BlueRowCollectionStaticStream() { }
|
||||
|
||||
public BlueRowCollectionStaticStream(IBlueRowCollection rows) { loadCollection(rows); }
|
||||
|
||||
public void loadCollection(IBlueRowCollection rows) {
|
||||
myFireEvent(new DataPacket(rows, rows, myLastValue != null ?
|
||||
new BlueTable((myLastValue as DataPacket).newRows) : new BlueTable(rows.schema)));
|
||||
}
|
||||
|
||||
public void crush_with_single_row(IBlueRow r) {
|
||||
public void crush_with_single_row(IBlueRow r)
|
||||
{
|
||||
BlueTable t = new BlueTable(r.schema);
|
||||
t.addRow(r);
|
||||
loadCollection(t);
|
||||
}
|
||||
|
||||
public void loadPacket(DataPacket dp) { myFireEvent(dp); }
|
||||
public void loadPacket (DataPacket dp) {myFireEvent (dp);}
|
||||
|
||||
/// <summary>
|
||||
/// Will work with streams that take ViewStream as first argument ex project, filter, distinct etc
|
||||
@@ -45,16 +35,17 @@ namespace BCG {
|
||||
/// <param name="streamType"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
public static IBlueRowCollection statelessOp(IBlueRowCollection rows, Type streamType, params object[] args) {
|
||||
ArrayList totArgs = new ArrayList(args);
|
||||
BlueRowCollectionStaticStream v1 = new BlueRowCollectionStaticStream();
|
||||
totArgs.Insert(0, v1);
|
||||
ViewStream retVal = Activator.CreateInstance(streamType, totArgs.ToArray()) as ViewStream;
|
||||
v1.loadCollection(rows);
|
||||
public static IBlueRowCollection statelessOp (IBlueRowCollection rows, Type streamType, params object[] args)
|
||||
{
|
||||
ArrayList totArgs = new ArrayList (args);
|
||||
BlueRowCollectionStaticStream v1 = new BlueRowCollectionStaticStream ();
|
||||
totArgs.Insert (0, v1);
|
||||
ViewStream retVal = Activator.CreateInstance (streamType, totArgs.ToArray()) as ViewStream;
|
||||
v1.loadCollection (rows);
|
||||
return retVal.rows;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -80,7 +80,7 @@ namespace BCG {
|
||||
|
||||
public IBlueRow map(IBlueRow row) {
|
||||
MutableBlueRow rv = new MutableBlueRow(getOutputSchema(row.schema), row);
|
||||
rv.setValue(myConversionColName, mapDateTime(row.get_datetime(myConversionColName), myConversion));
|
||||
rv.setValue(myConversionColName, mapDateTime(row[myConversionColName], myConversion));
|
||||
return rv;
|
||||
//return BlueDataUtility.getNewReplacedRow(row, mapDateTime(row[myConversionColName], myConversion), myConversionColName);
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using bts;
|
||||
|
||||
using BCG;
|
||||
|
||||
using System;
|
||||
[DataStreamUserRespresentation("DateTimeExpanderStream")]
|
||||
public class DateTimeExpanstionStream : ViewStream {
|
||||
public DateTimeExpanstionStream(ViewStream parent_stream, string inp_col) {
|
||||
Func<IBlueTableSchema, IBlueTableSchema> get_schema = (s) => {
|
||||
IBlueTableSchema rv = s.add_column(System.TypeCode.DateTime, $"{inp_col}_date");
|
||||
rv = rv.add_column(System.TypeCode.String, $"{inp_col}_day");
|
||||
rv = rv.add_column(System.TypeCode.Int32, $"{inp_col}_day_of_month");
|
||||
rv = rv.add_column(System.TypeCode.Int32, $"{inp_col}_month");
|
||||
rv = rv.add_column(System.TypeCode.Int32, $"{inp_col}_hour");
|
||||
rv = rv.add_column(System.TypeCode.Int32, $"{inp_col}_min");
|
||||
rv = rv.add_column(System.TypeCode.Int32, $"{inp_col}_seconds_of_day");
|
||||
return rv;
|
||||
};
|
||||
ViewStream rs = new MapStream(parent_stream,
|
||||
s => get_schema(s),
|
||||
r => {
|
||||
DateTime dt = r.get_datetime(inp_col);
|
||||
IBlueTableSchema s = get_schema(r.schema);
|
||||
MutableBlueRow rv = new MutableBlueRow(s, r);
|
||||
rv.setValue($"{inp_col}_date", dt.Date);
|
||||
rv.setValue($"{inp_col}_day_of_week", dt.DayOfWeek.ToString());
|
||||
rv.setValue($"{inp_col}_day_of_month", dt.Day);
|
||||
rv.setValue($"{inp_col}_month", dt.Date.Month);
|
||||
rv.setValue($"{inp_col}_hour", dt.Hour);
|
||||
rv.setValue($"{inp_col}_minute", dt.Minute);
|
||||
rv.setValue($"{inp_col}_seconds_of_day", (dt - dt.Date).TotalSeconds);
|
||||
return rv;
|
||||
});
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using bts;
|
||||
using bts.collections;
|
||||
|
||||
using System;
|
||||
using System.CodeDom;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
// Given 2 filters, and 2 columns, finds the different in the value of the 2 columns from the 2 rows
|
||||
// so:
|
||||
// f1(base_stream.rows)[col1] - f1(base_stream.rows)[col2]
|
||||
[DataStreamUserRespresentation("ColDiff")]
|
||||
public class ColumnDifferenceStream : ViewStream {
|
||||
private readonly ViewStream _base_stream;
|
||||
private readonly FilterStream.OnFilter _f1, _f2;
|
||||
private readonly string _c1, _c2;
|
||||
|
||||
public ColumnDifferenceStream(ViewStream base_stream, FilterStream.OnFilter f1, FilterStream.OnFilter f2, string col1, string col2) {
|
||||
_base_stream = base_stream;
|
||||
_f1 = f1;
|
||||
_f2 = f2;
|
||||
_c1 = col1;
|
||||
_c2 = col2;
|
||||
}
|
||||
|
||||
public ColumnDifferenceStream(ViewStream base_stream, string f1, string f2, string col1, string col2) {
|
||||
FilterStream.OnFilter f1_del = r => {
|
||||
BooleanExpressionFilter rv = new BooleanExpressionFilter(f1);
|
||||
return rv.filter(r);
|
||||
};
|
||||
FilterStream.OnFilter f2_del = r => {
|
||||
BooleanExpressionFilter rv = new BooleanExpressionFilter(f2);
|
||||
return rv.filter(r);
|
||||
};
|
||||
ViewStream rs = new ColumnDifferenceStream(base_stream, f1_del, f2_del, col1, col2);
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
// for each row, does a row[new_col_name] = row[col1] - rows[row_ffset][col2]
|
||||
// we should generlize this for any math operation
|
||||
public ColumnDifferenceStream(ViewStream parent_stream, string sort_col_name, int row_offset, string col1, string col2, string diff_col_name, double optional_perc_diff_filter = 0.0) {
|
||||
// use GlobalMapStream
|
||||
string diff_col_perc_name = $"{diff_col_name}_percentage";
|
||||
System.Func<System.Collections.Generic.List<BCG.IBlueRow>, uint, BCG.IBlueRow> g_map_func = (rows, idx) => {
|
||||
int minuend_idx = Convert.ToInt32(idx);
|
||||
var inp_schema = rows[0].schema;
|
||||
var out_schema = inp_schema.add_column(TypeCode.Double, diff_col_name);
|
||||
out_schema = out_schema.add_column(TypeCode.Double, diff_col_perc_name);
|
||||
// minuend - subtrahend
|
||||
IBlueRow minuend_row = rows.ElementAt(minuend_idx);
|
||||
MutableBlueRow rv = new MutableBlueRow(out_schema, minuend_row);
|
||||
int subtrahend_index = minuend_idx + row_offset;
|
||||
double diff_val = Double.NaN, diff_val_perc = Double.NaN;
|
||||
if (subtrahend_index >= 0) {
|
||||
try {
|
||||
IBlueRow subtrahend_row = rows.ElementAt(subtrahend_index);
|
||||
diff_val = minuend_row.get<double>(col1) - subtrahend_row.get<double>(col2);
|
||||
diff_val_perc = 100.0 * diff_val / subtrahend_row.get<double>(col1);
|
||||
} catch (Exception ex) {
|
||||
Log.assert(false, ex.Message);
|
||||
}
|
||||
}
|
||||
rv.setValue(diff_col_name, diff_val);
|
||||
rv.setValue(diff_col_perc_name, diff_val_perc);
|
||||
return rv;
|
||||
};
|
||||
ViewStream rs = new GlobalMapStream(parent_stream, sort_col_name, g_map_func);
|
||||
if (optional_perc_diff_filter != 0) {
|
||||
rs = new FilterStream(rs, r => {
|
||||
double diff_val_perc = r.get<double>(diff_col_perc_name);
|
||||
double abs_diff_val_perc = Math.Abs(diff_val_perc);
|
||||
return abs_diff_val_perc >= optional_perc_diff_filter;
|
||||
});
|
||||
}
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_base_stream.onChange += _handle_base_stream_update;
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
_base_stream.onChange -= _handle_base_stream_update;
|
||||
}
|
||||
|
||||
private void _handle_base_stream_update(object dp_obj) {
|
||||
// could have been done with filter and cartesian prod, and then math
|
||||
DataPacket dp = dp_obj as DataPacket;
|
||||
List<IBlueRow> rows = dp.newRows.to_list();
|
||||
var f1_rows = rows.Where(r => _f1(r));
|
||||
//Log.assert(f1_rows.Count() == 1);
|
||||
var f2_rows = rows.Where(r => _f2(r));
|
||||
//Log.assert(f2_rows.Count() == 1);
|
||||
if (f1_rows != null && f1_rows.Count() > 0 && f2_rows != null && f2_rows.Count() > 0) {
|
||||
IBlueRow f1_r = f1_rows.ElementAt(0);
|
||||
IBlueRow f2_r = f2_rows.ElementAt(0);
|
||||
double diff = f1_r.get<double>(_c1) - f2_r.get<double>(_c2);
|
||||
IBlueTableSchema out_schema = f1_r.schema.add_columns(Tuple.Create(typeof(double), "diff"));
|
||||
BlueTable out_table = new BlueTable(out_schema);
|
||||
MutableBlueRow out_row = new MutableBlueRow(out_schema, f1_r);
|
||||
out_row.setValue("diff", diff);
|
||||
out_table.addRow(out_row);
|
||||
DataPacket dp_out = BlueDataUtility.build_dp(out_table, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
} else {
|
||||
IBlueRow f1_r = rows.ElementAt(0);
|
||||
IBlueRow f2_r = rows.ElementAt(0);
|
||||
double diff = Double.NaN;
|
||||
IBlueTableSchema out_schema = f1_r.schema.add_columns(Tuple.Create(typeof(double), "diff"));
|
||||
BlueTable out_table = new BlueTable(out_schema);
|
||||
MutableBlueRow out_row = new MutableBlueRow(out_schema, f1_r);
|
||||
out_row.setValue("diff", diff);
|
||||
out_table.addRow(out_row);
|
||||
DataPacket dp_out = BlueDataUtility.build_dp(out_table, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using bts;
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
// Given a sort order, an optional group by col, it observes the values of a column
|
||||
// within that group (or the whole table, if grouping not specified) and returns all rows
|
||||
// where the value changes, ie row[current][col] != row[current-1][col]
|
||||
// TODO: a more general way to express a filter where row[current][col] != row[previous][col],
|
||||
// or even expand it to row[current][col_a] - row[previous][col_b] < 0.5
|
||||
[DataStreamUserRespresentation("ColEvol")]
|
||||
public class ColumnEvolutionStream : ViewStream {
|
||||
private readonly ViewStream _base_stream;
|
||||
private readonly string _sort_col;
|
||||
private readonly string _evol_col;
|
||||
public ColumnEvolutionStream(ViewStream base_stream, string sort_col, string evolution_col) {
|
||||
_base_stream = base_stream;
|
||||
_sort_col = sort_col;
|
||||
_evol_col = evolution_col;
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_base_stream.onChange += _handle_base_stream_update;
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
base.myOnLastSubscriber();
|
||||
}
|
||||
|
||||
private void _handle_base_stream_update(object dp_obj) {
|
||||
DataPacket dp = dp_obj as DataPacket;
|
||||
List<IBlueRow> rows = dp.newRows.to_list();
|
||||
rows.Sort((r1, r2) => BlueDataUtility.compare_rows(r2, r1, _sort_col));
|
||||
BlueTable rv = new BlueTable(dp.schema);
|
||||
IBlueRow prev_row = rows.ElementAt(0);
|
||||
foreach (IBlueRow r in rows) {
|
||||
var cr = BlueDataUtility.compare_rows(r, prev_row, _evol_col);
|
||||
if (cr != 0) {
|
||||
rv.addRow(r);
|
||||
}
|
||||
prev_row = r;
|
||||
}
|
||||
DataPacket dp_out = BlueDataUtility.build_dp(rv, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,75 +15,10 @@ using mbts;
|
||||
using BCG.Extensions;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Newtonsoft.Json;
|
||||
using BCG;
|
||||
using System.Runtime.CompilerServices;
|
||||
using bts;
|
||||
|
||||
namespace bts {
|
||||
|
||||
// public class CompositeRow : IBlueRow {
|
||||
// private IBlueRow _lrow, _rrow;
|
||||
// private BlueRow _out_row;
|
||||
// public CompositeRow(IBlueRow lrow, IBlueRow rrow) {
|
||||
// _lrow = lrow;
|
||||
// _rrow = rrow;
|
||||
// IBlueTableSchema schema = _lrow.schema;
|
||||
// List<object> vals = new List<object>();
|
||||
// foreach (var o in _lrow) {
|
||||
// vals.Add(o);
|
||||
// }
|
||||
// foreach (ColumnInfo ci in _rrow.schema.columnInfo) {
|
||||
// if (ci.colName == "id") {
|
||||
// continue;
|
||||
// }
|
||||
// vals.Add(_rrow[ci.colNo]);
|
||||
// schema = schema.add_column(ci.type_code(), ci.colName);
|
||||
// }
|
||||
// _out_row = new BlueRow(schema, vals.ToArray());
|
||||
// }
|
||||
// public IBlueTableSchema schema {
|
||||
// get { return _out_row.schema; }
|
||||
// }
|
||||
// public object? this[int index] {
|
||||
// get { return _out_row[index]; }
|
||||
// }
|
||||
// public object? this[string colName] {
|
||||
// get {
|
||||
// return _out_row[colName];
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
namespace BCG {
|
||||
public static class BlueDataUtility {
|
||||
public static IBlueRow create_composite_row(IBlueRow lr, IBlueRow rr, int id) {
|
||||
IBlueTableSchema schema = lr.schema;
|
||||
List<object> vals = new List<object>();
|
||||
foreach (ColumnInfo ci in lr.schema.columnInfo) {
|
||||
if (ci.colName == "id") {
|
||||
vals.Add(id);
|
||||
}
|
||||
vals.Add(lr[ci.colName]);
|
||||
}
|
||||
foreach (ColumnInfo ci in rr.schema.columnInfo) {
|
||||
if (ci.colName == "id") {
|
||||
continue;
|
||||
}
|
||||
schema = schema.add_column(ci.type_code(), ci.colName);
|
||||
vals.Add(rr[ci.colName]);
|
||||
}
|
||||
IBlueRow r = new BlueRow(schema, vals.ToArray());
|
||||
return r;
|
||||
}
|
||||
#region Extensions
|
||||
public static bool is_null(this IBlueRow r, string col_name) {
|
||||
object col_val = r[col_name];
|
||||
return col_val == null || DBNull.Value.Equals(col_val);
|
||||
}
|
||||
|
||||
public static DateTime get_datetime(this IBlueRow r, string col_name, DateTime err_value = default(DateTime)) {
|
||||
return BlueDataUtility.get_row_datetime_value(r, col_name, err_value);
|
||||
}
|
||||
@@ -114,17 +49,6 @@ namespace BCG {
|
||||
rv.Add(r.get<T>(col));
|
||||
return rv;
|
||||
}
|
||||
public static IEnumerable<T> get_colvalues<T>(IEnumerable<IBlueRow> rows, string col, int start_index, int count) {
|
||||
List<T> rv = new List<T>();
|
||||
int i = 0;
|
||||
int n_copied = 0;
|
||||
foreach (IBlueRow r in rows)
|
||||
if (i++ >= start_index && n_copied < count) {
|
||||
rv.Add(r.get<T>(col));
|
||||
n_copied++;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static IDictionary<T, IEnumerable<IBlueRow>> group_by<T>(IBlueRowCollection rows, string gp_col) {
|
||||
Dictionary<T, List<IBlueRow>> rv = new Dictionary<T, List<IBlueRow>>();
|
||||
@@ -188,17 +112,13 @@ namespace BCG {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<IBlueRow> to_list(this IBlueRowCollection rows) {
|
||||
public static IEnumerable<IBlueRow> to_ienum(this IBlueRowCollection rows) {
|
||||
List<IBlueRow> rv = new List<IBlueRow>();
|
||||
foreach (IBlueRow r in rows)
|
||||
rv.Add(r);
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static IEnumerable<IBlueRow> to_ienum(this IBlueRowCollection rows) {
|
||||
return rows.to_list();
|
||||
}
|
||||
|
||||
public static IDictionary<int, IBlueRow> to_map(this IBlueRowCollection rows) {
|
||||
Dictionary<int, IBlueRow> rv = new Dictionary<int, IBlueRow>();
|
||||
foreach (IBlueRow r in rows) {
|
||||
@@ -208,10 +128,6 @@ namespace BCG {
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static bool contains_column(this IBlueTableSchema input_schema, string col) {
|
||||
return input_schema.columnNames.Contains(col);
|
||||
}
|
||||
|
||||
public static IBlueTableSchema add_columns(this IBlueTableSchema input_schema, params Tuple<Type, string>[] cols) {
|
||||
List<ColumnInfo> cis = new List<ColumnInfo>(input_schema.columnInfo);
|
||||
foreach (Tuple<Type, string> c in cols)
|
||||
@@ -219,11 +135,6 @@ namespace BCG {
|
||||
return new BlueTableSchema(input_schema.tableName, cis.ToArray());
|
||||
}
|
||||
|
||||
public static IBlueTableSchema add_column(this IBlueTableSchema input_schema, TypeCode type_arg, string col_name) {
|
||||
Tuple<Type, string> tup = new Tuple<Type, string>(_typecode_to_type[type_arg], col_name);
|
||||
return add_columns(input_schema, tup);
|
||||
}
|
||||
|
||||
public static IBlueRowCollection to_collection(this IBlueRow r) {
|
||||
if (r == null)
|
||||
return null;
|
||||
@@ -280,18 +191,6 @@ namespace BCG {
|
||||
|
||||
#region json
|
||||
|
||||
public static Dictionary<string, string> convert_json_to_dictionary(string json_string) {
|
||||
Dictionary<string, string> dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(json_string);
|
||||
return dictionary;
|
||||
}
|
||||
public static IBlueRow convert_json_to_row(string json_string, int id = 0) {
|
||||
Dictionary<string, object> dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(json_string);
|
||||
if (!dictionary.ContainsKey("id")) {
|
||||
dictionary.Add("id", id);
|
||||
}
|
||||
return new BlueRow(dictionary);
|
||||
}
|
||||
|
||||
public static List<JsonNode> json_to_json_node_list(string jsonString) {
|
||||
var jsonNodeList = new List<JsonNode>();
|
||||
bool noe = String.IsNullOrEmpty(jsonString);
|
||||
@@ -310,7 +209,7 @@ namespace BCG {
|
||||
foreach (JsonNode jsonNode in jsonArray) {
|
||||
jsonNodeList.Add(jsonNode);
|
||||
}
|
||||
} catch (System.Text.Json.JsonException ex) {
|
||||
} catch (JsonException ex) {
|
||||
Console.WriteLine($"Invalid JSON: {ex.Message}");
|
||||
}
|
||||
|
||||
@@ -587,16 +486,7 @@ namespace BCG {
|
||||
ColumnInfo[] cis = new ColumnInfo[table.Columns.Count];
|
||||
foreach (DataColumn col in table.Columns)
|
||||
cis[col.Ordinal] = new ColumnInfo(col.ColumnName, col.Ordinal, col.DataType);
|
||||
IBlueTableSchema rv = new BlueTableSchema(cis, table.TableName);
|
||||
rv = rv.add_id_col_if_missing();
|
||||
return rv;
|
||||
}
|
||||
public static IBlueTableSchema add_id_col_if_missing(this IBlueTableSchema schema) {
|
||||
IBlueTableSchema rv = schema;
|
||||
if (!schema.columnNames.Contains("id")) {
|
||||
rv = schema.add_columns(Tuple.Create(typeof(int), "id"));
|
||||
}
|
||||
return rv;
|
||||
return new BlueTableSchema(cis, table.TableName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -854,16 +744,10 @@ namespace BCG {
|
||||
}
|
||||
|
||||
public static IBlueRowCollection toIBlueRowCollection(DataTable dt) {
|
||||
IBlueTableSchema schema = getSchema(dt);
|
||||
BlueTable rv = new BlueTable(schema);
|
||||
foreach (DataRow dr in dt.Rows) {
|
||||
MutableBlueRow nr = new MutableBlueRow(schema);
|
||||
foreach (DataColumn col in dr.Table.Columns)
|
||||
nr.setValue(col.ColumnName, dr[col.ColumnName]);
|
||||
nr.setValue("id", rv.Count);
|
||||
rv.addRow(nr);
|
||||
}
|
||||
return rv;
|
||||
BlueTable retVal = new BlueTable(getSchema(dt));
|
||||
foreach (DataRow dr in dt.Rows)
|
||||
retVal.addRow(dr);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public static IBlueRowCollection toIBlueRowCollection(DataRow[] rows) {
|
||||
@@ -935,20 +819,20 @@ namespace BCG {
|
||||
/// </summary>
|
||||
/// <param name="r1"></param>
|
||||
/// <param name="r2"></param>
|
||||
/// <param name="col_names"></param>
|
||||
/// <param name="colNames"></param>
|
||||
/// <returns></returns>
|
||||
public static int compare_rows(IBlueRow r1,
|
||||
IBlueRow r2,
|
||||
params string[] col_names) {
|
||||
int comp_res = 0;
|
||||
foreach (string cn in col_names) {
|
||||
object val1 = r1[cn];
|
||||
object val2 = r2[cn];
|
||||
comp_res = _compare_row_cols(val1, val2);
|
||||
if (comp_res != 0)
|
||||
params string[] colNames) {
|
||||
int retVal = 0;
|
||||
foreach (string colName in colNames) {
|
||||
object val1 = r1[colName];
|
||||
object val2 = r2[colName];
|
||||
retVal = _compare_row_cols(val1, val2);
|
||||
if (retVal != 0)
|
||||
break;
|
||||
}
|
||||
return comp_res;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private static int _compare_row_cols(object v1, object v2) {
|
||||
@@ -1724,10 +1608,8 @@ namespace BCG {
|
||||
|
||||
public static int[] get_column_indices(IBlueTableSchema schema, string[] col_names) {
|
||||
List<int> rv = new List<int>();
|
||||
foreach (string c in col_names) {
|
||||
Log.assert(schema.contains_column(c), $"Could not find col: {c} in table: {schema.tableName}");
|
||||
foreach (string c in col_names)
|
||||
rv.Add(schema[c].colNo);
|
||||
}
|
||||
return rv.ToArray();
|
||||
}
|
||||
|
||||
@@ -2214,53 +2096,23 @@ namespace BCG {
|
||||
try {
|
||||
if (v == null || v == DBNull.Value)
|
||||
return error_val;
|
||||
|
||||
if (v is DateTime) {
|
||||
return (DateTime)v;
|
||||
} else if (v is string) {
|
||||
DateTime rv_dt;
|
||||
|
||||
// Try parsing the string as a DateTime
|
||||
if (DateTime.TryParse((string)v,
|
||||
System.Globalization.CultureInfo.InvariantCulture,
|
||||
System.Globalization.DateTimeStyles.RoundtripKind,
|
||||
out rv_dt)) {
|
||||
else {
|
||||
if (v is DateTime)
|
||||
return (DateTime)v;
|
||||
else if (v is string) {
|
||||
DateTime rv_dt = error_val;
|
||||
DateTime.TryParse((string)v, out rv_dt);
|
||||
return rv_dt;
|
||||
} else {
|
||||
return error_val; // Return the error value if parsing fails
|
||||
double oa_date = (double)Convert.ChangeType(v, typeof(Double));
|
||||
return DateTime.FromOADate(oa_date);
|
||||
}
|
||||
} else {
|
||||
// Assume the input can be converted to a double and use FromOADate
|
||||
double oa_date = (double)Convert.ChangeType(v, typeof(Double));
|
||||
return DateTime.FromOADate(oa_date);
|
||||
}
|
||||
} catch {
|
||||
return error_val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// private static DateTime _get_datetime_value(object v, DateTime error_val) {
|
||||
// try {
|
||||
// if (v == null || v == DBNull.Value)
|
||||
// return error_val;
|
||||
// else {
|
||||
// if (v is DateTime)
|
||||
// return (DateTime)v;
|
||||
// else if (v is string) {
|
||||
// DateTime rv_dt = error_val;
|
||||
// DateTime.TryParse((string)v, out rv_dt);
|
||||
// return rv_dt;
|
||||
// } else {
|
||||
// double oa_date = (double)Convert.ChangeType(v, typeof(Double));
|
||||
// return DateTime.FromOADate(oa_date);
|
||||
// }
|
||||
// }
|
||||
// } catch {
|
||||
// return error_val;
|
||||
// }
|
||||
// }
|
||||
|
||||
#endregion
|
||||
|
||||
#region CSV methods
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.24.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="OpenAI" Version="2.0.0" />
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -47,11 +47,6 @@ namespace BCG {
|
||||
/// </summary>
|
||||
/// <param name="assemblyName"></param>
|
||||
public void loadAssembly(string assemblyName) {
|
||||
Func<Type, bool> is_silverpine_only = (t) => {
|
||||
if (!assemblyName.Contains("SharedStreams.dll"))
|
||||
return true;
|
||||
return t.Namespace == "bts.SilverPine";
|
||||
};
|
||||
bts.Log.Gen.info($"PrimitiveManager.loadAssembly assemblyName: {assemblyName}");
|
||||
if (myAssemblyNames.Contains(assemblyName))
|
||||
return;
|
||||
@@ -61,7 +56,7 @@ namespace BCG {
|
||||
Assembly.LoadFrom(assemblyName);
|
||||
|
||||
foreach (Type type in loadedAssembly.GetTypes())
|
||||
if (!type.IsInterface && is_silverpine_only(type)
|
||||
if (!type.IsInterface
|
||||
&& !type.IsAbstract
|
||||
&& type.IsSubclassOf(typeof(ViewStream))
|
||||
&& type.IsPublic) {
|
||||
|
||||
@@ -9,15 +9,7 @@
|
||||
Letter [a-zA-Z]
|
||||
BooleanConstant 'true'|'false'
|
||||
CSStringConstant \"([^\"\\]*|\\.)*\"
|
||||
YearInt [0-9]{4}
|
||||
MonthInt [0-9]{1,2}
|
||||
DayInt [0-9]{1,2}
|
||||
/**
|
||||
* DateTimeConstant supports American (mm/dd/yyyy) and European (yyyy/mm/dd)
|
||||
* formats. Month and day can be 1 or 2 digits. It does not validate that the
|
||||
* numbers represent an actual date.
|
||||
*/
|
||||
DateTimeConstant ({MonthInt}\/{DayInt}\/{YearInt}|{YearInt}\/{MonthInt}\/{DayInt})
|
||||
DateTimeConstant ([1-9]|'10'|'11'|'12')\/([1-9]|([1-2][0-9])|'30'|'31')\/[0-9][0-9][0-9]*
|
||||
IntegerConstant -?[0-9]+
|
||||
NullConstant 'null'
|
||||
RealConstant -?[0-9]+\.[0-9]+
|
||||
|
||||
+59
-61
@@ -1,62 +1,60 @@
|
||||
{
|
||||
"user": "bts",
|
||||
"sparkd": "http://192.168.1.80:8000/config",
|
||||
"pubsub": {
|
||||
"milliseconds_between_sub_info_updates": 1000,
|
||||
"milliseconds_between_time_slice_updates": 5000,
|
||||
"milliseconds_between_no_buffer_space_retries": 100,
|
||||
"retries_on_no_buffer_space": 1,
|
||||
"do_it_all_seconds_between_logs": 0,
|
||||
"heartbeat_interval": 15000,
|
||||
"missing_heartbeats_before_gc": 50,
|
||||
"use_managed_sockets": true,
|
||||
"state_update_period": 5000,
|
||||
"statistics_update_period": 5000,
|
||||
"disposed_connection_check_period": 1000,
|
||||
"message_processing_warning_threshold": 1000,
|
||||
"server_port": 12345,
|
||||
"publisher_routes": [
|
||||
{
|
||||
"name": "default",
|
||||
"server_address": "bts-cloud://192.168.1.80:12345",
|
||||
"tag": ".*"
|
||||
}
|
||||
],
|
||||
"subscriber_routes": [
|
||||
{
|
||||
"name": "default",
|
||||
"server_address": "bts-cloud://192.168.1.80:12345",
|
||||
"tag": ".*"
|
||||
}
|
||||
],
|
||||
"max_packet_size": 500000000,
|
||||
"blue_comm_must_die": true,
|
||||
"crushable_tags": [],
|
||||
"tag_type_to_assembly_map": [
|
||||
{
|
||||
"handler_class": "BCG.PubSubServerTagHandler",
|
||||
"assembly": "DataStreamCore.dll"
|
||||
}
|
||||
],
|
||||
"server_queue": "PubSubQueue",
|
||||
"port_range": {
|
||||
"first": 30400,
|
||||
"last": 31700
|
||||
},
|
||||
"bind_to_random_port": false,
|
||||
"debug_tags": "^NOTAGS$",
|
||||
"latency_report_threshold_ms": 1500,
|
||||
"use_substations": false,
|
||||
"use_dynamic_clients": false,
|
||||
"is_substation": false,
|
||||
"internally_publish_sub_info": true,
|
||||
"use_managed_clients_in_native_code": false,
|
||||
"compressed_tags": "^NOTAGS$",
|
||||
"tags_to_report_compression_ratio": "^NOTAGS$",
|
||||
"disable_msmq": false,
|
||||
"use_prepublished_server_state": false,
|
||||
"ip_translation": null,
|
||||
"gc_activation_threshold": 0,
|
||||
"wait_period_after_gc": 1000
|
||||
}
|
||||
"user": "bts",
|
||||
"pubsub": {
|
||||
"milliseconds_between_sub_info_updates": 1000,
|
||||
"milliseconds_between_time_slice_updates": 5000,
|
||||
"milliseconds_between_no_buffer_space_retries": 100,
|
||||
"retries_on_no_buffer_space": 1,
|
||||
"do_it_all_seconds_between_logs": 0,
|
||||
"heartbeat_interval": 15000,
|
||||
"missing_heartbeats_before_gc": 50,
|
||||
"use_managed_sockets": true,
|
||||
"state_update_period": 5000,
|
||||
"statistics_update_period": 5000,
|
||||
"disposed_connection_check_period": 1000,
|
||||
"message_processing_warning_threshold": 1000,
|
||||
"server_port": 12345,
|
||||
"publisher_routes": [
|
||||
{
|
||||
"name": "default",
|
||||
"server_address": "bts-cloud://192.168.1.80:12345",
|
||||
"tag": ".*"
|
||||
}
|
||||
],
|
||||
"subscriber_routes": [
|
||||
{
|
||||
"name": "default",
|
||||
"server_address": "bts-cloud://192.168.1.80:12345",
|
||||
"tag": ".*"
|
||||
}
|
||||
],
|
||||
"max_packet_size": 500000000,
|
||||
"blue_comm_must_die": true,
|
||||
"crushable_tags": [],
|
||||
"tag_type_to_assembly_map": [
|
||||
{
|
||||
"handler_class": "BCG.PubSubServerTagHandler",
|
||||
"assembly": "DataStreamCore.dll"
|
||||
}
|
||||
],
|
||||
"server_queue": "PubSubQueue",
|
||||
"port_range": {
|
||||
"first": 30400,
|
||||
"last": 31700
|
||||
},
|
||||
"bind_to_random_port": false,
|
||||
"debug_tags": "^NOTAGS$",
|
||||
"latency_report_threshold_ms": 1500,
|
||||
"use_substations": false,
|
||||
"use_dynamic_clients": false,
|
||||
"is_substation": false,
|
||||
"internally_publish_sub_info": true,
|
||||
"use_managed_clients_in_native_code": false,
|
||||
"compressed_tags": "^NOTAGS$",
|
||||
"tags_to_report_compression_ratio": "^NOTAGS$",
|
||||
"disable_msmq": false,
|
||||
"use_prepublished_server_state": false,
|
||||
"ip_translation": null,
|
||||
"gc_activation_threshold": 0,
|
||||
"wait_period_after_gc": 1000
|
||||
}
|
||||
}
|
||||
@@ -169,10 +169,8 @@ namespace BCG
|
||||
}
|
||||
#endregion
|
||||
|
||||
private Stopwatch _stopwatch = new Stopwatch();
|
||||
private void myTryExpression(string expStr)
|
||||
{
|
||||
_stopwatch.Restart();
|
||||
myFreezeView(false); // force unfreeze the view
|
||||
DataStreamExpression oldExp = myExp;
|
||||
try
|
||||
@@ -346,7 +344,6 @@ namespace BCG
|
||||
// this is the stream callback
|
||||
private void myCallback(object o)
|
||||
{
|
||||
_stopwatch.Stop();
|
||||
var timer = Stopwatch.StartNew();
|
||||
DataPacket dp = o as DataPacket;
|
||||
myCrono.Stop();
|
||||
@@ -362,8 +359,7 @@ namespace BCG
|
||||
myToolStripStatusLabelRows.BackColor = Color.Black;
|
||||
myToolStripStatusLabelTime.ForeColor = Color.White;
|
||||
myToolStripStatusLabelRows.ForeColor = Color.White;
|
||||
string time_text = "Last update: " + DateTime.Now.ToString("hh:mm:ss:fff tt") + $" time: {_stopwatch.ElapsedMilliseconds} msecs\t\t";
|
||||
myToolStripStatusLabelTime.Text = time_text;
|
||||
myToolStripStatusLabelTime.Text = "Last update: " + DateTime.Now.ToString("hh:mm:ss:fff tt");
|
||||
myToolStripStatusLabelRows.Text = "New = " + dp.newRows.Count + " Added = " + dp.addedRows.Count + " Deleted = " + dp.deletedRows.Count;
|
||||
Log.Ui.diag(Text);
|
||||
int hscrollval = myChangeStyle ? 0 : myDataGrid.HorizScrollBarValue;
|
||||
|
||||
@@ -36,8 +36,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.ColumnExpressions", "Bt
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.ColumnSortExpressions", "Bts.ColumnSortExpressions\Bts.ColumnSortExpressions.csproj", "{B038CB72-4E81-4AF1-976F-ED8655C2C3D6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamQueryAnalyzer", "DataStreamQueryAnalyzer\DataStreamQueryAnalyzer.csproj", "{BFA5BA5C-927A-41A9-A696-1E2F4B5FFD15}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -115,9 +113,5 @@ Global
|
||||
{B038CB72-4E81-4AF1-976F-ED8655C2C3D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B038CB72-4E81-4AF1-976F-ED8655C2C3D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B038CB72-4E81-4AF1-976F-ED8655C2C3D6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BFA5BA5C-927A-41A9-A696-1E2F4B5FFD15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BFA5BA5C-927A-41A9-A696-1E2F4B5FFD15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BFA5BA5C-927A-41A9-A696-1E2F4B5FFD15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BFA5BA5C-927A-41A9-A696-1E2F4B5FFD15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -117,10 +117,10 @@ public class PubSubConfig {
|
||||
WaitPeriodAfterGc = 1000,
|
||||
SimpleEchoServer = false,
|
||||
PublisherRoutes = new() {
|
||||
new("bluto://127.0.0.1:12345", ".*")
|
||||
new("bts-cloud://192.168.1.80:12345", ".*")
|
||||
},
|
||||
SubscriberRoutes = new() {
|
||||
new("bluto://127.0.0.1:12345", ".*")
|
||||
new("bts-cloud://192.168.1.80:12345", ".*")
|
||||
}
|
||||
};
|
||||
return rv;
|
||||
|
||||
File renamed without changes.
@@ -1,252 +0,0 @@
|
||||
using bts.SilverPine;
|
||||
|
||||
namespace bts.SilverPine {
|
||||
using bts.api;
|
||||
using bts.spark;
|
||||
|
||||
using System;
|
||||
|
||||
using ZstdSharp.Unsafe;
|
||||
|
||||
public static class ContractUtils {
|
||||
public class FutureTradableContract {
|
||||
public string symbol;
|
||||
public DateTime expiration;
|
||||
public Exchange exchange;
|
||||
public string contract_text;
|
||||
}
|
||||
public class FutureSpreadContract {
|
||||
public List<Tuple<double, bts.SilverPine.ContractUtils.FutureTradableContract>> legs;
|
||||
public string symbol {
|
||||
get {
|
||||
return legs == null || legs.Count == 0 ? String.Empty : legs.ElementAt(0).Item2.symbol;
|
||||
}
|
||||
}
|
||||
public string contract_text;
|
||||
}
|
||||
public class FutureContinousContract {
|
||||
public string symbol;
|
||||
public Exchange exchange;
|
||||
}
|
||||
// this is for all future conytracts belonging to a symbol
|
||||
public class FutureWildcardContract {
|
||||
public string symbol;
|
||||
public Exchange exchange;
|
||||
}
|
||||
public class FutureContract {
|
||||
public FutureWildcardContract wildcard_contract = null;
|
||||
public FutureTradableContract future_tradable_contract = null;
|
||||
public FutureSpreadContract spread_tradable_contract = null;
|
||||
public FutureContinousContract continous_constract = null;
|
||||
|
||||
public FutureContract(string txt) {
|
||||
wildcard_contract = parse_wildcard_contract(txt);
|
||||
if (wildcard_contract != null)
|
||||
return;
|
||||
FutureTradableContract fc = parse_future_contract(txt);
|
||||
if (fc != null) {
|
||||
future_tradable_contract = fc;
|
||||
return;
|
||||
}
|
||||
FutureSpreadContract sc = parse_future_spread_contract(txt);
|
||||
if (sc != null) {
|
||||
spread_tradable_contract = sc;
|
||||
return;
|
||||
}
|
||||
// this is not totally true, since ParseFutureSpreadContract does not
|
||||
// parse ICS spreads
|
||||
continous_constract = new FutureContinousContract() { symbol = txt };
|
||||
}
|
||||
public bool is_continous_contract => continous_constract != null;
|
||||
public string symbol() {
|
||||
if (wildcard_contract != null)
|
||||
return wildcard_contract.symbol;
|
||||
if (continous_constract != null) {
|
||||
return continous_constract.symbol;
|
||||
} else if (future_tradable_contract != null) {
|
||||
return future_tradable_contract.symbol;
|
||||
} else if (spread_tradable_contract != null) {
|
||||
return spread_tradable_contract.symbol;
|
||||
}
|
||||
Log.assert(false);
|
||||
return String.Empty;
|
||||
}
|
||||
public string contract_text {
|
||||
get {
|
||||
if (future_tradable_contract != null)
|
||||
return future_tradable_contract.contract_text;
|
||||
if (spread_tradable_contract != null)
|
||||
return spread_tradable_contract.contract_text;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#region Parsing
|
||||
public static FutureWildcardContract parse_wildcard_contract(string contract_txt, Exchange exchange = Exchange.CME) {
|
||||
if (contract_txt.EndsWith("*")) {
|
||||
contract_txt = contract_txt.Replace("*", String.Empty);
|
||||
return new FutureWildcardContract() {
|
||||
symbol = contract_txt,
|
||||
exchange = exchange
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static FutureTradableContract parse_future_contract(string contract_txt, Exchange exchange = Exchange.CME) {
|
||||
// Validate the future string length
|
||||
if (!contract_txt.All(c => Char.IsLetterOrDigit(c)))
|
||||
return null;
|
||||
if (contract_txt.Length < 4) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract the symbol and the expiration month/year codes
|
||||
string symbol = contract_txt.Substring(0, contract_txt.Length - 2);
|
||||
char monthCode = contract_txt[contract_txt.Length - 2];
|
||||
char yearCode = contract_txt[contract_txt.Length - 1];
|
||||
|
||||
// Map month code to month, return null if the month code is invalid
|
||||
int month = monthCode switch {
|
||||
'F' => 1, // January
|
||||
'G' => 2, // February
|
||||
'H' => 3, // March
|
||||
'J' => 4, // April
|
||||
'K' => 5, // May
|
||||
'M' => 6, // June
|
||||
'N' => 7, // July
|
||||
'Q' => 8, // August
|
||||
'U' => 9, // September
|
||||
'V' => 10, // October
|
||||
'X' => 11, // November
|
||||
'Z' => 12, // December
|
||||
_ => 0 // Return 0 for invalid month code
|
||||
};
|
||||
|
||||
if (month == 0) {
|
||||
return null; // Invalid month code
|
||||
}
|
||||
|
||||
// Calculate the year based on the current decade
|
||||
int currentYear = DateTime.Now.Year;
|
||||
int decadeStart = currentYear / 10 * 10;
|
||||
int year = decadeStart + (yearCode - '0');
|
||||
|
||||
// If the year is in the past, assume the next decade
|
||||
if (year < currentYear) {
|
||||
year += 10;
|
||||
}
|
||||
|
||||
// Create the FutureContract instance and set its properties
|
||||
DateTime expiration = new DateTime(year, month, 1);
|
||||
var futureContract = new FutureTradableContract {
|
||||
symbol = symbol,
|
||||
expiration = expiration,
|
||||
exchange = exchange,
|
||||
contract_text = contract_txt
|
||||
};
|
||||
|
||||
return futureContract;
|
||||
}
|
||||
// Method to parse a futures spread, e.g. "CLX4-CLZ4"
|
||||
public static FutureSpreadContract parse_future_spread_contract(string contract_txt, Exchange exchange = Exchange.CME) {
|
||||
// Split the string by '-' to handle each leg
|
||||
var spreadParts = contract_txt.Split('-');
|
||||
if (spreadParts.Length < 2) {
|
||||
return null; // Not a valid spread format
|
||||
}
|
||||
|
||||
var spreadContract = new FutureSpreadContract { legs = new List<Tuple<double, FutureTradableContract>>() };
|
||||
|
||||
foreach (var part in spreadParts) {
|
||||
// Split each leg by '*', assuming the format is weight*future or just future
|
||||
string[] legParts = part.Split('*');
|
||||
double weight = 1.0;
|
||||
string futurePart;
|
||||
|
||||
if (legParts.Length == 2) {
|
||||
if (!double.TryParse(legParts[0], out weight)) {
|
||||
return null; // Invalid weight, parsing failed
|
||||
}
|
||||
futurePart = legParts[1];
|
||||
} else if (legParts.Length == 1) {
|
||||
futurePart = legParts[0];
|
||||
} else {
|
||||
return null; // Invalid format, too many '*' parts
|
||||
}
|
||||
|
||||
// Parse the future contract
|
||||
var futureContract = parse_future_contract(futurePart, exchange);
|
||||
if (futureContract == null) {
|
||||
return null; // Failed to parse the future part
|
||||
}
|
||||
|
||||
// Add the leg to the spread contract
|
||||
spreadContract.legs.Add(new Tuple<double, FutureTradableContract>(weight, futureContract));
|
||||
}
|
||||
return spreadContract;
|
||||
}
|
||||
|
||||
// public static ContractType DetermineFutureOrSpread(string contract) {
|
||||
// if (contract.Contains("-")) {
|
||||
// return ContractType.FutureSpread;
|
||||
// } else {
|
||||
// return ContractType.Future;
|
||||
// }
|
||||
// }
|
||||
#endregion
|
||||
|
||||
public static ContractType get_type(string contract_txt) {
|
||||
FutureTradableContract fc = parse_future_contract(contract_txt);
|
||||
if (fc != null) {
|
||||
return ContractType.Future;
|
||||
}
|
||||
FutureSpreadContract sc = parse_future_spread_contract(contract_txt);
|
||||
if (sc != null) {
|
||||
return ContractType.FutureSpread;
|
||||
}
|
||||
// tehre are some non calendar spreads we cant parse
|
||||
//Log.assert(false);
|
||||
return bts.SilverPine.ContractUtils.ContractType.FutureSpread;
|
||||
}
|
||||
|
||||
public static ContractCategory get_category(string symbol) {
|
||||
var tp = get_symbol_category(symbol);
|
||||
return tp.Item1;
|
||||
}
|
||||
|
||||
public static Tuple<ContractCategory, string> get_symbol_category(string symbol) {
|
||||
ContractUtils.FutureTradableContract fc = parse_future_contract(symbol);
|
||||
if (fc != null) {
|
||||
return Tuple.Create(ContractCategory.FutureString, fc.symbol);
|
||||
}
|
||||
var sc = parse_future_spread_contract(symbol);
|
||||
if (sc != null) {
|
||||
return Tuple.Create(ContractCategory.FutureString, sc.symbol);
|
||||
}
|
||||
return Tuple.Create(ContractCategory.Symbol, symbol);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum ContractType {
|
||||
Spot,
|
||||
Option,
|
||||
Future,
|
||||
FutureSpread,
|
||||
OptionSpread
|
||||
}
|
||||
public enum ContractCategory {
|
||||
Symbol = 0,
|
||||
FutureString,
|
||||
SpreadString
|
||||
}
|
||||
public enum CallPut {
|
||||
Call,
|
||||
Put
|
||||
}
|
||||
public enum Exchange {
|
||||
CME
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
// Finds the regions around specified events
|
||||
[DataStreamUserRespresentation("EventsPriceAction")]
|
||||
public class EventsPriceActionStream : ViewStream {
|
||||
public EventsPriceActionStream(string symbol, string event_type, string pre_event_period,
|
||||
string post_event_period, int n_events) :
|
||||
this(symbol, event_type, TimeBasedFilter.parse_duration(pre_event_period), TimeBasedFilter.parse_duration(post_event_period),
|
||||
n_events, ViewStreamDatabase.instance) { }
|
||||
|
||||
public EventsPriceActionStream(string symbol, string event_type, TimeSpan pre_event_period,
|
||||
TimeSpan post_event_period, int n_events, ViewStreamDatabase vsd) {
|
||||
// TODO: figure out which bars to use, 1 min or 1 day or live, based on pre_event_period / post_event_period
|
||||
FuturesActiveContractStream olhcv_str = new FuturesActiveContractStream(symbol);
|
||||
ViewStream events_str = new EventsStream(vsd, event_type);
|
||||
// todo
|
||||
//events_str = new TopStream(events_str, n_events, "-ts");
|
||||
ViewStream rs = new TimeProximityJoinStream(olhcv_str, "ts_event", events_str, "ts", pre_event_period, post_event_period);
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
public class IndicatorStream : ViewStream {
|
||||
enum Indicator {
|
||||
StandardDeviation = 0
|
||||
}
|
||||
public class IndicatorInfo {
|
||||
Indicator indicator;
|
||||
IDictionary<string, object> parameters;
|
||||
}
|
||||
public IndicatorStream(string symbol_name, string indicator_name, string indicator_params_json) {
|
||||
|
||||
}
|
||||
public IndicatorStream(string symbol_name, IndicatorInfo info) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using ZstdSharp.Unsafe;
|
||||
|
||||
[DataStreamUserRespresentation("AbsVolume")]
|
||||
// Calculates the volume within a time window (this does not do rates, like highest daily volume etc,
|
||||
// but with some thought can perhaps be extended)
|
||||
public class AbsoluteVolumeStream : ViewStream {
|
||||
// TODO, abstract this out
|
||||
// adds contract_type to OHLCV stream
|
||||
private static ViewStream _get_ohlcv_steam(string symbol, DateTime d1, DateTime d2) {
|
||||
var ohlcv_params = OHLCVStream.get_params(d1, d2);
|
||||
ViewStream rs = new OHLCVStream(symbol, ohlcv_params);
|
||||
Func<IBlueTableSchema, IBlueTableSchema> create_schema =
|
||||
s => BlueDataUtility.add_columns(s, Tuple.Create(typeof(string), "contract_type"));
|
||||
rs = new SuperMapStream(rs,
|
||||
s => create_schema(s),
|
||||
r => {
|
||||
IBlueTableSchema out_schema = create_schema(r.schema);
|
||||
string contract_txt = r.get<string>("contract");
|
||||
var contr_type = ContractUtils.get_type(contract_txt);
|
||||
MutableBlueRow out_row = new MutableBlueRow(out_schema, r);
|
||||
out_row.setValue("contract_type", contr_type.ToString());
|
||||
return new IBlueRow[] { out_row };
|
||||
});
|
||||
return rs;
|
||||
}
|
||||
|
||||
public AbsoluteVolumeStream(string symbol, string ctype, DateTime d1)
|
||||
: this(symbol, ctype, d1, d1) { }
|
||||
|
||||
public AbsoluteVolumeStream(string symbol, string ctype, DateTime d1, DateTime d2)
|
||||
: this(symbol, Enum.Parse<ContractUtils.ContractType>(ctype), d1, d2) {
|
||||
}
|
||||
|
||||
static void swap_if_necessary(ref DateTime dt1, ref DateTime dt2) {
|
||||
if (dt1 < dt2) {
|
||||
DateTime aux = dt1;
|
||||
dt1 = dt2;
|
||||
dt2 = aux;
|
||||
}
|
||||
}
|
||||
|
||||
private AbsoluteVolumeStream(string symbol, ContractUtils.ContractType ctype, DateTime d1, DateTime d2) {
|
||||
swap_if_necessary(ref d1, ref d2);
|
||||
ViewStream ohlcv_str = _get_ohlcv_steam(symbol, d1, d2);
|
||||
ohlcv_str = new FilterStream(ohlcv_str,
|
||||
r => r.get_datetime("ts_event") <= d1 && r.get_datetime("ts_event") >= d2);
|
||||
ohlcv_str = new FilterStream(ohlcv_str, r => String.Compare(ctype.ToString(), r.get<string>("contract_type"), true) == 0);
|
||||
ViewStream rs = new MaxStream(ohlcv_str, "volume");
|
||||
rs = new NewProjectStream(rs, "volume:total_volume contract !");
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,105 +1,35 @@
|
||||
namespace bts.SilverPine {
|
||||
namespace BCG {
|
||||
using BCG.Utilities.General;
|
||||
|
||||
using bts.api;
|
||||
using bts.api.domain;
|
||||
using bts.api.synthetic;
|
||||
using bts.md;
|
||||
using BCG;
|
||||
using bts.spark;
|
||||
using bts.utils;
|
||||
|
||||
using mbts;
|
||||
using mbts.co2;
|
||||
using mbts.config;
|
||||
using mbts.spark;
|
||||
using mbts.ui;
|
||||
|
||||
using Spark.Core.Data;
|
||||
using Spark.Core.Disposables;
|
||||
using Spark.Core.Reactive;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using bts.api.core;
|
||||
using Spark.Api.MarketData;
|
||||
|
||||
using SecurityKey = System.UInt32;
|
||||
using System.Data.Entity.Infrastructure;
|
||||
|
||||
public class FakeBBOStream : ViewStream, IWorker {
|
||||
private string _symbol;
|
||||
public BlueTable _table = new BlueTable(BBOStream._bbo_schema);
|
||||
private DateTime _last_fired_time = DateTime.MinValue;
|
||||
private TimeSpan _period = TimeSpan.FromMilliseconds(333);
|
||||
private double _start_price;
|
||||
private double _inc;
|
||||
private int _total_count = 5;
|
||||
private Random _rnd = new Random(DateTime.Now.Millisecond);
|
||||
private string[] _months = new string[]{
|
||||
"F","G", "H", "J","K", "M", "N","Q","U","V","X","Z"
|
||||
};
|
||||
private ViewStreamDatabase _vsd;
|
||||
public FakeBBOStream(string contract_type, string exchange, string symbol, double start_price, double inc)
|
||||
:
|
||||
this(contract_type, exchange, symbol, start_price, inc, ViewStreamDatabase.instance) { }
|
||||
|
||||
public FakeBBOStream(string contract_type, string exchange, string symbol, double start_price, double inc, ViewStreamDatabase vsd) {
|
||||
_symbol = symbol;
|
||||
_start_price = start_price;
|
||||
_inc = inc;
|
||||
_vsd = vsd;
|
||||
Log.assert(contract_type.ToLower() == "future");
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_vsd.addWorker(this);
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
_vsd.removeWorker(this);
|
||||
}
|
||||
|
||||
private bool _random_truefase() {
|
||||
int r = _rnd.Next(0, 100);
|
||||
return r % 2 == 0;
|
||||
}
|
||||
|
||||
private IBlueRow _perturb_row(IBlueRow er) {
|
||||
MutableBlueRow rv = new MutableBlueRow(er);
|
||||
double bid_price = rv.get<double>("bid_price");
|
||||
bid_price += _inc;
|
||||
double ask_price = bid_price + _inc;
|
||||
rv.setValue("bid_price", bid_price);
|
||||
rv.setValue("ask_price", ask_price);
|
||||
return rv;
|
||||
}
|
||||
|
||||
public void doWork() {
|
||||
if (DateTime.Now - _last_fired_time < _period)
|
||||
return;
|
||||
_last_fired_time = DateTime.Now;
|
||||
if (_table.Count == 0) {
|
||||
// first fire_symbol
|
||||
string year_code = DateTime.Now.Year.ToString().Last().ToString();
|
||||
for (int i = 0; i < _total_count; i++) {
|
||||
string month_code = _months[i % _months.Length];
|
||||
string sec = $"{_symbol}{month_code}{year_code}";
|
||||
double bid_price = _start_price + _rnd.Next(-10, 10) * _inc;
|
||||
double ask_price = bid_price + _inc;
|
||||
BlueRow nr = new BlueRow(_table.schema, _table.Count, _table.Count, sec,
|
||||
bid_price, _rnd.Next(1, 10),
|
||||
ask_price, _rnd.Next(1, 10));
|
||||
_table.addRow(nr);
|
||||
var dp = BlueDataUtility.build_dp(new BlueTable(_table), myLastValue as DataPacket);
|
||||
myFireEvent(dp);
|
||||
}
|
||||
} else {
|
||||
BlueTable deleted_rows = new BlueTable(_table.schema);
|
||||
BlueTable added_rows = new BlueTable(_table.schema);
|
||||
// go through all rows, select some at random, add them to deleted, get
|
||||
// the replaced one and add it to added, updates table state and fire
|
||||
for (int i = 0; i < _table.Count; i++) {
|
||||
if (_random_truefase()) {
|
||||
IBlueRow er = _table[i];
|
||||
IBlueRow nr = _perturb_row(er);
|
||||
_table.deleteRow(er);
|
||||
_table.addRow(nr);
|
||||
}
|
||||
}
|
||||
var dp = BlueDataUtility.build_dp_inc(new BlueTable(_table), myLastValue as DataPacket, true);
|
||||
myFireEvent(dp);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Data;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
[DataStreamUserRespresentation("bbo")]
|
||||
public class BBOStream : ViewStream, IWorker {
|
||||
@@ -109,7 +39,7 @@ namespace bts.SilverPine {
|
||||
private int _id = 0;
|
||||
IReadOnlyDictionary<SecurityKey, BookTuple> _cached_state = null;
|
||||
MarketDataClient _md_client;
|
||||
internal static IBlueTableSchema _bbo_schema = BlueDataUtility.form_schema("bbo",
|
||||
private readonly IBlueTableSchema _bbo_schema = BlueDataUtility.form_schema("bbo",
|
||||
Tuple.Create("id", TypeCode.Int32),
|
||||
Tuple.Create("sec_key", TypeCode.UInt32),
|
||||
Tuple.Create("sec", TypeCode.String),
|
||||
@@ -124,11 +54,9 @@ namespace bts.SilverPine {
|
||||
}
|
||||
|
||||
public BBOStream(ViewStreamDatabase vsd) {
|
||||
// bts.Log.Gen.info("BBOStream.cons");
|
||||
// _vsd = vsd;
|
||||
// _md_client = new MarketDataClient(new MDSource(TimeSpan.FromSeconds(0.5)));
|
||||
FakeBBOStream rs = new FakeBBOStream("Future", "CME", "ES", 5000, 0.25, vsd);
|
||||
mySetRealSource(rs);
|
||||
bts.Log.Gen.info("BBOStream.cons");
|
||||
_vsd = vsd;
|
||||
_md_client = new MarketDataClient(new MDSource(TimeSpan.FromSeconds(0.5)));
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using ZstdSharp.Unsafe;
|
||||
|
||||
public class DateTimeRange {
|
||||
public readonly DateTime range_beg;
|
||||
public readonly DateTime range_end;
|
||||
public DateTimeRange(DateTime range_beg_, DateTime range_end_) {
|
||||
range_beg = range_beg_;
|
||||
range_end = range_end_;
|
||||
}
|
||||
public static DateTimeRange parse(string range_beg_, string range_end_) {
|
||||
DateTime range_beg = String.IsNullOrEmpty(range_beg_) ? DateTime.MinValue : DateTime.Parse(range_beg_);
|
||||
DateTime range_end = String.IsNullOrEmpty(range_end_) ? DateTime.MaxValue : DateTime.Parse(range_end_);
|
||||
return new DateTimeRange(range_beg, range_end);
|
||||
}
|
||||
}
|
||||
|
||||
public class FutureBarsLoader {
|
||||
public static string get_db_table_name(BarSize bar_size, string symbol, bool is_continous) {
|
||||
switch (bar_size) {
|
||||
case BarSize.ONE_DAY: {
|
||||
if (is_continous) {
|
||||
return $"bars_future_{symbol}_continous_1day";
|
||||
} else
|
||||
return $"bars_future_{symbol}_all_1day";
|
||||
}
|
||||
case BarSize.ONE_MIN: {
|
||||
if (is_continous) {
|
||||
return $"bars_future_{symbol}_continous_1min";
|
||||
} else
|
||||
return $"bars_future_{symbol}_all_1min";
|
||||
}
|
||||
}
|
||||
Log.assert(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public enum BarSize {
|
||||
ONE_DAY = 0,
|
||||
ONE_MIN
|
||||
}
|
||||
|
||||
[DataStreamUserRespresentation("FuturesHistorical1DayBars")]
|
||||
public class FuturesHistorical1DayBarsStream : ViewStream {
|
||||
|
||||
// this gets the raw bars for a symbol (perhaps make it into a raw bars stream?)
|
||||
public FuturesHistorical1DayBarsStream(string symbol) :
|
||||
this(symbol, DateTime.MinValue, DateTime.MaxValue) { }
|
||||
|
||||
// creates the non raw stream (ie for tradable contract, or continous contract)
|
||||
public FuturesHistorical1DayBarsStream(string future_contract, DateTime range_beg, DateTime range_end)
|
||||
: this(new ContractUtils.FutureContract(future_contract), new DateTimeRange(range_beg, range_end)) { }
|
||||
|
||||
// this creates a tradable contracts bars streams or continous contracts stream. if get_all_rows is true,
|
||||
// it gets the raw table with all contracts for that symbol
|
||||
public FuturesHistorical1DayBarsStream(ContractUtils.FutureContract future_contract,
|
||||
DateTimeRange dt_range) {
|
||||
DateTime beg = dt_range.range_beg;//.ToUniversalTime(),
|
||||
DateTime end = dt_range.range_end;//.ToUniversalTime();
|
||||
beg = beg.Date;
|
||||
end = end.Date.Add(new TimeSpan(23, 59, 59));
|
||||
// this returns rows from beg and end inclusive
|
||||
Func<string, SQLiteStream> get_sqlite_str = (table_name) => {
|
||||
string range_beg_iso8601 = beg.ToString("yyyy-MM-ddTHH:mm:ss"),
|
||||
range_end_iso8601 = end.ToString("yyyy-MM-ddTHH:mm:ss");
|
||||
string sql_str = $"select * from {table_name} where ts_event >= '{range_beg_iso8601}' AND ts_event <= '{range_end_iso8601}'";
|
||||
return new SQLiteStream(SQLiteHelper.db_name, sql_str);
|
||||
};
|
||||
string symbol = future_contract.symbol();
|
||||
if (future_contract.wildcard_contract != null) {
|
||||
string table_name = FutureBarsLoader.get_db_table_name(BarSize.ONE_DAY, future_contract.symbol(), false);
|
||||
ViewStream rs = get_sqlite_str(table_name);
|
||||
//rs = new DateStandardizationStream(rs, "ts_event", DateConversion.ChopTime);
|
||||
mySetRealSource(rs);
|
||||
return;
|
||||
}
|
||||
if (future_contract.wildcard_contract != null) {
|
||||
string table_name = FutureBarsLoader.get_db_table_name(BarSize.ONE_DAY, future_contract.symbol(), false);
|
||||
ViewStream rs = get_sqlite_str(table_name);
|
||||
//rs = new DateStandardizationStream(rs, "ts_event", DateConversion.ChopTime);
|
||||
mySetRealSource(rs);
|
||||
return;
|
||||
}
|
||||
if (future_contract.is_continous_contract) {
|
||||
string table_name = FutureBarsLoader.get_db_table_name(BarSize.ONE_DAY, symbol, true);
|
||||
ViewStream rs = get_sqlite_str(table_name);
|
||||
//rs = new DateStandardizationStream(rs, "ts_event", DateConversion.ChopTime);
|
||||
mySetRealSource(rs);
|
||||
return;
|
||||
} else {
|
||||
string table_name = FutureBarsLoader.get_db_table_name(BarSize.ONE_DAY, future_contract.symbol(), false);
|
||||
ViewStream rs = get_sqlite_str(table_name);
|
||||
//rs = new DateStandardizationStream(rs, "ts_event", DateConversion.ChopTime);
|
||||
//TODO: filter it
|
||||
rs = new FilterStream(rs, $"symbol = '{future_contract.contract_text}'");
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DataStreamUserRespresentation("FuturesHistorical1MinBars")]
|
||||
public class FuturesHistorical1MinuteBarsStream : ViewStream {
|
||||
// same as the above but for one min
|
||||
// this gets the raw bars for a symbol
|
||||
public FuturesHistorical1MinuteBarsStream(string symbol) :
|
||||
this(symbol, DateTime.MinValue, DateTime.MaxValue) { }
|
||||
|
||||
// creates the non raw stream (ie for tradable contract, or continous contract)
|
||||
public FuturesHistorical1MinuteBarsStream(string future_contract, DateTime range_beg, DateTime range_end)
|
||||
: this(new ContractUtils.FutureContract(future_contract), new DateTimeRange(range_beg, range_end)) { }
|
||||
|
||||
// this creates a tradable contracts bars streams or continous contracts stream. if get_all_rows is true,
|
||||
// it gets the raw table with all contracts for that symbol
|
||||
public FuturesHistorical1MinuteBarsStream(ContractUtils.FutureContract future_contract,
|
||||
DateTimeRange dt_range) {
|
||||
Func<string, SQLiteStream> get_sqlite_str = (table_name) => {
|
||||
string range_beg_iso8601 = dt_range.range_beg.ToString("yyyy-MM-ddTHH:mm:ss"),
|
||||
range_end_iso8601 = dt_range.range_end.ToString("yyyy-MM-ddTHH:mm:ss");
|
||||
//string sql_str = $"select * from {table_name} where DATE(ts_event) >= '{range_beg_iso8601}' AND DATE(ts_event) <= '{range_end_iso8601}'";
|
||||
string sql_str = $"select * from {table_name} where ts_event >= '{range_beg_iso8601}' AND ts_event <= '{range_end_iso8601}'";
|
||||
return new SQLiteStream(SQLiteHelper.db_name, sql_str);
|
||||
};
|
||||
string symbol = future_contract.symbol();
|
||||
if (future_contract.wildcard_contract != null) {
|
||||
string table_name = FutureBarsLoader.get_db_table_name(BarSize.ONE_MIN, future_contract.symbol(), false);
|
||||
ViewStream rs = get_sqlite_str(table_name);
|
||||
mySetRealSource(rs);
|
||||
return;
|
||||
}
|
||||
if (future_contract.is_continous_contract) {
|
||||
string table_name = FutureBarsLoader.get_db_table_name(BarSize.ONE_MIN, symbol, true);
|
||||
ViewStream rs = get_sqlite_str(table_name);
|
||||
mySetRealSource(rs);
|
||||
return;
|
||||
} else {
|
||||
string table_name = FutureBarsLoader.get_db_table_name(BarSize.ONE_MIN, future_contract.symbol(), false);
|
||||
ViewStream rs = get_sqlite_str(table_name);
|
||||
// TODO: filter
|
||||
rs = new FilterStream(rs, $"symbol = '{future_contract.contract_text}'");
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DataStreamUserRespresentation("FutureHistoricalBars")]
|
||||
public class FutureHistoricalBarsStream : ViewStream {
|
||||
public FutureHistoricalBarsStream(string fut_contract, string range_beg, string range_end) {
|
||||
DateTime dt_range_beg = DateTime.Parse(range_beg);
|
||||
DateTime dt_range_end = DateTime.Parse(range_end);
|
||||
TimeSpan diff = dt_range_end - dt_range_beg;
|
||||
BarSize bar_size = diff < TimeSpan.FromDays(1.0) ? BarSize.ONE_MIN : BarSize.ONE_DAY;
|
||||
ViewStream rs = new FutureHistoricalBarsStream(fut_contract, bar_size.ToString(), dt_range_beg, dt_range_end);
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
public FutureHistoricalBarsStream(string fut_contract, string bar_size)
|
||||
: this(fut_contract, bar_size, DateTime.MinValue, DateTime.MaxValue) { }
|
||||
|
||||
public FutureHistoricalBarsStream(string fut_contract, string bar_size,
|
||||
string dt_range_beg, string dt_range_end)
|
||||
: this(fut_contract, bar_size, DateTime.Parse(dt_range_beg),
|
||||
DateTime.Parse(dt_range_end)) { }
|
||||
|
||||
public FutureHistoricalBarsStream(string fut_contract, string bar_size,
|
||||
DateTime dt_range_beg, DateTime dt_range_end)
|
||||
:
|
||||
this(new ContractUtils.FutureContract(fut_contract), Enum.Parse<BarSize>(bar_size, true),
|
||||
new DateTimeRange(dt_range_beg, dt_range_end)) { }
|
||||
|
||||
public FutureHistoricalBarsStream(ContractUtils.FutureContract fut_contract, BarSize bar_size,
|
||||
DateTimeRange dt_range) {
|
||||
switch (bar_size) {
|
||||
case BarSize.ONE_DAY: {
|
||||
ViewStream rs = new FuturesHistorical1DayBarsStream(fut_contract, dt_range);
|
||||
mySetRealSource(rs);
|
||||
break;
|
||||
}
|
||||
case BarSize.ONE_MIN: {
|
||||
ViewStream rs = new FuturesHistorical1MinuteBarsStream(fut_contract, dt_range);
|
||||
mySetRealSource(rs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DataStreamUserRespresentation("FuturePriceDiff")]
|
||||
public class FutureHistoricalBarsPriceDiffStream : ViewStream {
|
||||
|
||||
public FutureHistoricalBarsPriceDiffStream(string future_contract, string dt1, string dt2)
|
||||
:
|
||||
this(new ContractUtils.FutureContract(future_contract), DateTime.Parse(dt1), DateTime.Parse(dt2), "close", ViewStreamDatabase.instance) {
|
||||
}
|
||||
|
||||
|
||||
public FutureHistoricalBarsPriceDiffStream(string future_contract, DateTime dt1, DateTime dt2)
|
||||
:
|
||||
this(new ContractUtils.FutureContract(future_contract), dt1, dt2, "close", ViewStreamDatabase.instance) {
|
||||
}
|
||||
|
||||
public FutureHistoricalBarsPriceDiffStream(string future_contract, DateTime dt1, DateTime dt2, string col)
|
||||
:
|
||||
this(new ContractUtils.FutureContract(future_contract), dt1, dt2, col, ViewStreamDatabase.instance) {
|
||||
}
|
||||
|
||||
|
||||
public FutureHistoricalBarsPriceDiffStream(ContractUtils.FutureContract fc, DateTime dt1, DateTime dt2, string col, ViewStreamDatabase vsd) {
|
||||
BarSize bsize = dt2 - dt1 >= TimeSpan.FromDays(1.0) ? BarSize.ONE_DAY : BarSize.ONE_MIN;
|
||||
ViewStream rs = new FutureHistoricalBarsStream(fc, BarSize.ONE_DAY, new DateTimeRange(dt1, dt2));
|
||||
|
||||
rs = new ColumnDifferenceStream(rs, r => {
|
||||
DateTime r_dt = r.get_datetime("ts_event");
|
||||
var rv = dt1.Equals(r_dt);
|
||||
return rv;
|
||||
},
|
||||
//r => dt2.Equals(r.get_datetime("ts_event")), col, col);
|
||||
r => {
|
||||
DateTime r_dt = r.get_datetime("ts_event");
|
||||
var rv = dt2.Equals(r_dt);
|
||||
return rv;
|
||||
}, col, col);
|
||||
rs = new NewProjectStream(rs, "diff !");
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
|
||||
// takes the contract name and expands it into multuiple columns corresponding to the contracts.
|
||||
// the contract columns are a union, of all properties with some of them empty
|
||||
public class ContractExpanderStream : ViewStream {
|
||||
private static IBlueTableSchema map_schema(IBlueTableSchema schema) {
|
||||
return schema.add_column(TypeCode.String, "contract_type");
|
||||
}
|
||||
public ContractExpanderStream(ViewStream parent_str, string contract_col_name) {
|
||||
ViewStream rs = new MapStream(parent_str, (schema) => map_schema(schema),
|
||||
r => {
|
||||
string contract = r.get<string>(contract_col_name);
|
||||
var ct = ContractUtils.get_type(contract);
|
||||
MutableBlueRow rv = new MutableBlueRow(map_schema(r.schema), r);
|
||||
rv.setValue("contract_type", ct.ToString());
|
||||
return rv;
|
||||
});
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
using BCG;
|
||||
|
||||
namespace bts.SilverPine {
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
*Expression*
|
||||
----------------------------------------------------------------------
|
||||
//r=FutureHistoricalBars("ES*", "02/01/2024 09:30 AM", "02/01/2024 09:30 PM")
|
||||
r=FutureHistoricalBars("ES*","One_Day", 02/01/2024, 02/01/2025)
|
||||
r=contractExpander(r,"symbol")
|
||||
r=filter(r,"contract_type='FutureSpread'")
|
||||
r=aggregate(r,"symbol","volume:Sum","ts_event")
|
||||
r=aggregate(r,"volume_sum:Max")
|
||||
r=newProject(r,"volume_sum_max:volume symbol !")
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*Schema*
|
||||
----------------------------------------------------------------------
|
||||
symbol System.String
|
||||
id System.Int32
|
||||
volume System.Double
|
||||
*/
|
||||
|
||||
[DataStreamUserRespresentation("VolumeAgg")]
|
||||
public class VolumeAggregationStream : ViewStream {
|
||||
public VolumeAggregationStream(string future_contract, string contract_type, DateTime range_beg, DateTime range_end)
|
||||
: this(future_contract, contract_type, range_beg, range_end, ViewStreamDatabase.instance) { }
|
||||
|
||||
public VolumeAggregationStream(string future_contract, string contract_type, string range_beg, string range_end)
|
||||
:
|
||||
this(future_contract, contract_type, DateTime.Parse(range_beg), DateTime.Parse(range_end), ViewStreamDatabase.instance) { }
|
||||
|
||||
public VolumeAggregationStream(string future_contract, string contract_type, DateTime range_beg, DateTime range_end, ViewStreamDatabase db) {
|
||||
future_contract = future_contract.EndsWith("*") ? future_contract : future_contract + "*";
|
||||
ViewStream r;
|
||||
r = new FutureHistoricalBarsStream(future_contract,
|
||||
range_beg.ToString(), range_end.ToString());
|
||||
r = new ContractExpanderStream(r, "symbol");
|
||||
r = new FilterStream(r, $"contract_type='{contract_type}'");
|
||||
r = new NonIncGroupByStream(r, "symbol", "volume:Sum", "ts_event");
|
||||
r = new NonIncGroupByStream(r, "volume_sum:Max");
|
||||
r = new NewProjectStream(r, "volume_sum_max:volume symbol !");
|
||||
mySetRealSource(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using bts;
|
||||
|
||||
namespace bts.SilverPine {
|
||||
public static class IndicatorCalc {
|
||||
public static double calculate_pearson_correlation(List<double> prices1, List<double> prices2) {
|
||||
if (prices1 == null)
|
||||
throw new ArgumentNullException(nameof(prices1), "First price list cannot be null.");
|
||||
if (prices2 == null)
|
||||
throw new ArgumentNullException(nameof(prices2), "Second price list cannot be null.");
|
||||
if (prices1.Count != prices2.Count)
|
||||
throw new ArgumentException("Price lists must have the same number of elements.");
|
||||
if (prices1.Count < 2)
|
||||
throw new ArgumentException("At least two data points are required to calculate correlation.");
|
||||
|
||||
int n = prices1.Count;
|
||||
double sumX = 0;
|
||||
double sumY = 0;
|
||||
double sumX2 = 0;
|
||||
double sumY2 = 0;
|
||||
double sumXY = 0;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
double x = prices1[i];
|
||||
double y = prices2[i];
|
||||
|
||||
sumX += x;
|
||||
sumY += y;
|
||||
sumX2 += x * x;
|
||||
sumY2 += y * y;
|
||||
sumXY += x * y;
|
||||
}
|
||||
|
||||
double numerator = (n * sumXY) - (sumX * sumY);
|
||||
double denominatorPart1 = (n * sumX2) - (sumX * sumX);
|
||||
double denominatorPart2 = (n * sumY2) - (sumY * sumY);
|
||||
double denominator = Math.Sqrt(denominatorPart1 * denominatorPart2);
|
||||
|
||||
if (denominator == 0)
|
||||
throw new InvalidOperationException("Denominator is zero, correlation is undefined.");
|
||||
|
||||
return numerator / denominator;
|
||||
}
|
||||
public static double calculate_VWAP(List<Tuple<int, double>> volumePriceData) {
|
||||
Log.Gen.info($"ChartingHelper.calculate_VWAP n_vals: {volumePriceData.Count}");
|
||||
double totalVolume = 0;
|
||||
double totalPriceVolume = 0;
|
||||
|
||||
foreach (var data in volumePriceData) {
|
||||
int volume = data.Item1; // Volume
|
||||
double price = data.Item2; // Closing price
|
||||
|
||||
// Accumulate total price-volume (price * volume) and total volume
|
||||
totalPriceVolume += price * volume;
|
||||
totalVolume += volume;
|
||||
}
|
||||
|
||||
// VWAP is totalPriceVolume divided by totalVolume
|
||||
return totalVolume > 0 ? totalPriceVolume / totalVolume : 0;
|
||||
}
|
||||
|
||||
// Calculate Volatility (Standard Deviation of returns) over a given period
|
||||
public static double calculate_volatility(IList<double> prices, int period = 252) {
|
||||
if (prices == null || prices.Count < period + 1) {
|
||||
throw new ArgumentException("Insufficient data to calculate volatility.");
|
||||
}
|
||||
|
||||
// Calculate daily returns
|
||||
var returns = new List<double>();
|
||||
for (int i = 1; i < prices.Count; i++) {
|
||||
double dailyReturn = (prices[i] - prices[i - 1]) / prices[i - 1];
|
||||
returns.Add(dailyReturn);
|
||||
}
|
||||
|
||||
// Get the returns over the desired period
|
||||
var recentReturns = returns.Skip(returns.Count - period).Take(period).ToList();
|
||||
|
||||
// Calculate the mean of returns
|
||||
double meanReturn = recentReturns.Average();
|
||||
|
||||
// Calculate the variance (sum of squared differences from the mean)
|
||||
double variance = recentReturns.Sum(r => Math.Pow(r - meanReturn, 2)) / period;
|
||||
|
||||
// Volatility is the square root of variance (standard deviation)
|
||||
double volatility = Math.Sqrt(variance);
|
||||
|
||||
// Annualize volatility by multiplying by the square root of 252 (number of trading days in a year)
|
||||
return volatility * Math.Sqrt(252);
|
||||
}
|
||||
|
||||
// Calculate SMA (Simple Moving Average) for a given period (e.g., 50, 100, or 200)
|
||||
public static double calculate_SMA(IList<double> prices, int period = 50) {
|
||||
if (prices == null || prices.Count < period) {
|
||||
throw new ArgumentException("Insufficient data to calculate SMA.");
|
||||
}
|
||||
|
||||
// Sum up the prices over the given period
|
||||
double sum = prices.Skip(prices.Count - period).Take(period).Sum();
|
||||
|
||||
// Return the average
|
||||
return sum / period;
|
||||
}
|
||||
|
||||
public static double calculate_RSI(IList<double> prices, int period = 14) {
|
||||
if (prices == null || prices.Count < period + 1) {
|
||||
return Double.NaN;
|
||||
//throw new ArgumentException("Insufficient data to calculate RSI.");
|
||||
}
|
||||
|
||||
double gainSum = 0;
|
||||
double lossSum = 0;
|
||||
|
||||
// Calculate the initial average gain and loss over the first 'period' days
|
||||
for (int i = 1; i <= period; i++) {
|
||||
double change = prices[i] - prices[i - 1];
|
||||
if (change > 0) {
|
||||
gainSum += change;
|
||||
} else {
|
||||
lossSum -= change; // Subtract since loss is negative
|
||||
}
|
||||
}
|
||||
|
||||
double avgGain = gainSum / period;
|
||||
double avgLoss = lossSum / period;
|
||||
|
||||
// Calculate RSI using smoothed values
|
||||
for (int i = period + 1; i < prices.Count; i++) {
|
||||
double change = prices[i] - prices[i - 1];
|
||||
if (change > 0) {
|
||||
avgGain = (avgGain * (period - 1) + change) / period;
|
||||
avgLoss = (avgLoss * (period - 1)) / period;
|
||||
} else {
|
||||
avgGain = (avgGain * (period - 1)) / period;
|
||||
avgLoss = (avgLoss * (period - 1) - change) / period;
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent division by zero in case of no losses
|
||||
if (avgLoss == 0) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
double rs = avgGain / avgLoss;
|
||||
double rsi = 100 - (100 / (1 + rs));
|
||||
|
||||
return rsi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using bts;
|
||||
|
||||
[DataStreamUserRespresentation("DailyChange")]
|
||||
// takes in the ohlcv stream and computes the closing vs closing difference
|
||||
public class DailyChange : ViewStream {
|
||||
public DailyChange(ViewStream ohlc_str) {
|
||||
GlobalMapStream rs = new GlobalMapStream(ohlc_str, "ts_event", "contract",
|
||||
(rows, idx) => {
|
||||
double daily_change = Double.NaN;
|
||||
double daily_change_perc = Double.NaN;
|
||||
IBlueRow ir = rows.ElementAt((int)idx);
|
||||
if (idx < rows.Count - 1) {
|
||||
IBlueRow pr = rows.ElementAt((int)idx + 1);
|
||||
double close = ir.get<double>("close"), prev_close = pr.get<double>("close");
|
||||
daily_change = close - prev_close;
|
||||
daily_change_perc = 100.0 * daily_change / prev_close;
|
||||
}
|
||||
IBlueTableSchema schema = ir.schema.add_columns(Tuple.Create(typeof(double), "daily_change"));
|
||||
schema = schema.add_columns(Tuple.Create(typeof(double), "daily_change_perc"));
|
||||
MutableBlueRow nr = new MutableBlueRow(schema, ir);
|
||||
nr.setValue("daily_change", daily_change);
|
||||
nr.setValue("daily_change_perc", daily_change_perc);
|
||||
return nr;
|
||||
});
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using System;
|
||||
using BCG.Utilities.General;
|
||||
using System.Data;
|
||||
using bts.api.domain;
|
||||
|
||||
namespace BCG {
|
||||
// Stream computes the EMA of a column in any stream. It takes in the base stream, the column name and a smoothing factor
|
||||
// as args, and create one row with an ema column, which is the running ema of the column provided
|
||||
[DataStreamUserRespresentation("ema")]
|
||||
public class EMAStream : ViewStream {
|
||||
private ViewStream _stream;
|
||||
private readonly string _col_name;
|
||||
private EMACalculator _calc;
|
||||
private readonly IBlueTableSchema _schema = BlueDataUtility.form_schema(
|
||||
"SMA", Tuple.Create("id", TypeCode.Int32),
|
||||
Tuple.Create("ema", TypeCode.Double));
|
||||
|
||||
public EMAStream(ViewStream stream, string col_name, double smoothing_factor) {
|
||||
_col_name = col_name;
|
||||
_stream = stream;
|
||||
_calc = new EMACalculator(smoothing_factor);
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_stream.onChange += new ChangeDelegate(_onstream_change);
|
||||
}
|
||||
protected override void myOnLastSubscriber() {
|
||||
_stream.onChange -= new ChangeDelegate(_onstream_change);
|
||||
}
|
||||
|
||||
|
||||
private void _onstream_change(object o) {
|
||||
|
||||
DataPacket dp = o as DataPacket;
|
||||
foreach (IBlueRow r in dp.addedRows) {
|
||||
double price = r.get<double>(_col_name);
|
||||
if (!Double.IsNaN(price))
|
||||
_calc.add(price);
|
||||
}
|
||||
IBlueRow nr = new BlueRow(_schema, 0, _calc.get_EMA());
|
||||
BlueTable state = new BlueTable(_schema);
|
||||
state.addRow(nr);
|
||||
DataPacket dp_out = BlueDataUtility.build_dp_inc(state, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using bts;
|
||||
|
||||
[DataStreamUserRespresentation("RSI")]
|
||||
public class RSIStream : ViewStream {
|
||||
// public RSIStream(ViewStreamDatabase vsd, string symbol, int n_days) {
|
||||
|
||||
// }
|
||||
|
||||
public RSIStream(ViewStream instrument_ohlc_str, int period) {
|
||||
GlobalMapStream rs = new GlobalMapStream(instrument_ohlc_str, "ts_event", "contract",
|
||||
(rows, idx) => {
|
||||
IBlueRow ir = rows.ElementAt((int)idx);
|
||||
IEnumerable<double> closes = BlueDataUtility.get_colvalues<double>(rows, "close", (int)idx + 1, period + 2);
|
||||
double rsi = IndicatorCalc.calculate_RSI(closes.ToList(), period);
|
||||
IBlueTableSchema schema = ir.schema.add_columns(Tuple.Create(typeof(double), "rsi"));
|
||||
MutableBlueRow nr = new MutableBlueRow(schema, ir);
|
||||
nr.setValue("rsi", rsi);
|
||||
return nr;
|
||||
});
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
Whitespace-only changes.
@@ -0,0 +1,87 @@
|
||||
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using System;
|
||||
using BCG.Utilities.General;
|
||||
using System.Data;
|
||||
using bts.api.domain;
|
||||
using System.Reactive.Concurrency;
|
||||
using mbts.spark;
|
||||
|
||||
namespace BCG {
|
||||
// Stream computes the EMA of a column in any stream. It takes in the base stream, the column name and a smoothing factor
|
||||
// as args, and create one row with an ema column, which is the running ema of the column provided
|
||||
[DataStreamUserRespresentation("renko")]
|
||||
public class RenkoStream : ViewStream {
|
||||
private ViewStream _stream;
|
||||
private readonly string _col_name;
|
||||
private readonly double _brick_sz;
|
||||
private RenkoCalculator _calc;
|
||||
|
||||
private BlueTable _table = new BlueTable(BlueDataUtility.form_schema(
|
||||
"Renko", Tuple.Create("id", TypeCode.Int32),
|
||||
Tuple.Create("entry_price", TypeCode.Double),
|
||||
Tuple.Create("current_price", TypeCode.Double),
|
||||
Tuple.Create("brick_low", TypeCode.Double),
|
||||
Tuple.Create("brick_high", TypeCode.Double),
|
||||
Tuple.Create("brick_transition", TypeCode.String),
|
||||
Tuple.Create("n_updates_within", TypeCode.Int32)
|
||||
));
|
||||
|
||||
public RenkoStream(ViewStream stream, string col_name, double brick_sz) {
|
||||
_col_name = col_name;
|
||||
_stream = stream;
|
||||
_brick_sz = brick_sz;
|
||||
_calc = new RenkoCalculator(brick_sz);
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_stream.onChange += _onstream_change;
|
||||
}
|
||||
protected override void myOnLastSubscriber() {
|
||||
_stream.onChange -= new ChangeDelegate(_onstream_change);
|
||||
}
|
||||
|
||||
|
||||
private IBlueRow _remove_row(RenkoBrick brick) {
|
||||
var row = _table[brick.id];
|
||||
_table.deleteRow(row);
|
||||
return row;
|
||||
}
|
||||
|
||||
private IBlueRow _create_new_row(RenkoBrick brick) {
|
||||
return new BlueRow(_table.schema, brick.id,
|
||||
brick.entry_price, brick.current_price, brick.low, brick.high,
|
||||
brick.entry.ToString(), brick.n_updates);
|
||||
}
|
||||
|
||||
private void _onstream_change(object o) {
|
||||
// what feeds in is a time series
|
||||
BlueTable deleted_rows = new BlueTable(_table.schema);
|
||||
BlueTable added_rows = new BlueTable(_table.schema);
|
||||
DataPacket dp = o as DataPacket;
|
||||
foreach (IBlueRow r in dp.addedRows) {
|
||||
double val = r.get<double>(_col_name);
|
||||
var new_bricks = _calc.update(val);
|
||||
if (new_bricks.Count() > 0) {
|
||||
foreach (var nb in new_bricks) {
|
||||
var new_row = _create_new_row(nb);
|
||||
added_rows.addRow(new_row);
|
||||
_table.addRow(new_row);
|
||||
}
|
||||
} else {
|
||||
var existing_brick = _calc.current_brick;
|
||||
var del_row = _remove_row(existing_brick);
|
||||
deleted_rows.addRow(del_row);
|
||||
var new_row = _create_new_row(existing_brick);
|
||||
added_rows.addRow(new_row);
|
||||
_table.addRow(new_row);
|
||||
}
|
||||
}
|
||||
myFireEvent(new DataPacket(_table, added_rows, deleted_rows));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,24 +1,54 @@
|
||||
namespace bts.SilverPine {
|
||||
using bts;
|
||||
using BCG;
|
||||
|
||||
[DataStreamUserRespresentation("SMA")]
|
||||
public class SMAStream : ViewStream {
|
||||
public SMAStream(ViewStream ohlc_str, int period) {
|
||||
GlobalMapStream rs = new GlobalMapStream(ohlc_str, "ts_event", "contract",
|
||||
(rows, idx) => {
|
||||
IBlueRow ir = rows.ElementAt((int)idx);
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
|
||||
using System;
|
||||
using BCG.Utilities.General;
|
||||
using System.Data;
|
||||
using bts.api.domain;
|
||||
|
||||
namespace BCG {
|
||||
// Stream computes the SMA of a column in any stream. It takes in the base stream, the column namer and a smoothing factor
|
||||
// as args, and create one row with an sma column, which is the running ema of the column provided
|
||||
[DataStreamUserRespresentation("sma")]
|
||||
public class SMAStream : ViewStream {
|
||||
private ViewStream _stream;
|
||||
private readonly string _col_name;
|
||||
private Chartutils.SMACalculator _calc;
|
||||
private readonly IBlueTableSchema _schema = BlueDataUtility.form_schema(
|
||||
"SMA", Tuple.Create("id", TypeCode.Int32),
|
||||
Tuple.Create("sma", TypeCode.Double));
|
||||
|
||||
public SMAStream(ViewStream stream, string col_name, int window_size) {
|
||||
_col_name = col_name;
|
||||
_stream = stream;
|
||||
_calc = new Chartutils.SMACalculator(window_size);
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_stream.onChange += new ChangeDelegate(_onstream_change);
|
||||
}
|
||||
protected override void myOnLastSubscriber() {
|
||||
_stream.onChange -= new ChangeDelegate(_onstream_change);
|
||||
}
|
||||
|
||||
|
||||
private void _onstream_change(object o) {
|
||||
|
||||
DataPacket dp = o as DataPacket;
|
||||
foreach (IBlueRow r in dp.addedRows) {
|
||||
double price = r.get<double>(_col_name);
|
||||
if (!Double.IsNaN(price))
|
||||
_calc.add(r.get<double>(_col_name));
|
||||
}
|
||||
IBlueRow nr = new BlueRow(_schema, 0, _calc.get_SMA());
|
||||
BlueTable state = new BlueTable(_schema);
|
||||
state.addRow(nr);
|
||||
DataPacket dp_out = BlueDataUtility.build_dp_inc(state, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IEnumerable<double> closes = BlueDataUtility.get_colvalues<double>(rows, "close", (int)idx + 1, period + 2);
|
||||
double rsi = IndicatorCalc.calculate_RSI(closes.ToList(), period);
|
||||
IBlueTableSchema schema = ir.schema.add_columns(Tuple.Create(typeof(double), "rsi"));
|
||||
MutableBlueRow nr = new MutableBlueRow(schema, ir);
|
||||
nr.setValue("rsi", rsi);
|
||||
return nr;
|
||||
});
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
|
||||
namespace BCG {
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
*Expression*
|
||||
----------------------------------------------------------------------
|
||||
r=filter(bbo(),"sec='BTC-PERPETUAL'")
|
||||
r=math(r,"wt_mid_price = (bid_price*bid_sz + ask_price*ask_sz)/(bid_sz+ask_sz)")
|
||||
r=timeSeries(r)
|
||||
r=math(r,"sz = (bid_sz + ask_sz) * 1.0")
|
||||
r=filter(r,"sz > 0")
|
||||
r=renko(r,"wt_mid_price", 2.0)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*Schema*
|
||||
----------------------------------------------------------------------
|
||||
id System.Int32
|
||||
entry_price System.Double
|
||||
current_price System.Double
|
||||
brick_low System.Double
|
||||
brick_high System.Double
|
||||
brick_transition System.String
|
||||
n_updates_within System.Int32
|
||||
*/
|
||||
|
||||
|
||||
public class SecurityRenkoStream : ViewStream {
|
||||
public SecurityRenkoStream(int sec_key, double brick_sz) {
|
||||
ViewStream r;
|
||||
|
||||
r = new FilterStream(new BBOStream(),
|
||||
$"sec_key={sec_key}");
|
||||
r = new MathStream(r,
|
||||
"wt_mid_price = (bid_price*bid_sz + ask_price*ask_sz)/(bid_sz+ask_sz)");
|
||||
r = new TimeSeriesStream(r);
|
||||
r = new MathStream(r,
|
||||
"sz = (bid_sz + ask_sz) * 1.0");
|
||||
r = new FilterStream(r,
|
||||
"sz > 0");
|
||||
r = new RenkoStream(r,
|
||||
"wt_mid_price",
|
||||
brick_sz);
|
||||
|
||||
|
||||
mySetRealSource(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using MathNet.Numerics.Statistics;
|
||||
|
||||
// calculates the reazlied standard deviation of a series of prices
|
||||
public class StandardDeviationStream : ViewStream {
|
||||
public StandardDeviationStream(string symbol, string std_dev_period)
|
||||
:
|
||||
this(symbol, TimeBasedFilter.parse_duration(std_dev_period)) { }
|
||||
|
||||
public StandardDeviationStream(string symbol, TimeSpan std_dev_period) {
|
||||
// since this is a 1_day bar str, 90 rows => 90 days, so no need to filter
|
||||
int n_days = std_dev_period.Days;
|
||||
ViewStream ohlcv_str = new FuturesActiveContractStream(symbol);
|
||||
IBlueTableSchema out_schema = null;
|
||||
int id = 0;
|
||||
Func<List<IBlueRow>, uint, IBlueRow> find_std_dev = (rows, idx) => {
|
||||
int iidx = Convert.ToInt32(idx);
|
||||
if (rows == null || rows.Count == 0)
|
||||
return null;
|
||||
IBlueRow ir = rows.ElementAt(iidx);
|
||||
out_schema = out_schema ?? ir.schema.add_column(TypeCode.Double, "std_dev");
|
||||
MutableBlueRow rv = new MutableBlueRow(out_schema, ir);
|
||||
rv.setValue("std_dev", Double.NaN);
|
||||
IEnumerable<double> last_n_close_prices = rows.Skip(iidx).Take(n_days).Select(r => r.get<double>("close"));
|
||||
if (last_n_close_prices.Count() >= n_days) {
|
||||
double std_dev = MathNet.Numerics.Statistics.Statistics.StandardDeviation(last_n_close_prices);
|
||||
rv.setValue("std_dev", std_dev);
|
||||
}
|
||||
//rv.setValue("id", id++);
|
||||
return rv;
|
||||
};
|
||||
ViewStream rs = new GlobalMapStream(ohlcv_str, "ts_event", find_std_dev);
|
||||
rs = new NullFilterStream(rs, "std_dev", true);
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
using BCG;
|
||||
using BCG.Utilities.General;
|
||||
|
||||
using System;
|
||||
|
||||
namespace bts {
|
||||
[DataStreamUserRespresentation("tradebars")]
|
||||
public class TradeBarsStream : ViewStream, IWorker {
|
||||
|
||||
public class TradeBar {
|
||||
static double[] calculate_log_returns(double[] prices) {
|
||||
// Calculate logarithmic returns
|
||||
double[] returns = new double[prices.Length - 1];
|
||||
for (int i = 1; i < prices.Length; i++) {
|
||||
returns[i - 1] = Math.Log(prices[i] / prices[i - 1]);
|
||||
}
|
||||
return returns;
|
||||
}
|
||||
|
||||
static double calculate_volatility(double[] returns) {
|
||||
// Calculate standard deviation of logarithmic returns
|
||||
double mean = returns.Average();
|
||||
double sum_of_squares = returns.Sum(x => Math.Pow(x - mean, 2));
|
||||
double variance = sum_of_squares / (returns.Length - 1);
|
||||
double volatility = Math.Sqrt(variance);
|
||||
|
||||
return volatility;
|
||||
}
|
||||
public void add_trade(IBlueRow r) {
|
||||
double price = r.get<double>("price");
|
||||
//prices.Add(price);
|
||||
double qty = r.get<double>(col_name: "qty");
|
||||
if (n_entries == 0) {
|
||||
open = price;
|
||||
low = price < low ? price : low;
|
||||
high = price > high ? price : high;
|
||||
}
|
||||
n_entries++;
|
||||
volume += qty;
|
||||
vwap_sum += price * qty;
|
||||
close = price;
|
||||
if ("Buy".Equals(r.get<string>("aggressor"))) {
|
||||
n_buys_aggs++;
|
||||
} else {
|
||||
n_sell_aggs++;
|
||||
}
|
||||
}
|
||||
private List<double> prices = new List<double>();
|
||||
public readonly string security;
|
||||
public double low = Double.MaxValue, high, open, close, median, std_dev, vwap_sum, volume;
|
||||
public uint n_buys_aggs, n_sell_aggs, n_entries;
|
||||
public DateTime bar_start = DateTime.Now;
|
||||
public TradeBar(string security_) {
|
||||
security = security_;
|
||||
}
|
||||
public double volatility {
|
||||
get {
|
||||
//if (prices.Count == 1)
|
||||
return 0.0;
|
||||
var log_returns = calculate_log_returns(prices.ToArray());
|
||||
return calculate_volatility(log_returns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly int _bar_period_seconds;
|
||||
private readonly ViewStreamDatabase _vsd;
|
||||
private ViewStream _timesales_stream;
|
||||
private ViewStream _bbo_stream;
|
||||
private IDictionary<uint, TradeBar> _sec_bar_map = new Dictionary<uint, TradeBar>();
|
||||
private bool _dirty = false;
|
||||
private TimeSpan _fire_period;
|
||||
private DateTime _last_fire_time = DateTime.Now;
|
||||
private BlueTable _table = new BlueTable(BlueDataUtility.form_schema("TradeBars",
|
||||
Tuple.Create("id", TypeCode.Int32),
|
||||
Tuple.Create("bar_start", TypeCode.DateTime),
|
||||
Tuple.Create("bar_end", TypeCode.DateTime),
|
||||
Tuple.Create("day_of_week", TypeCode.String),
|
||||
Tuple.Create("n_trades", TypeCode.UInt32),
|
||||
Tuple.Create("security", TypeCode.String),
|
||||
Tuple.Create("sec_key", TypeCode.UInt32),
|
||||
Tuple.Create("low", TypeCode.Double),
|
||||
Tuple.Create("high", TypeCode.Double),
|
||||
Tuple.Create("open", TypeCode.Double),
|
||||
Tuple.Create("close", TypeCode.Double),
|
||||
Tuple.Create("vwap_sum", TypeCode.Double),
|
||||
Tuple.Create("volume", TypeCode.Double),
|
||||
Tuple.Create("n_buy_aggs", TypeCode.UInt32),
|
||||
Tuple.Create("n_sell_aggs", TypeCode.UInt32),
|
||||
Tuple.Create("volatility", TypeCode.Double)));
|
||||
|
||||
|
||||
public TradeBarsStream(int bar_period_seconds)
|
||||
: this(bar_period_seconds, ViewStreamDatabase.instance) { }
|
||||
public TradeBarsStream(int bar_period_seconds, ViewStreamDatabase vsd) {
|
||||
_vsd = vsd;
|
||||
_bar_period_seconds = bar_period_seconds;
|
||||
_timesales_stream = new TimeSalesStream(10000, vsd);
|
||||
_fire_period = TimeSpan.FromSeconds(bar_period_seconds);
|
||||
_bbo_stream = new BBOStream(_vsd);
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_timesales_stream.onChange += _on_timesales;
|
||||
_bbo_stream.onChange += _on_bbo;
|
||||
_vsd.addWorker(this);
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
_vsd.removeWorker(this);
|
||||
_timesales_stream.onChange -= _on_timesales;
|
||||
_bbo_stream.onChange -= _on_bbo;
|
||||
}
|
||||
|
||||
public void doWork() {
|
||||
if (DateTime.Now - _last_fire_time > _fire_period) {
|
||||
if (_dirty) {
|
||||
_dirty = false;
|
||||
_last_fire_time = DateTime.Now;
|
||||
BlueTable added_rows = new BlueTable(_table.schema);
|
||||
foreach (var kv in _sec_bar_map) {
|
||||
var sec_key = kv.Key;
|
||||
var tbar = kv.Value;
|
||||
IBlueRow new_row = new BlueRow(_table.schema, _table.Count, tbar.bar_start, DateTime.Now,
|
||||
tbar.bar_start.DayOfWeek.ToString(),
|
||||
tbar.n_entries, tbar.security, sec_key, tbar.low, tbar.high, tbar.open,
|
||||
tbar.close, tbar.vwap_sum, tbar.volume, tbar.n_sell_aggs, tbar.n_sell_aggs,
|
||||
tbar.volatility);
|
||||
added_rows.addRow(new_row);
|
||||
_table.addRow(new_row);
|
||||
}
|
||||
_sec_bar_map.Clear();
|
||||
DataPacket dp_out = new DataPacket(_table, added_rows, new BlueTable(_table.schema));
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void _on_timesales(object obj) {
|
||||
DataPacket dp = obj as DataPacket;
|
||||
foreach (IBlueRow r in dp.addedRows) {
|
||||
uint sec_key = r.get<UInt32>("sec_key");
|
||||
TradeBar tbar = null;
|
||||
if (!_sec_bar_map.TryGetValue(sec_key, out tbar)) {
|
||||
tbar = new TradeBar(r.get<string>("sec"));
|
||||
_sec_bar_map.Add(sec_key, tbar);
|
||||
}
|
||||
_dirty = true;
|
||||
tbar.add_trade(r);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void _on_bbo(object obj) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
// namespace bts.SilverPine {
|
||||
// using bts;
|
||||
// using BCG;
|
||||
// using MongoDB.Driver.Linq;
|
||||
// using System.ComponentModel.DataAnnotations;
|
||||
// using ZstdSharp.Unsafe;
|
||||
|
||||
// [DataStreamUserRespresentation("VWAP")]
|
||||
// public class VWAPStream : ViewStream {
|
||||
// // returns the VWAP stream for each contract
|
||||
// private static ViewStream build_vwap_stream(string symbol, DateTime begin_dt, DateTime end_dt) {
|
||||
// var ohlcv_params = OHLCVStream.get_params(begin_dt, end_dt);
|
||||
// ViewStream ohlc_str = new OHLCVStream(symbol, ohlcv_params);
|
||||
// // stream is grouped per contract and then vwap is calculated per contract
|
||||
// GlobalMapStream rs = new GlobalMapStream(ohlc_str, "ts_event", "contract",
|
||||
// (rows, idx) => {
|
||||
// Log.Gen.info($"VWAPStream.GlobalMapStream delegate n_rows: {rows.Count} idx: {idx}");
|
||||
// IBlueRow ir = rows.ElementAt((int)idx);
|
||||
// var sel_rows = rows.Skip((int)idx).Where(r => r.get_datetime("ts_event") >= end_dt && r.get_datetime("ts_event") <= begin_dt);
|
||||
// var volumeprices = sel_rows.Select(r => Tuple.Create(r.get<int>("volume"), r.get<double>("close"))).ToList();
|
||||
// double vwap = IndicatorCalc.calculate_VWAP(volumeprices);
|
||||
// IBlueTableSchema schema = ir.schema.add_columns(Tuple.Create(typeof(double), "vwap"));
|
||||
// MutableBlueRow nr = new MutableBlueRow(schema, ir);
|
||||
// //vwap = -313.987;
|
||||
// nr.setValue("vwap", vwap);
|
||||
// return nr;
|
||||
// });
|
||||
// return rs;
|
||||
// }
|
||||
// // the args want dt1 > dt2, if its nto we, swap them
|
||||
// static void swap_if_necessary(ref DateTime dt1, ref DateTime dt2) {
|
||||
// if (dt1 < dt2) {
|
||||
// DateTime aux = dt1;
|
||||
// dt1 = dt2;
|
||||
// dt2 = aux;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // this assumes the ohlc_str has diff contracts
|
||||
// public VWAPStream(string symbol_or_contract, DateTime begin_dt, DateTime end_dt) {
|
||||
// swap_if_necessary(ref begin_dt, ref end_dt);
|
||||
// Tuple<ContractUtils.ContractCategory, string> ccat_sym_contr = ContractUtils.get_symbol_category(symbol_or_contract);
|
||||
// string symbol = String.Empty;
|
||||
// symbol = ccat_sym_contr.Item2;
|
||||
// var ohlcv_params = OHLCVStream.get_params(begin_dt, end_dt);
|
||||
// ViewStream vwap_str = build_vwap_stream(symbol, begin_dt, end_dt);
|
||||
// // vwap_str now has vwap for all contracts. if the arg was a symbol, we need to filter it for the active contract,
|
||||
// // whihc we do with FutureActivesContractStream. If the arg was a contract we'll simply filter it
|
||||
// ViewStream rs = vwap_str;
|
||||
// switch (ccat_sym_contr.Item1) {
|
||||
// case ContractUtils.ContractCategory.FutureString:
|
||||
// case ContractUtils.ContractCategory.SpreadString:
|
||||
// rs = new FilterStream(vwap_str, r => r.get<string>("contract").CompareTo(ccat_sym_contr.Item2) == 0);
|
||||
// break;
|
||||
// case ContractUtils.ContractCategory.Symbol:
|
||||
// rs = new FuturesActiveContractStream(vwap_str);
|
||||
// break;
|
||||
// }
|
||||
// rs = new FilterStream(rs, r => r.get_datetime("ts_event").CompareTo(begin_dt) == 0);
|
||||
// rs = new NewProjectStream(rs, "! vwap");
|
||||
// mySetRealSource(rs);
|
||||
// }
|
||||
|
||||
// public VWAPStream(string symbol_or_contract, string begin_dt, string end_dt)
|
||||
// :
|
||||
// this(symbol_or_contract, DateTime.Parse(begin_dt), DateTime.Parse(end_dt)) { }
|
||||
// }
|
||||
// }
|
||||
|
||||
using System;
|
||||
|
||||
using BCG;
|
||||
|
||||
using bts.api;
|
||||
|
||||
namespace bts.SilverPine {
|
||||
/*
|
||||
----------------------------------------------------------------------
|
||||
*Expression*
|
||||
----------------------------------------------------------------------
|
||||
//nl("Find Settlement price of the SP500 future in the first week of 2023.")
|
||||
|
||||
r=FutureHistoricalBars("ES", "One_Day", "1/1/2024", "2/1/2024")
|
||||
r=math(r, "vprice = volume * close")
|
||||
r=aggregate(r, "vprice:Sum, volume:Sum")
|
||||
r=math(r, "vwap = vprice_sum / volume_sum")
|
||||
r=newProject(r, "vwap !")
|
||||
|
||||
----------------------------------------------------------------------
|
||||
*Schema*
|
||||
----------------------------------------------------------------------
|
||||
id System.Int32
|
||||
vwap System.Double
|
||||
*/
|
||||
|
||||
[DataStreamUserRespresentation("VWAP")]
|
||||
public class VWAPStream : ViewStream {
|
||||
public VWAPStream(string symbol_or_contract, DateTime beg_dt, DateTime end_dt)
|
||||
:
|
||||
this(symbol_or_contract, beg_dt, end_dt, ViewStreamDatabase.instance) { }
|
||||
|
||||
public VWAPStream(string symbol_or_contract, DateTime beg_dt, DateTime end_dt, ViewStreamDatabase db) {
|
||||
var fc = new ContractUtils.FutureContract(symbol_or_contract);
|
||||
ViewStream r = new FutureHistoricalBarsStream(fc, BarSize.ONE_DAY, new DateTimeRange(beg_dt, end_dt));
|
||||
|
||||
r = new MathStream(r,
|
||||
"vprice = volume * close");
|
||||
r = new NonIncGroupByStream(r,
|
||||
"vprice:Sum, volume:Sum");
|
||||
r = new MathStream(r,
|
||||
"vwap = vprice_sum / volume_sum");
|
||||
r = new NewProjectStream(r,
|
||||
"vwap !");
|
||||
mySetRealSource(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
[DataStreamUserRespresentation("Events")]
|
||||
public class EventsStream : ViewStream {
|
||||
public EventsStream(string event_type) : this(ViewStreamDatabase.instance, event_type) { }
|
||||
|
||||
public EventsStream(ViewStreamDatabase vsd, string event_type) {
|
||||
ViewStream rs =
|
||||
new SQLiteStream("Data Source=C:\\Users\\m_tah\\development\\data\\stream_data.db;Version=3;",
|
||||
"select * from events");
|
||||
if (!String.IsNullOrEmpty(event_type)) {
|
||||
rs = new FilterStream(rs, r => String.Compare(event_type, r.get<string>("event_type"), true) == 0);
|
||||
}
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using bts;
|
||||
// Given volume data per date for all futures (all exps + spreads) it selects the
|
||||
// the future with the highest volume
|
||||
[DataStreamUserRespresentation("FuturesActiveContract")]
|
||||
public class FuturesActiveContractStream : ViewStream, INonIncGroupByEvaluator {
|
||||
|
||||
public FuturesActiveContractStream(string future_name)
|
||||
// the active contract's resoulution is a day, so we used
|
||||
: this(new OHLCVStream(future_name,
|
||||
// uses Historic Daily bars to find the acive contract
|
||||
new OHLCVStream.OHLCVParams(OHLCVStream.Source.SQL, OHLCVStream.OHLCVType.HISTORIC, OHLCVStream.OHLCVBarSize.ONE_DAY,
|
||||
OHLCVStream.get_default_historic_range()))) { }
|
||||
|
||||
// simply finds the most active (highest volume) contract per day
|
||||
public FuturesActiveContractStream(ViewStream ohlcv_stream) {
|
||||
var rs = new FilterStream(ohlcv_stream, r => {
|
||||
ContractUtils.ContractType t = ContractUtils.get_type(r.get<string>("contract"));
|
||||
return t == ContractUtils.ContractType.Future;
|
||||
});
|
||||
mySetRealSource(new NonIncGroupByStream(rs, this));
|
||||
}
|
||||
|
||||
public IBlueRowCollection evaluate(IDictionary<int, List<IBlueRow>> grouped_rows) {
|
||||
Func<string, bool> is_future = (c) => ContractUtils.get_category(c) == ContractUtils.ContractCategory.FutureString;
|
||||
BlueTable rv = null;
|
||||
Func<List<IBlueRow>, IBlueRow> reduce = (rows) => {
|
||||
var future_rows = rows.Where(r => is_future(r.get<string>("contract")));
|
||||
IBlueRow rv = future_rows.ElementAt(0);
|
||||
foreach (IBlueRow r in future_rows) {
|
||||
if (r.get<int>("volume") > rv.get<int>("volume"))
|
||||
rv = r;
|
||||
}
|
||||
return rv;
|
||||
};
|
||||
foreach (var kv in grouped_rows) {
|
||||
var rows = kv.Value;
|
||||
if (rows == null || rows.Count == 0)
|
||||
continue;
|
||||
IBlueRow rr = reduce(rows);
|
||||
rv = rv ?? new BlueTable(rr.schema);
|
||||
rv.addRow(rr);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
public string[] get_group_by_cols() {
|
||||
return new string[] { "ts_event" };
|
||||
}
|
||||
}
|
||||
|
||||
// Reduces the OHLCV stream by date and by either contract (if given explicty) or active contract
|
||||
// is the first arg is a symbol and not a contract
|
||||
public class FilteredOHLCVStream : ViewStream {
|
||||
public FilteredOHLCVStream(string symbol_or_contract)
|
||||
:
|
||||
this(symbol_or_contract, DateTime.Today.Date.Subtract(TimeSpan.FromDays(1)), DateTime.MinValue) { }
|
||||
|
||||
public FilteredOHLCVStream(string symbol_or_contract, DateTime dt1, DateTime dt2) {
|
||||
Tuple<ContractUtils.ContractCategory, string> tup = ContractUtils.get_symbol_category(symbol_or_contract);
|
||||
var ohlcv_params = OHLCVStream.get_params(dt1, dt2);
|
||||
ViewStream rs = new OHLCVStream(tup.Item2, ohlcv_params);
|
||||
switch (tup.Item1) {
|
||||
case ContractUtils.ContractCategory.FutureString:
|
||||
case ContractUtils.ContractCategory.SpreadString:
|
||||
rs = new FilterStream(rs, $"contract = '{symbol_or_contract}'");
|
||||
break;
|
||||
case ContractUtils.ContractCategory.Symbol:
|
||||
rs = new FuturesActiveContractStream(rs);
|
||||
break;
|
||||
}
|
||||
rs = new FilterStream(rs, r => r.get_datetime("ts_event") <= dt1 &&
|
||||
r.get_datetime("ts_event") >= dt2);
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using bts.api;
|
||||
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
[DataStreamUserRespresentation("FuturesContinousContract")]
|
||||
public class FuturesContinousContractStream : ViewStream {
|
||||
// the argument is symbol, like "ES" etc and not the contract itself
|
||||
public FuturesContinousContractStream(string symbol) : this(symbol, ViewStreamDatabase.instance) { }
|
||||
public FuturesContinousContractStream(string symbol, ViewStreamDatabase db) {
|
||||
ViewStream r = new FuturesHistorical1DayBarsStream(symbol);
|
||||
// filtering for futures only
|
||||
r = new FilterStream(r, r => {
|
||||
string contract = r.get<string>("symbol");
|
||||
var fc = new ContractUtils.FutureContract(contract);
|
||||
return fc.future_tradable_contract != null;
|
||||
});
|
||||
r = new NonIncGroupByStream(r,
|
||||
"ts_event",
|
||||
"volume:Max");
|
||||
r = new NewProjectStream(r,
|
||||
"ts_event symbol !");
|
||||
r = new SortStream(r,
|
||||
"-ts_event");
|
||||
mySetRealSource(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using bts;
|
||||
using BCG;
|
||||
|
||||
// it uses the volume - better to use open interst perhap - to detect the rollover, is when a new
|
||||
// futuere exp becomes the highest volume one
|
||||
[DataStreamUserRespresentation("FuturesRoll")]
|
||||
public class FuturesRollStream : ViewStream {
|
||||
public FuturesRollStream(string future_symbol) {
|
||||
//ViewStream ohlcv_str = new OHLCVStream(future_symbol);
|
||||
ViewStream rs = new FuturesActiveContractStream(future_symbol);
|
||||
rs = new ColumnEvolutionStream(rs, "ts_event", "contract");
|
||||
rs = new NewProjectStream(rs, "ts_event:roll_date !");
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
[DataStreamUserRespresentation("OHLCVPriceDiff")]
|
||||
public class OHLCVPriceDiffStream : ViewStream {
|
||||
// TODO, abstract this out
|
||||
private static ViewStream _get_ohlcv_steam(string symbol_or_contract, DateTime d1, DateTime d2) {
|
||||
var tup = ContractUtils.get_symbol_category(symbol_or_contract);
|
||||
var ohlcv_params = OHLCVStream.get_params(d1, d2);
|
||||
var cont_cat = tup.Item1;
|
||||
string symbol = tup.Item2;
|
||||
ViewStream rs = new OHLCVStream(symbol, ohlcv_params);
|
||||
switch (cont_cat) {
|
||||
case ContractUtils.ContractCategory.FutureString:
|
||||
case ContractUtils.ContractCategory.SpreadString:
|
||||
rs = new FilterStream(rs, $"contract = '{symbol_or_contract}'");
|
||||
break;
|
||||
case ContractUtils.ContractCategory.Symbol:
|
||||
rs = new FuturesActiveContractStream(rs);
|
||||
break;
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
||||
public OHLCVPriceDiffStream(string symbol_or_contract, DateTime d1, DateTime d2)
|
||||
: this(symbol_or_contract, d1, d2, "close") { }
|
||||
|
||||
public OHLCVPriceDiffStream(string symbol_or_contract, DateTime d1, DateTime d2, string col) {
|
||||
ViewStream rs = _get_ohlcv_steam(symbol_or_contract, d1, d2);
|
||||
rs = new ColumnDifferenceStream(rs, r => d1.Equals(r.get_datetime("ts_event")),
|
||||
r => d2.Equals(r.get_datetime("ts_event")), col, col);
|
||||
rs = new NewProjectStream(rs, "diff !");
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using bts;
|
||||
using BCG;
|
||||
using MongoDB.Driver;
|
||||
|
||||
// OHLCV request breakdown
|
||||
// symbol_or_contract (if symbol, get continous, otherwise get raw and filter it)
|
||||
// bar_size (one min, one day)
|
||||
// live/historic
|
||||
// time range
|
||||
|
||||
// internal code oranization only
|
||||
public class OHLCV_1min_stream : ViewStream {
|
||||
|
||||
public OHLCV_1min_stream(string symbol_or_contract, string range_beg, string range_end) :
|
||||
this(symbol_or_contract, DateTime.Parse(range_beg), DateTime.Parse(range_end)) { }
|
||||
|
||||
public OHLCV_1min_stream(string symbol_or_contract, DateTime range_beg, DateTime range_end) {
|
||||
Func<string, bool, SQLiteStream> get_sqlite_str = (symbol, is_continous_contracts) => {
|
||||
string table_name = is_continous_contracts ? $"ohlcv_1min_{symbol}_continous" : $"{symbol}_ohlcv_1min";
|
||||
string db_str = $"Data Source={SQLiteHelper.location}{SQLiteHelper.db_name};Version=3";
|
||||
string range_beg_iso8601 = range_beg.ToString("yyyy-MM-ddTHH:mm:ss"),
|
||||
range_end_iso8601 = range_end.ToString("yyyy-MM-ddTHH:mm:ss");
|
||||
string sql_str = $"select * from {table_name} where DATE(ts_event) >= '{range_beg_iso8601}' AND DATE(ts_event) <= '{range_end_iso8601}'";
|
||||
return new SQLiteStream(db_str, sql_str);
|
||||
};
|
||||
|
||||
Tuple<ContractUtils.ContractCategory, string> tup = ContractUtils.get_symbol_category(symbol_or_contract);
|
||||
var contract_cat = tup.Item1;
|
||||
switch (contract_cat) {
|
||||
case ContractUtils.ContractCategory.Symbol: {
|
||||
ViewStream res = get_sqlite_str(tup.Item2, true);
|
||||
mySetRealSource(res);
|
||||
// this creates the continous stream for 1 min bars, but we store it in the DB, so we just read it from it
|
||||
// ViewStream ohlcv_1min = get_sqlite_str(tup.Item2, false);
|
||||
// // the following is whats written to the DB in the _contionous table
|
||||
// ohlcv_1min = new DateTimeExpanstionStream(ohlcv_1min, "ts_event");
|
||||
// ViewStream active_contr_str = new FuturesActiveContractStream(tup.Item2);
|
||||
// ViewStream res = new NonIncJoinStream(ohlcv_1min, "ts_event_date symbol", "ts_event ts_event_date symbol open high low close volume",
|
||||
// active_contr_str, "ts_event contract", "ts_event:date contract:continous_contract");
|
||||
// res = new NullFilterStream(res, "continous_contract", true);
|
||||
// res = new NewProjectStream(res, "ts_event date continous_contract open high low close volume !");
|
||||
// mySetRealSource(res);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ViewStream sql_str = get_sqlite_str(tup.Item2, false);
|
||||
ViewStream rs = new FilterStream(sql_str, $"symbol='{symbol_or_contract}'");
|
||||
// filter here
|
||||
mySetRealSource(rs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is to make bigger bars form smaller bars. Right now the assumption it only works
|
||||
// with symbols vs contracts, and the 1min <= aggregation_period < 1day
|
||||
[DataStreamUserRespresentation("OHLCVAggregated")]
|
||||
public class OHLCVAggregatedStream : ViewStream {
|
||||
public OHLCVAggregatedStream(string symbol, string agregation_period, string range_beg, string range_end) :
|
||||
this(symbol, TimeBasedFilter.parse_duration(agregation_period), DateTime.Parse(range_beg), DateTime.Parse(range_end)) {
|
||||
}
|
||||
|
||||
public OHLCVAggregatedStream(string symbol, TimeSpan aggregation_period, DateTime range_beg, DateTime range_end) {
|
||||
Tuple<ContractUtils.ContractCategory, string> tup = ContractUtils.get_symbol_category(symbol);
|
||||
Log.assert(tup.Item1 == ContractUtils.ContractCategory.Symbol);
|
||||
if (aggregation_period < TimeSpan.FromDays(1.0) &&
|
||||
aggregation_period > TimeSpan.FromMinutes(1.0)) {
|
||||
ViewStream r = new OHLCV_1min_stream(symbol, range_beg, range_end);
|
||||
r = new DateTimeExpanstionStream(r,
|
||||
"ts_event");
|
||||
double tot_secs = aggregation_period.TotalSeconds;
|
||||
r = new MathStream(r,
|
||||
$"bucket = Floor(ts_event_seconds_of_day / {tot_secs})");
|
||||
r = new NonIncGroupByStream(r,
|
||||
"bucket",
|
||||
// column:operation
|
||||
"open:first, high:max, low:min, close:last, volume:sum",
|
||||
"ts_event");
|
||||
r = new SortStream(r,
|
||||
"-ts_event");
|
||||
mySetRealSource(r);
|
||||
} else {
|
||||
// fix it later
|
||||
Log.assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[DataStreamUserRespresentation("OHLCV")]
|
||||
// This stream retreives the OHLCV table as is, and fires it as-is.
|
||||
// The only logic here is as follows:
|
||||
// 1. deciding bw sql table or pubsub
|
||||
// 2. deciding bw live, historic or append(live, historic)
|
||||
// 3. deciding size of bar
|
||||
// (the logic for2 and 3 is in get_params)
|
||||
public class OHLCVStream : ViewStream {
|
||||
public enum Source {
|
||||
SQL,
|
||||
PubSub
|
||||
}
|
||||
public enum OHLCVType {
|
||||
LIVE,
|
||||
HISTORIC,
|
||||
LIVE_AND_HISTORIC
|
||||
|
||||
};
|
||||
public enum OHLCVBarSize {
|
||||
ONE_DAY = 0,
|
||||
ONE_HOUR,
|
||||
ONE_MIN,
|
||||
ONE_SEC
|
||||
};
|
||||
public class OHLCVParams {
|
||||
public readonly Source source = Source.SQL;
|
||||
public readonly OHLCVType type = OHLCVType.HISTORIC;
|
||||
public readonly OHLCVBarSize bar_size;
|
||||
public readonly Tuple<DateTime, DateTime> optional_dt_range;
|
||||
public OHLCVParams(Source source_, OHLCVType type_, OHLCVBarSize bar_size_,
|
||||
Tuple<DateTime, DateTime> optional_dt_range_) {
|
||||
source = source_;
|
||||
type = type_;
|
||||
bar_size = bar_size_;
|
||||
optional_dt_range = optional_dt_range_;
|
||||
}
|
||||
}
|
||||
|
||||
public static OHLCVParams get_params(DateTime dt1, DateTime dt2) {
|
||||
Func<DateTime, bool> today = (dt) => dt.Date >= DateTime.Now.Date;
|
||||
TimeSpan period = dt1 > dt2 ? dt1 - dt2 : dt2 - dt1;
|
||||
bool has_today = today(dt1) || today(dt2);
|
||||
bool has_history = !today(dt1) && !today(dt2);
|
||||
Source source = Source.SQL;
|
||||
OHLCVType type = (has_today && has_history) ? OHLCVType.LIVE_AND_HISTORIC :
|
||||
((has_today && !has_history) ? OHLCVType.LIVE : OHLCVType.HISTORIC);
|
||||
// TODO, for less than a day, its defaulted to 1 min
|
||||
OHLCVBarSize bar_size = period >= TimeSpan.FromDays(1.0) ? OHLCVBarSize.ONE_DAY : OHLCVBarSize.ONE_MIN;
|
||||
Tuple<DateTime, DateTime> optional_dt_range = new Tuple<DateTime, DateTime>(dt1, dt2);
|
||||
return new OHLCVParams(source, type, bar_size, optional_dt_range);
|
||||
}
|
||||
|
||||
public static Tuple<DateTime, DateTime> get_default_historic_range() {
|
||||
return Tuple.Create(DateTime.Now.Date.Subtract(TimeSpan.FromDays(1)), DateTime.MinValue);
|
||||
}
|
||||
|
||||
private static string get_table_from_barsize(OHLCVBarSize bar_size, string symbol) {
|
||||
switch (bar_size) {
|
||||
case OHLCVBarSize.ONE_DAY:
|
||||
return $"{symbol}_OHLCV_1DAY";
|
||||
case OHLCVBarSize.ONE_SEC:
|
||||
case OHLCVBarSize.ONE_MIN:
|
||||
case OHLCVBarSize.ONE_HOUR:
|
||||
return $"{symbol}_OHLCV_1MIN";
|
||||
}
|
||||
Log.assert(false);
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
private Source _sourse = Source.SQL; // get from config
|
||||
private readonly string _location = "C:\\Users\\m_tah\\development\\data\\";
|
||||
private readonly string _db_name = "stream_data.db";
|
||||
// the symbol is used ot retreive the correct table, the data flows as-is from the table
|
||||
// with some name / type changes
|
||||
public OHLCVStream(string symbol, OHLCVParams ohlcv_params) {
|
||||
switch (ohlcv_params.type) {
|
||||
case OHLCVType.LIVE:
|
||||
case OHLCVType.LIVE_AND_HISTORIC:
|
||||
// TODO
|
||||
Log.assert(false);
|
||||
break;
|
||||
case OHLCVType.HISTORIC:
|
||||
// TODO: assuming 1 day only for historic
|
||||
string table_name = get_table_from_barsize(ohlcv_params.bar_size, symbol);// $"{symbol}_OHLCV_1DAY";
|
||||
//string table_name = $"{symbol}_{ohlcv_params.bar_size}";
|
||||
string db_str = $"Data Source={_location}{_db_name};Version=3";
|
||||
string sql_str = $"select * from {table_name}";
|
||||
// "Data Source=C:\\Users\\m_tah\\development\\data\\stream_data.db;Version=3;"
|
||||
ViewStream rs = new SQLiteStream(db_str, sql_str);
|
||||
rs = new SchemaGuesserStream(rs);
|
||||
if (ohlcv_params.bar_size == OHLCVBarSize.ONE_DAY)
|
||||
rs = new DateStandardizationStream(rs, "ts_event", DateConversion.ChopTime);
|
||||
rs = new NewProjectStream(rs, "symbol:contract");
|
||||
mySetRealSource(rs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
public OHLCVStream(string symbol)
|
||||
:
|
||||
this(symbol, new OHLCVParams(Source.SQL, OHLCVType.HISTORIC, OHLCVBarSize.ONE_DAY, get_default_historic_range())) { }
|
||||
|
||||
public OHLCVStream(string symbol, OHLCVBarSize bar_size)
|
||||
:
|
||||
this(symbol, new OHLCVParams(Source.SQL, OHLCVType.HISTORIC, bar_size, get_default_historic_range())) {
|
||||
}
|
||||
|
||||
public OHLCVStream(string symbol, string bar_size)
|
||||
:
|
||||
this(symbol, Enum.Parse<OHLCVBarSize>(bar_size)) { }
|
||||
|
||||
// aggregates the bars
|
||||
public OHLCVStream(string symbol, TimeSpan agregation_period) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using bts;
|
||||
|
||||
[DataStreamUserRespresentation("Settlement")]
|
||||
public class SettlementPriceStream : ViewStream {
|
||||
|
||||
public SettlementPriceStream(string future_name, string date_txt)
|
||||
: this(future_name, date_txt, date_txt) { }
|
||||
|
||||
public SettlementPriceStream(string future_name, string begin_dt, string end_dt)
|
||||
: this(future_name, DateTime.Parse(begin_dt).Date, DateTime.Parse(end_dt).Date) { }
|
||||
|
||||
public SettlementPriceStream(string symbol_or_contract, DateTime begin_dt)
|
||||
: this(symbol_or_contract, begin_dt, begin_dt) { }
|
||||
|
||||
public SettlementPriceStream(string symbol_or_contract, DateTime begin_dt, DateTime end_dt) {
|
||||
ContractUtils.FutureContract fc = new ContractUtils.FutureContract(symbol_or_contract);
|
||||
ViewStream rs = new FutureHistoricalBarsStream(fc, BarSize.ONE_DAY, new DateTimeRange(begin_dt, end_dt));
|
||||
rs = new NewProjectStream(rs, "symbol ts_event:date close:settlement !");
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
// Takes multiple bars and collapses them into one, which is aggregated over a bigger time period.
|
||||
// All bars belonging to a common group_by_col, are aggregated
|
||||
public class BarsAggregatorStream : ViewStream {
|
||||
public BarsAggregatorStream(ViewStream ohlcv_stream, params string[] group_by_cols) {
|
||||
ViewStream rs = new NonIncGroupByStream(ohlcv_stream,
|
||||
() => { return group_by_cols; },
|
||||
(group_rows) => {
|
||||
var sorted_rows = group_rows.OrderBy(r => r.get_datetime("ts_event"));
|
||||
IBlueRow first_row = sorted_rows.First(),
|
||||
last_row = sorted_rows.Last();
|
||||
double open = first_row.get<double>("open");
|
||||
double close = last_row.get<double>("close");
|
||||
double low = sorted_rows.Min(r => r.get<double>("low"));
|
||||
double high = sorted_rows.Max(r => r.get<double>("high"));
|
||||
double volume = 0.0;
|
||||
foreach (IBlueRow r in sorted_rows)
|
||||
volume += r.get<double>("volume");
|
||||
MutableBlueRow rv = new MutableBlueRow(first_row);
|
||||
rv.setValue("open", open);
|
||||
rv.setValue("close", close);
|
||||
rv.setValue("low", low);
|
||||
rv.setValue("high", high);
|
||||
rv.setValue("volume", volume);
|
||||
return new IBlueRow[] { rv }.ToList();
|
||||
}
|
||||
);
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
// this is an internal stream. its job is to take an OHLCV stream
|
||||
// and filter it for
|
||||
// 1. symbol (table_name and active contract) and
|
||||
// 2. time (can be a day of the week, month, and a time of the day period)
|
||||
public class BarsSearcherStream : ViewStream {
|
||||
public BarsSearcherStream(string symbol, OHLCVStream.OHLCVBarSize bar_size,
|
||||
string day_of_week, TimeSpan tod_begin, TimeSpan tod_end) {
|
||||
ViewStream rs = new OHLCVStream(symbol, bar_size);
|
||||
rs = new DateTimeExpanstionStream(rs, "ts_event");
|
||||
rs = new FilterStream(rs, r => {
|
||||
DateTime ts = r.get_datetime("ts_event");
|
||||
return r.get<string>("ts_event_day") == day_of_week.ToString() &&
|
||||
ts.TimeOfDay >= tod_begin && ts.TimeOfDay <= tod_end;
|
||||
});
|
||||
// look at symbol and either filter ir ot do the active contracts
|
||||
// assuming its symbol
|
||||
rs = new NonIncJoinStream(rs, "ts_event_date", "open high low close volume contract ts_event",
|
||||
new FuturesActiveContractStream(symbol), "ts_event", "ts_event:date contract:active_contract");
|
||||
// filter it for the active contract only
|
||||
rs = new FilterStream(rs, r => String.Compare(r.get<string>("contract"), r.get<string>("active_contract")) == 0);
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
public BarsSearcherStream(string symbol, string bar_size,
|
||||
string day_of_week, string tod_begin, string tod_end)
|
||||
:
|
||||
this(symbol, Enum.Parse<OHLCVStream.OHLCVBarSize>(bar_size), day_of_week,
|
||||
TimeSpan.Parse(tod_begin), TimeSpan.Parse(tod_end)) { }
|
||||
}
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
namespace BCG {
|
||||
using bts.api.orderman;
|
||||
|
||||
enum TSGroupByOperation {
|
||||
OHLC = 0,
|
||||
Statistics
|
||||
}
|
||||
|
||||
[DataStreamUserRespresentation("timeseriesanalysis")]
|
||||
public class TimeSeriesGroupByStream : ViewStream {
|
||||
public TimeSeriesGroupByStream(ViewStream md_str, string timebucket_col, string output_col, string operation) {
|
||||
ViewStream rs = new NonIncGroupByStream(md_str, new OHLCNonIncGroupByEvaluator(timebucket_col, output_col));
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
public class OHLC {
|
||||
public OHLC(double open_args, double high_args, double low_args, double close_args) {
|
||||
open = open_args;
|
||||
high = high_args;
|
||||
low = low_args;
|
||||
close = close_args;
|
||||
}
|
||||
public readonly double open, high, low, close;
|
||||
}
|
||||
public class OHLCNonIncGroupByEvaluator : INonIncGroupByEvaluator {
|
||||
private string _timestamp_col;
|
||||
private string _output_col;
|
||||
private IBlueTableSchema _out_schema;
|
||||
public OHLCNonIncGroupByEvaluator(string timestamp_col, string output_col) {
|
||||
_timestamp_col = timestamp_col;
|
||||
_output_col = output_col;
|
||||
}
|
||||
|
||||
string open_col {
|
||||
get {
|
||||
return $"{_output_col}_open"; ;
|
||||
}
|
||||
}
|
||||
string high_col {
|
||||
get {
|
||||
return $"{_output_col}_high"; ;
|
||||
}
|
||||
}
|
||||
string low_col {
|
||||
get {
|
||||
return $"{_output_col}_low"; ;
|
||||
}
|
||||
}
|
||||
string close_col {
|
||||
get {
|
||||
return $"{_output_col}_close"; ;
|
||||
}
|
||||
}
|
||||
private void _build_schema(IBlueTableSchema input_schema) {
|
||||
List<Tuple<Type, string>> new_cols = new List<Tuple<Type, string>>();
|
||||
ColumnInfo ci = input_schema[_output_col];
|
||||
new_cols.Add(Tuple.Create(ci.colType, open_col));
|
||||
new_cols.Add(Tuple.Create(ci.colType, high_col));
|
||||
new_cols.Add(Tuple.Create(ci.colType, low_col));
|
||||
new_cols.Add(Tuple.Create(ci.colType, close_col));
|
||||
// should hide the output col
|
||||
_out_schema = BlueDataUtility.add_columns(input_schema, new_cols.ToArray());
|
||||
}
|
||||
|
||||
public IBlueRowCollection evaluate(IDictionary<int, List<IBlueRow>> grouped_rows) {
|
||||
if (_out_schema == null) {
|
||||
if (grouped_rows.Count > 0) {
|
||||
foreach (var kv in grouped_rows) {
|
||||
var rows = kv.Value;
|
||||
if (rows != null && rows.Count > 0) {
|
||||
_build_schema(rows.ElementAt(0).schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BlueTable rv = new BlueTable(_out_schema);
|
||||
foreach (var kv in grouped_rows) {
|
||||
int id = kv.Key;
|
||||
IEnumerable<IBlueRow> rows = kv.Value;
|
||||
// sort rows on time to compute o,c correctly??
|
||||
if (rows != null && rows.Count() > 0) {
|
||||
IBlueRow reprow = rows.ElementAt(0);
|
||||
IEnumerable<double> vals = BlueDataUtility.get_colvalues<double>(rows, _output_col);
|
||||
OHLC ohlc = compute_ohlc(vals);
|
||||
MutableBlueRow nr = new MutableBlueRow(_out_schema, reprow);
|
||||
nr.setValue("id", kv.Key);
|
||||
nr.setValue(open_col, ohlc.open);
|
||||
nr.setValue(high_col, ohlc.high);
|
||||
nr.setValue(low_col, ohlc.low);
|
||||
nr.setValue(close_col, ohlc.close);
|
||||
rv.addRow(nr);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public string[] get_group_by_cols() {
|
||||
return new string[] { _timestamp_col };
|
||||
}
|
||||
|
||||
static OHLC compute_ohlc(IEnumerable<double> prices) {
|
||||
double o = prices.ElementAt(0);
|
||||
double c = prices.ElementAt(prices.Count() - 1);
|
||||
double l = prices.Min();
|
||||
double h = prices.Max();
|
||||
return new(o, h, l, c);
|
||||
}
|
||||
}
|
||||
[DataStreamUserRespresentation("RSI")]
|
||||
public class RSIStream : ViewStream {
|
||||
// for ms_str expects a timeseries with a timestamp col and an output col (price col) to calculate the ohlc for
|
||||
public RSIStream(ViewStream md_str, string timebucket_column, string output_col) {
|
||||
|
||||
}
|
||||
}
|
||||
[DataStreamUserRespresentation("Bollinger")]
|
||||
public class BollingerBandStream : ViewStream {
|
||||
// for ms_str expects a timeseries with a timestamp col and an output col (price col) to calculate the ohlc for
|
||||
public BollingerBandStream(ViewStream md_str, string timebucket_column, string output_col) {
|
||||
}
|
||||
}
|
||||
[DataStreamUserRespresentation("OHLC")]
|
||||
public class OHLCStream : ViewStream {
|
||||
// for ms_str expects a timeseries with a timestamp col and an output col (price col) to calculate the ohlc for
|
||||
public OHLCStream(ViewStream md_str, string timebucket_column, string output_col) {
|
||||
ViewStream rs = new TimeSeriesGroupByStream(md_str, timebucket_column, output_col, TSGroupByOperation.OHLC.ToString());
|
||||
mySetRealSource(rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
{
|
||||
"prompts": [
|
||||
{
|
||||
"category": "Settlement",
|
||||
"description": "This is a few shot learning example for an NL to DSL. The DSL function in question is Settlement (symbol_or_contract, datetime1). The first argument is a future (like CL, for crude oil) or a specific future contract like crude oil Dec 24 future (CLZ4). The second argument is the date at which the settlement is to be fetched. There is an overloaded function, Settlement (symbol_or_contract, begin_dt, end_dt) which gets the settlements for all dates from begin_dt to end_dt. This will also have datetimes expressed as Today, Yesterday, Last Friday, First Friday of the month, Last Thursday of August etc. You will need to know what Today is, since there will be referecnes to last week, yesterday etc. These examples are assuming Today is 10/11/2024, however you should use the Today's real date",
|
||||
"prompt": "What was the settlement for SP 500 Future on June 8th?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "Find Settlement price of the SP500 future on 04/22/2023.",
|
||||
"dsl": "Settlement(\"ES\", 4/22/2023)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find Settlement price of the Silver Dec 24 Future on 04/22/2023.",
|
||||
"dsl": "Settlement(\"SIZ4\", 4/22/2023)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find Yesterday's Settlement of the Crude Oil Future.",
|
||||
"dsl": "Settlement(\"CL\", 10/10/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find today's settlement of the 10 year treasury future.",
|
||||
"dsl": "Settlement(\"ZN\", 10/11/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find the Settlement of Natural Gas Dec 24 future on the first Friday of Sept.",
|
||||
"dsl": "Settlement(\"NGZ4\", 9/6/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find the Settlement of WTI Jan 25 future in the first Week of Sept.",
|
||||
"dsl": "Settlement(\"CLF5\", 9/2/2024, 9/6/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find the Settlement price for the Sp 500 Dec 24 Mar 25 spread for the first two weeks of September.",
|
||||
"dsl": "Settlement(\"ESZ4-ESH5\", 9/14/2024, 9/1/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find the Settlement of Natural Gas future on the first Friday of Sept.",
|
||||
"dsl": "Settlement(\"NG\", 9/6/2024)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "VWAP",
|
||||
"description": "This is a few shot learning example for an NL to DSL. The DSL function in question is VWAP (symbol_or_contract, perio_end_date, period_start_date). The first argument is a future (like CL, for crude oil, or ES for SP 500) or a specific future contract like crude oil Dec 24 future (CLZ4) or SP 500 Dec 2024 (ESZ4). The second and third argument define the end and start of the VWAP period, respectively. So for example, if we are calculating the 10 day VWAP on 10/15/2023, the period will be from 10/15/2023 going back to 10/05/2023. so the second argument will 10/05/2023 and the third argument will be 10/15/2023. The NL prompt will also have datetimes expressed as Today, Yesterday, Last Friday, Last Sunday, First day of quarter, Today etc. You will need to translate these as dates that need to be passed to the VWAP DSL function. ",
|
||||
"prompt": "What was the VWAP for SP 500 Future over the past 30 days?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "Find the 20 day VWAP of the SP future on 04/22/2023.",
|
||||
"dsl": "VWAP(\"ES\", 4/02/2023, 4/22/2023)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find Yesterday's 10 day VWAP of the Crude Oil Future.",
|
||||
"dsl": "VWAP(\"CL\", 10/01/2024, 10/10/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find today's 30-day VWAP of the 10 year treasury future.",
|
||||
"dsl": "VWAP(\"ZN\", 9/11/2024, 10/11/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Find the 10 hour VWAP of the Natural Gas future from yesterday at 5:00 PM.",
|
||||
"dsl": "VWAP(\"NG\", 9/27/2024 7:00:00, 9/27/2024 17:00:00)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "FuturePriceDiff",
|
||||
"description": "This is a few-shot learning example for an NL to DSL. The DSL function in question is FuturePriceDiff(symbol_or_contract, datetime1, datetime2). The first argument is a future (like CL, for crude oil, or ES for SP 500 and so on and so forth) or a specific future contract like crude oil Dec 24 future (CLZ4). The second and third arguments are datetimes (usually dates) that the function finds the difference of prices at. If the dates are given like \"first day of quarter\", \"first week of August\" I expect you to convert them into exact dates since the function only takes specific dates. The second argument should be the smaller datetime and the 3rd argument should be the end of the range, ie the higher one. Any prompt asking for price difference or price move should call FuturePriceDiff. If the dates you compute to pass to FuturePriceDiff are dates on which futures exchange might be closed (like 1/1, 12/25, Thanksgiving etc) please adjust the date to the nearest viable trading date, for example if the date falls on christmas day, change it to 12/24 and so on and so on and so forth, or the date happens to be a saturday or sunday, change it to Friday or Monday depending on which is closest",
|
||||
"prompt": "What is the difference in SP 500 Future from July 10th to July 14th?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "What is the difference in ZN price from July 10th to July 14th?",
|
||||
"dsl": "FuturePriceDiff(\"ZN\", 7/10/2024, 7/14/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "What is the price difference in SP Future price from Sept 10th and Sept 5th?",
|
||||
"dsl": "FuturePriceDiff(\"ES\", 9/5/2024, 9/10/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "What is the price difference in Natural Gas Dec Future price from Aug 30th and Aug 20th?",
|
||||
"dsl": "FuturePriceDiff(\"NGZ4\", 8/20/2024, 8/30/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "What is the price move in SP 500 Future from Aug 30th 2023 to October 10th 2023",
|
||||
"dsl": "FuturePriceDiff(\"ES\", 8/30/2023, 10/10/2023)"
|
||||
},
|
||||
{
|
||||
"natural_language": "What is the price move in SP 500 Future during teh first quarter of last year",
|
||||
"dsl": "FuturePriceDiff(\"ES\", 1/1/2023, 3/31/2023)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Aggregate Volume",
|
||||
"description": "this is a few shot learning example for an NL to DSL. The DSL function in question is VolumeAgg(symbol, contract_type, datetime1, datetime2), which computes the highest volume in the date range, specified by datetime1, and datetime2. The first argument is a future symbol (like CL for crude oil, ES for SP 500 etc). The second argument is the ContractType, which is \"Future\" for futures and \"FutureSpread\" for future spreads. the 3rd argument is the begin date and the 4th argument is the end date, between which the max volume is computed. If no future is specified use \"*\" from the first arugment.",
|
||||
"prompt": "Which SP 500 Future traded the most between 7/14/2024 and 7/10/2024",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "Which SP Future traded the most between 7/10/2024 and 7/14/2024",
|
||||
"dsl": "VolumeAgg(\"ES\", \"Future\", 1/1/2024, 1/7/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Which Gold Spread traded the most in the first month of this year",
|
||||
"dsl": "VolumeAgg(\"GC\", \"FutureSpread\", 1/1/2024, 1/31/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Which 10 year Spread traded the highest volume last week to now?(in this example(only) we are assuming today is 11/26/2024)",
|
||||
"dsl": "VolumeAgg(\"ZN\", \"FutureSpread\", 11/19/2024, 11/26/2024)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Which Corn Spread traded the most today (in this example(only) we are assuming today is 11/26/2024)?",
|
||||
"dsl": "VolumeAgg(\"ZC\", \"FutureSpread\", 11/26/2024, 11/26/2024)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Roll",
|
||||
"description": "This is a few shot learning example for an NL to DSL. The DSL function in question is FuturesRoll(symbol) which computes the rollover date for a future, ie when the highest volume swtches from one expiration to the next one. ",
|
||||
"prompt": "When does the roll typically occur In SP 500?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "When does the roll typically occur In CL?",
|
||||
"dsl": "FuturesRoll(\"CL\")"
|
||||
},
|
||||
{
|
||||
"natural_language": "When does the roll typically occur for 10 year treasury?",
|
||||
"dsl": "FuturesRoll(\"ZN\")"
|
||||
},
|
||||
{
|
||||
"natural_language": "When does the roll usually occur for Gold Future",
|
||||
"dsl": "FuturesRoll(\"GC\")"
|
||||
},
|
||||
{
|
||||
"natural_language": "At what date does the future rollover happens for SP500?",
|
||||
"dsl": "FuturesRoll(\"ES\")"
|
||||
},
|
||||
{
|
||||
"natural_language": "When does the future rollover happens for the Corn Future?",
|
||||
"dsl": "FuturesRoll(\"ZC\")"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Daily Move",
|
||||
"description": "This is a few shot learning example for an NL to DSL. ",
|
||||
"prompt": "How often did Sp 500 Future settle + or - 10% over the previous day?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "List all the days when the SP 500 closed + or -5% from the previous day's close",
|
||||
"dsl": "ColDiff(filteredOHLCV(\"ES\"),\"ts_event\", -1, \"close\", \"close\", \"close_diff\", 5)"
|
||||
},
|
||||
{
|
||||
"natural_language": "List all the days when the Crude Oil closed + or -2.5% from the previous day's close",
|
||||
"dsl": "ColDiff(filteredOHLCV(\"CL\"),\"ts_event\", -1, \"close\", \"close\", \"close_diff\", 2.5)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Show me all the days when the Ten year Treaury Future opened + or -1% from the previous day's open",
|
||||
"dsl": "ColDiff(filteredOHLCV(\"ZN\"),\"ts_event\", -1, \"open\", \"open\", \"open_diff\", 1.0)"
|
||||
},
|
||||
{
|
||||
"natural_language": "List all the trading days when the Silver Future opened + or -1% from the previous day's close",
|
||||
"dsl": "ColDiff(filteredOHLCV(\"SI\"),\"ts_event\", -1, \"open\", \"open\", \"open_diff\", 1.0)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Average Volume",
|
||||
"description": "This is a few shot learning example for an NL to DSL. For the purpose of this few shot prompts, lets assume today is 10/3/2024 ",
|
||||
"prompt": "When does the most open interest typically shift from one contract to another in SP 500 Future?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "When does the most open interest typically shift from one contract to another in e-minis? ",
|
||||
"dsl": "FuturesRoll(\"ES\")"
|
||||
},
|
||||
{
|
||||
"natural_language": "Usually when does the open interest move from one contract to another in WTI?",
|
||||
"dsl": "FuturesRoll(\"CL\")"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Events",
|
||||
"description": "This is a few shot learning example for an NL to DSL. In the NL prompt the user is asking to show the price of a future (treasury future, or SP 500 future etc) around an event type. The event type could be \"FOMC Announcement\" or \"Storage numbers\" etc. The DSL is as follows: EventsPriceAction(future_name, event_type, pre_event_window, post_event_window, number_of_events) first arg is the name of the future, (ex ES or ZN etc), the second argument is the event type, for example, \"FOMC announcement\", the 3rd argument is a time window for how much pre-event data to include in the end result, the 4th argument is how much post-event data to include in the end result. Both are strings of the form \"5d\" for 5 days, \"5h\" for 5 hours and \"120m\" for 120 minutes and so on. Usually, only one of the event periods is provided. Set the other to be half of what the user provided. The last argument is the number of events to consider. So if it’s 7, that means the most recent 7 events. If the user does not specify that, pass a large number.",
|
||||
"prompt": "What did the volume and price of SP500 Future do following the release of the last 10 FOMC rates?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "How did SP 500 Future do in the 5 days following the FOMC announcements?",
|
||||
"dsl": "EventsPriceAction(\"ES\", \"FOMC Announcement\", \"2d\", \"5d\", 10)"
|
||||
},
|
||||
{
|
||||
"natural_language": "How did the price of Treasury Future evolve in the 2 days following the Job Reports?",
|
||||
"dsl": "EventsPriceAction(\"ZN\", \"Job Reports\", \"1d\", \"2d\", 10)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Show me the price movement and volume of Crude Oil futures during the 5-minute window following the last 5 OPEC meetings.",
|
||||
"dsl": "EventsPriceAction(\"CL\", \"OPEC Meeting\", \"2m\", \"5m\", 5)"
|
||||
},
|
||||
{
|
||||
"natural_language": "Show me the price movement and volume of SP 500 futures preceding the 10-minute window of the last 5 OPEC meetings.",
|
||||
"dsl": "EventsPriceAction(\"CL\", \"OPEC Meeting\", \"10m\", \"5m\", 5)"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Indicator, Standard Deviation",
|
||||
"description": "This is a few shot learning example for an NL to DSL. In the NL prompt the user is asking to show all the days when the price of a future (treasury future, or SP 500 future etc) moved more than m times the N days standard deviation, where both m and N are provided. For example, the DSL for \"Using a 90d standard deviation, give me the dates and amounts of the last 4+ standard deviation moves in WTI futures\" would be: r=standardDeviation(\"ES\", \"90d\")\nr=math(r, \"abs_daily_change = Abs(close - open) comp = std_dev * 4\")\nr=filter(r,\"abs_daily_change >= comp\"). The first line, creates a stream for StandardDeviation, based on the number of days, for example 90d standard deviation, and assigned it to r, the second line takes r from the first line and passes it to a math stream that creates 2 new columns, abs_daily_change and comp. comp is the factor (4, from 4+ in the prompt) times standard deviation. The third line filters (like a sql where) of rows where abs_daily_change >= comp",
|
||||
"prompt": "Using a 90d standard deviation, give me the dates and amounts of the last 1+ standard deviation moves in SP futures ?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "Using a 90d standard deviation, give me the dates and amounts of the last 1+ standard deviation moves in WTI futures ?",
|
||||
"dsl": "r=standardDeviation(\"CL\", \"90d\")\nr=math(r, \"abs_daily_change = Abs(close - open) comp = std_dev * 1.0\")\nr=filter(r,\"abs_daily_change >= comp\")"
|
||||
},
|
||||
{
|
||||
"natural_language": "Show me the times the SP Futures moved twice the 60 day standard deviation",
|
||||
"dsl": "r=standardDeviation(\"ES\", \"60d\")\nr=math(r, \"abs_daily_change = Abs(close - open) comp = std_dev * 2.0\")\nr=filter(r,\"abs_daily_change >= comp\")"
|
||||
},
|
||||
{
|
||||
"natural_language": "List all the days the Gold Futures moved 1.5 times the 45 day standard deviation",
|
||||
"dsl": "r=standardDeviation(\"GC\", \"45d\")\nr=math(r, \"abs_daily_change = Abs(close - open) comp = std_dev * 1.5\")\nr=filter(r,\"abs_daily_change >= comp\")"
|
||||
},
|
||||
{
|
||||
"natural_language": "List all the days the 10 year treasury future moved more than twice the 1 month standard deviation",
|
||||
"dsl": "r=standardDeviation(\"ZN\", \"30d\")\nr=math(r, \"abs_daily_change = Abs(close - open) comp = std_dev * 2.0\")\nr=filter(r,\"abs_daily_change >= comp\")"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Price Movement",
|
||||
"description": "This is a few shot learning example for an NL to DSL. In the NL prompt the user is asking for the average price movement for e-minis (aka ES aka SP Futures aka SP 500 Futures)) on Wednesday between 9:30 am and 9:40 AM? the multiline DSL is as follows (along with the explaination in comments before each line, dont include the comments in the asnwer): //following line gets the 1 min ohlcv bars of ES \n r=OHLCV_1min_stream(\"ES\")\n //this passes it to the filter stream, which filters the rows for Wednesday, and time bw 9:30 and 9:40.\nr=filter(r,\"ts_event_day = 'Wednesday' and ts_event_hour = 9 and ts_event_min >= 30 and ts_event_min < 40\")\n// this aggregates it using the date as the agregation key, it find the max of the column called high, and the low of the column called min, to find the max and the min prices in that time window\nr=aggregate(r, \"ts_event_date\", \"high: max, low: min\")\n/// this then passes the previous result to the math stream operator which calculates the move, which is the difference between high_max and low_min (columns that were added from the previous aggregate)\nr=math(r,\"move = high_max - low_min\")\n// At the end we compute the mean of the move column, notice this is the total mean, so we are not providing an aggregation col to agregate\nr=aggregate(r, \"move:mean\")\n// we project out every col by the ! operator and call rename move_mean as average_vol\nr=newProject(r,\"move_mean:average_move !\")",
|
||||
"prompt": "What is the average price movement for SP Futures (ES) on Wednesday between 9:30 am and 9:40 AM ?",
|
||||
"examples": [
|
||||
{
|
||||
"natural_language": "What is the average price movement for SP Futures (ES) on Wednesday between 9:30 am and 9:40 AM?",
|
||||
"dsl": "r=OHLCV_1min_stream(\"ES\")\nr=filter(r,\"ts_event_day = 'Wednesday' and ts_event_hour = 9 and ts_event_min >= 30 and ts_event_min < 40\")\nr=aggregate(r, \"ts_event_date\", \"high: max, low: min\")\nr=math(r,\"move = high_max - low_min\")\nr=aggregate(r, \"move:mean\")\nr=newProject(r,\"move_mean:average_move !\")"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using bts;
|
||||
using bts.SilverPine;
|
||||
|
||||
[DataStreamUserRespresentation("nl")]
|
||||
public class NLStream : ViewStream {
|
||||
private readonly string _nl_prompt;
|
||||
private ViewStream _nl_to_dsl_stream, _dsl_stream;
|
||||
public NLStream(string nl_prompt) {
|
||||
_nl_prompt = nl_prompt;
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_nl_to_dsl_stream = new NLToDSLStream(_nl_prompt);
|
||||
_nl_to_dsl_stream.onChange += _handle_dsl_callback;
|
||||
}
|
||||
|
||||
private void _handle_dsl_callback(object dp_obj) {
|
||||
DataPacket dp = dp_obj as DataPacket;
|
||||
var r = dp.newRows.to_list().ElementAt(0);
|
||||
string dsl = r.get<string>("response");
|
||||
Log.Gen.info($"NLStream._handle_dsl_callback dsl: {dsl}");
|
||||
_dsl_stream = new DSLStream(dsl);
|
||||
_dsl_stream.onChange += _handle_data_cb;
|
||||
}
|
||||
|
||||
private void _handle_data_cb(object dp_obj) {
|
||||
var dp = dp_obj as DataPacket;
|
||||
DataPacket dp_out = BlueDataUtility.build_dp_inc(dp.newRows, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
// This subscribes to 1. NLToFewShotStream, gets the 2. total fewshot prompt, constructs and 3. OpenAIPromptReponseStream,
|
||||
// passing in 2. to 3. As it gets the calbacks from 3. it fires them
|
||||
[DataStreamUserRespresentation("nl_to_dsl")]
|
||||
public class NLToDSLStream : ViewStream {
|
||||
private readonly string _nl_prompt;
|
||||
private ViewStream _nl_to_fw_prompt_stream;
|
||||
ViewStream _openai_prompt_str = null;
|
||||
public NLToDSLStream(string nl_prompt) {
|
||||
_nl_prompt = nl_prompt;
|
||||
_nl_to_fw_prompt_stream = new NLToFewShotPromptStream(nl_prompt);
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
_nl_to_fw_prompt_stream.onChange += _on_fs_prompt;
|
||||
}
|
||||
|
||||
private void _on_fs_prompt(object dp_obj) {
|
||||
DataPacket dp = dp_obj as DataPacket;
|
||||
IBlueRow r = dp.newRows.to_list().ElementAt(0);
|
||||
string few_shot_prompt = r.get<string>("few_shot_prompt");
|
||||
Log.Gen.info($"NLToDSLStream._on_fs_prompt nl_prompt: {_nl_prompt} few_shot_prompt: {few_shot_prompt}");
|
||||
_openai_prompt_str = new OpenAIPromptStream(few_shot_prompt);
|
||||
_openai_prompt_str.onChange += _on_openai_prompt;
|
||||
}
|
||||
|
||||
private void _on_openai_prompt(object dp_obj) {
|
||||
DataPacket dp = dp_obj as DataPacket;
|
||||
var dp_out = BlueDataUtility.build_dp(dp.newRows, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using SimMetrics.Net.Metric;
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
|
||||
[DataStreamUserRespresentation("nl_to_fewshot_prompt")]
|
||||
// given an nl prompt, retreives the correct fewshot prompt and converts it into a form
|
||||
// that be sent to openAI as a prompt
|
||||
public class NLToFewShotPromptStream : ViewStream {
|
||||
public NLToFewShotPromptStream(string nl) {
|
||||
// TODO based on confi, we can either have NLToIndexedFewShotPromptStream
|
||||
// or NLToNonIndexedFewShotPromptStream (which is when a al the few shots are
|
||||
// concatenated and sent)
|
||||
mySetRealSource(new NLToIndexedFewShotPromptStream(nl));
|
||||
//_nl_prompt = nl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using BCG;
|
||||
|
||||
using MongoDB.Driver.Linq;
|
||||
|
||||
using SimMetrics.Net.Metric;
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
|
||||
[DataStreamUserRespresentation("nl_to_indexed_fewshot_prompt")]
|
||||
// given an nl prompt, retreives the correct fewshot prompt and converts it into a form
|
||||
// that be sent to openAI as a prompt
|
||||
public class NLToIndexedFewShotPromptStream : ViewStream {
|
||||
|
||||
// Represents a pair of a natural language query and its dsl
|
||||
public class FewShotExample {
|
||||
public string natural_language { get; set; }
|
||||
public string dsl { get; set; }
|
||||
}
|
||||
|
||||
// Class to represent each prompt category
|
||||
public class FewShotPrompt {
|
||||
public string category { get; set; }
|
||||
// this is the explaination of the DSL
|
||||
public string description { get; set; }
|
||||
// th actual prompt given by the user/CME
|
||||
public string prompt { get; set; }
|
||||
public List<FewShotExample> examples { get; set; }
|
||||
|
||||
public override string ToString() {
|
||||
string rv = $"System: {description}\n";
|
||||
int ex_no = 0;
|
||||
foreach (FewShotExample ex in examples) {
|
||||
rv += $"{++ex_no}. Natural Language: \"{ex.natural_language}\"" + "\n";
|
||||
rv += $" DSL: {ex.dsl}\n";
|
||||
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// this is how it should be prepended to the actual prompt:
|
||||
// System: This is a few-shot learning example for converting natural language prompts to a DSL function for settlement data retrieval. The DSL function can take either a single date or a date range. Assume today's date is 10/11/2024. The function is structured as follows:
|
||||
// - Settlement(symbol_or_contract, datetime1): Retrieves the settlement for the specified date.
|
||||
// - Settlement(symbol_or_contract, begin_dt, end_dt): Retrieves the settlements for all dates in the specified range.
|
||||
|
||||
// Examples:
|
||||
// 1. Natural Language: "Find the Settlement price of the SP future on 04/22/2023."
|
||||
// DSL: Settlement(SP, 4/22/2023)
|
||||
|
||||
// 2. Natural Language: "Find Yesterday's Settlement of the Crude Oil Future."
|
||||
// DSL: Settlement(CL, 10/10/2024)
|
||||
|
||||
// 3. Natural Language: "Find today's settlement of the 10-year treasury future."
|
||||
// DSL: Settlement(ZN, 10/10/2024)
|
||||
|
||||
// 4. Natural Language: "Find the Settlement of Natural Gas future on the first Friday of Sept."
|
||||
// DSL: Settlement(NG, 9/6/2024)
|
||||
|
||||
// 5. Natural Language: "Find the Settlement of Natural Gas Dec 24 future in the first Week of October."
|
||||
// DSL: Settlement(NGZ4, 10/1/2024, 10/1/2024)
|
||||
|
||||
// 6. Natural Language: "Find the settlement prices for the Wheat and Corn spread for the first two weeks of November."
|
||||
// DSL: Settlement(ZWZ4-ZCZ4, 11/1/2024, 11/14/2024)
|
||||
|
||||
// [Your Real Prompt Goes Here]
|
||||
|
||||
|
||||
// Root class to map the JSON structure
|
||||
public class Root {
|
||||
public List<FewShotPrompt> prompts { get; set; }
|
||||
}
|
||||
|
||||
public static Root read_json_file() {
|
||||
// TODO
|
||||
string json_file_path = @"C:\Users\m_tah\development\spark\src\DataStreamSuite\SharedStreams\NL\FewShotPrompts.json";
|
||||
string json_string = File.ReadAllText(json_file_path);
|
||||
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
||||
Root root = JsonSerializer.Deserialize<Root>(json_string, options);
|
||||
return root;
|
||||
}
|
||||
|
||||
private readonly string _nl_prompt;
|
||||
private string _fewshot_index_prompt;
|
||||
private string _fewshot_index_reponse;
|
||||
// this is the first stream that sends all FewShotPrompt.prompt and asks the LLM
|
||||
// to find the FewShotPrompt.prompt that matches the nl_prompt the closest. That
|
||||
// gives us our FewShotPrompt
|
||||
private ViewStream _nl_to_fewshot_index_stream;
|
||||
public NLToIndexedFewShotPromptStream(string nl) {
|
||||
_nl_prompt = nl;
|
||||
}
|
||||
|
||||
private static string _build_fewshot_prompt(FewShotPrompt fw_prompt, string nl_prompt) {
|
||||
string rv = "You are a helpful assistant that converts natural language into DSL. ";
|
||||
rv += $"{fw_prompt}\n\n";
|
||||
rv += "Now, convert the following prompt into DSL: \n";
|
||||
rv += $"Natural Language: {nl_prompt}\n";
|
||||
return rv;
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
Root root = read_json_file();
|
||||
string meta_prompt = build_fewshot_index_prompt(root, _nl_prompt);
|
||||
_fewshot_index_prompt = meta_prompt;
|
||||
Log.Gen.info($"NLToDSLStream.myOnFirstSubscriber _fewshot_index_prompt: {_fewshot_index_prompt}");
|
||||
_nl_to_fewshot_index_stream = new OpenAIPromptStream(meta_prompt);
|
||||
_nl_to_fewshot_index_stream.onChange += _on_fewshot_index;
|
||||
//Log.Gen.info($"NLToDSLStream.myOnFirstSubscriber meta_prompt: {meta_prompt}");
|
||||
|
||||
// this needs to be sent to the LLM to get the few-shot item. Once the few-shot item is received, then
|
||||
// we can prepend the fewshot to the prompt and send it
|
||||
//Log.Gen.info($"NLToDSLStream.myOnFirstSubscriber total_prompt: {final_prompt}");
|
||||
//_fire_event(final_prompt);
|
||||
}
|
||||
|
||||
private void _on_fewshot_index(object dp_obj) {
|
||||
DataPacket dp = dp_obj as DataPacket;
|
||||
IBlueRow r = dp.newRows.to_ienum().ElementAt(0);
|
||||
string response = r.get<string>("response");
|
||||
_fewshot_index_reponse = response;
|
||||
Log.Gen.info($"NLToDSLStream._on_fewshot_index prompt: {r.get<string>("prompt")}");
|
||||
Log.Gen.info($"NLToDSLStream._on_fewshot_index response: {response}");
|
||||
// parse the response
|
||||
// the response is mostly like :
|
||||
// 0. 0. What was the settlement for SP 500 Future on June 8th?
|
||||
// however, sometimes for no reason is returns a
|
||||
// Prompt 0: What was the settlement for SP 500 Future on June 8th?
|
||||
int index = 0;
|
||||
if (response.ToLower().StartsWith("prompt")) {
|
||||
// for the unusual case
|
||||
string[] toks = response.Split(':', '.');
|
||||
toks = toks[0].Split(' ');
|
||||
index = Int32.Parse(toks[1]);
|
||||
} else {
|
||||
// for the usual case
|
||||
string[] toks = response.Split('.');
|
||||
index = Int32.Parse(toks[0]);
|
||||
}
|
||||
var root = read_json_file();
|
||||
FewShotPrompt fs_prompt = root.prompts[index];
|
||||
string final_prompt = _build_fewshot_prompt(fs_prompt, _nl_prompt);
|
||||
_fire_event(final_prompt);
|
||||
}
|
||||
|
||||
private void _fire_event(string final_prompt) {
|
||||
IBlueTableSchema schema = BlueDataUtility.form_schema("NLToIndexedFewShotPromptStream",
|
||||
Tuple.Create("id", TypeCode.Int32),
|
||||
Tuple.Create("main_prompt", TypeCode.String),
|
||||
Tuple.Create("fewshot_index_prompt", TypeCode.String),
|
||||
Tuple.Create("fewshot_index_response", TypeCode.String),
|
||||
Tuple.Create("few_shot_prompt", TypeCode.String));
|
||||
IBlueRow nr = new BlueRow(schema, 0, _nl_prompt, _fewshot_index_prompt, _fewshot_index_reponse, final_prompt);
|
||||
BlueTable nt = new BlueTable(schema);
|
||||
nt.addRow(nr);
|
||||
var dp_out = BlueDataUtility.build_dp(nt, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
|
||||
// since find_matching_prompt using string matching loses semantics and often results
|
||||
// the incorrect few-shot entry (ex for, "Find the VWAP of the Sp 500 Dec 24 future during the first Week of October 24?").
|
||||
// so we assemble all the prompts from the few-shot (field "prompt") entry and ask an LLM to tell us which is the closest to the prompt.
|
||||
// based on that we select the few-shot entry. This is what this function does
|
||||
public static string build_fewshot_index_prompt(Root root, string nl_prompt) {
|
||||
string meta_promp = "Take a look at the following prompt examples:\n";
|
||||
int rv = 0;
|
||||
foreach (FewShotPrompt fs_entry in root.prompts) {
|
||||
meta_promp += $"{rv++}. {fs_entry.prompt}\n";
|
||||
}
|
||||
meta_promp += "Based on the above prompts, tell me which prompt (give me answer as the index only, and nothing else) does the following prompt most closely matches to: \n";
|
||||
meta_promp += nl_prompt;
|
||||
return meta_promp;
|
||||
}
|
||||
|
||||
public static FewShotPrompt find_matching_prompt(Root root, string nl_prompt) {
|
||||
var levenshtein = new SimMetrics.Net.Metric.Levenstein();
|
||||
FewShotPrompt rv = root.prompts.ElementAt(0);
|
||||
Func<FewShotPrompt, double> get_total_sim = (fsp) => {
|
||||
double similiarity = levenshtein.GetSimilarity(fsp.prompt, nl_prompt);
|
||||
foreach (FewShotExample fs_ex in fsp.examples) {
|
||||
similiarity += levenshtein.GetSimilarity(fs_ex.natural_language, nl_prompt);
|
||||
}
|
||||
return similiarity;
|
||||
};
|
||||
double highest_simmiliarity = 0.0;
|
||||
foreach (FewShotPrompt p in root.prompts) {
|
||||
double similiarity = get_total_sim(p); //levenshtein.GetSimilarity(p.prompt, nl_prompt);
|
||||
if (similiarity > highest_simmiliarity) {
|
||||
highest_simmiliarity = similiarity;
|
||||
rv = p;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
namespace bts.SilverPine {
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
// using OpenAI.GPT3;
|
||||
// using OpenAI.GPT3.ObjectModels.RequestModels;
|
||||
// using OpenAI.GPT3.Managers;
|
||||
using BCG;
|
||||
using BCG.Utilities.General;
|
||||
|
||||
|
||||
// given a prompt, this stream connects to openAI and gets the response back
|
||||
// it then fires a callback with the schema id, prompt, response
|
||||
public class OpenAIPromptStream : ViewStream, IWorker {
|
||||
#region OpenAI communication
|
||||
static string api_key = //File.ReadAllText("OpenAIGPT4.key");
|
||||
"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";
|
||||
|
||||
// Uses HttpClient to send the prompt to OpenAI gpt4, and queues the response in the response_queue
|
||||
public static async Task get_GPT4_http_responseAsync(string prompt, SyncQueue<string> response_queue) {
|
||||
Log.Gen.info($"OpenAIPromptStream.GetGPT4ResponseAsync prompt: {prompt}");
|
||||
// Read the API key from the file
|
||||
|
||||
|
||||
// OpenAI API URL for the completion request
|
||||
string apiUrl = "https://api.openai.com/v1/chat/completions";
|
||||
|
||||
// Create the request payload
|
||||
var requestBody = new {
|
||||
model = "gpt-3.5-turbo",
|
||||
messages = new[]
|
||||
{
|
||||
new { role = "user", content = prompt }
|
||||
},
|
||||
max_tokens = 500 // Adjust based on your response length needs
|
||||
};
|
||||
|
||||
// Serialize the payload to JSON
|
||||
string jsonRequestBody = JsonSerializer.Serialize(requestBody);
|
||||
|
||||
using (HttpClient client = new HttpClient()) {
|
||||
// Add the OpenAI API key to the Authorization header
|
||||
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {api_key}");
|
||||
|
||||
// Prepare the request content
|
||||
HttpContent content = new StringContent(jsonRequestBody, Encoding.UTF8, "application/json");
|
||||
|
||||
// Send the POST request to OpenAI API
|
||||
HttpResponseMessage response = await client.PostAsync(apiUrl, content);
|
||||
|
||||
// Ensure the response is successful
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// Read the response content as a string
|
||||
string response_content = await response.Content.ReadAsStringAsync();
|
||||
Log.Gen.info($"OpenAIPromptStream.GetGPT4ResponseAsync prompt: {prompt} response: {response_content}");
|
||||
|
||||
// Parse the response content
|
||||
var json_doc = JsonDocument.Parse(response_content);
|
||||
string gpt_response = json_doc.RootElement
|
||||
.GetProperty("choices")[0]
|
||||
.GetProperty("message")
|
||||
.GetProperty("content")
|
||||
.GetString();
|
||||
|
||||
//return gpt_response;
|
||||
response_queue.enqueue(gpt_response);
|
||||
Log.Gen.info($"OpenAIPromptStream.GetGPT4ResponseAsync gpt_response: {gpt_response}");
|
||||
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
private readonly string _prompt;
|
||||
private readonly ViewStreamDatabase _vsd;
|
||||
private SyncQueue<string> _queue = new SyncQueue<string>();
|
||||
public OpenAIPromptStream(string prompt)
|
||||
: this(ViewStreamDatabase.instance, prompt) {
|
||||
}
|
||||
|
||||
public OpenAIPromptStream(ViewStreamDatabase vsd, string prompt) {
|
||||
Log.Gen.info($"OpenAIPromptStream.OpenAIPromptStream prompt: {prompt}");
|
||||
_prompt = prompt;
|
||||
_vsd = vsd;
|
||||
}
|
||||
|
||||
protected override void myOnFirstSubscriber() {
|
||||
Task.Factory.StartNew(() => get_GPT4_http_responseAsync(_prompt, _queue));
|
||||
_vsd.addWorker(this);
|
||||
}
|
||||
|
||||
protected override void myOnLastSubscriber() {
|
||||
}
|
||||
|
||||
public void doWork() {
|
||||
var response = _queue.dequeue(0);
|
||||
if (response == null)
|
||||
return;
|
||||
IBlueTableSchema schema = BlueDataUtility.form_schema("OpenAIRespone",
|
||||
Tuple.Create("id", TypeCode.Int32),
|
||||
Tuple.Create("prompt", TypeCode.String),
|
||||
Tuple.Create("response", TypeCode.String));
|
||||
IBlueRow nr = new BlueRow(schema, 0, _prompt, response);
|
||||
BlueTable nt = new BlueTable(schema);
|
||||
nt.addRow(nr);
|
||||
var dp_out = BlueDataUtility.build_dp(nt, myLastValue as DataPacket);
|
||||
myFireEvent(dp_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
|
||||
<PackageReference Include="OpenAI" Version="2.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,42 +1,56 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(Spark.Admin.WebApp)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/safe_dep_glob.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/SymLink.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/ProtobufGenerateJs.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/ProtobufGenerateFs.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/Protobuf.cmake)
|
||||
|
||||
file(
|
||||
GLOB_RECURSE ${PROJECT_NAME}_PROTO_SOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
# dependencies
|
||||
set(PROTO_GLOBS
|
||||
../lib/api/*.proto
|
||||
../lib/api/services/*.proto
|
||||
../lib/domain_model/*.proto
|
||||
../lib/sparkproto/*.proto
|
||||
../lib/md/protos/*.proto
|
||||
../../externals/linux/include/google/protobuf/descriptor.proto
|
||||
../../externals/linux/include/google/protobuf/timestamp.proto
|
||||
)
|
||||
../../externals/linux/include/google/protobuf/timestamp.proto)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json
|
||||
COMMAND npm install --include=dev
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/package.json
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
file(
|
||||
GLOB_RECURSE _proto_rel_SOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${PROTO_GLOBS})
|
||||
|
||||
file(
|
||||
GLOB_RECURSE _proto_abs_SOURCES
|
||||
${PROTO_GLOBS})
|
||||
|
||||
file(
|
||||
GLOB_RECURSE _ts_SOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
src/*.ts)
|
||||
|
||||
file(
|
||||
GLOB_RECURSE _fs_SOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
src/*.fs)
|
||||
|
||||
set(_tools ${CMAKE_SOURCE_DIR}/tools)
|
||||
set(_quiet_exec ${_tools}/quiet_exec.sh)
|
||||
set(_venv_exec ${_tools}/venv_exec.sh)
|
||||
set(_tools_py ${CMAKE_SOURCE_DIR}/tools/py)
|
||||
|
||||
# The tsconfig file is generated as a function of the cmake build type, and
|
||||
# binary dir. Depending on the build type, it extends either
|
||||
# 'tsconfig.debug.json' or 'tsconfig.release.json'.
|
||||
set(_tsconfig_base "${CMAKE_CURRENT_SOURCE_DIR}/tsconfig.$<IF:$<CONFIG:Debug>,debug,release>.json")
|
||||
set(WEBPACK_MODE $<IF:$<CONFIG:Debug>,"development","production">)
|
||||
set(_tsconfig "${CMAKE_CURRENT_BINARY_DIR}/tsconfig.json")
|
||||
|
||||
set(_venv_python ${CMAKE_SOURCE_DIR}/.venv/bin/python)
|
||||
set(_gen_tsconfig_py ${_tools_py}/gen_tsconfig.py)
|
||||
set(_build_admin_web_app_py ${_tools_py}/build_admin_web_app.py)
|
||||
|
||||
set(_gen_tsconfig_deps ${_venv_exec} ${_venv_python} ${_gen_tsconfig_py} ${_tsconfig_base})
|
||||
|
||||
set(_build_admin_web_app_deps
|
||||
${_quiet_exec}
|
||||
${_venv_exec}
|
||||
@@ -46,142 +60,49 @@ set(_build_admin_web_app_deps
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/webpack.config.js
|
||||
${CMAKE_SOURCE_DIR}/src/lib/api/service_compiler/templates/fs/fable.fs
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json
|
||||
${${PROJECT_NAME}_PROTO_SOURCES}
|
||||
${_proto_rel_SOURCES}
|
||||
${_api_ts_SOURCES}
|
||||
${_ui_fs_SOURCES}
|
||||
${_tsconfig})
|
||||
|
||||
update_deps_file("${_build_admin_web_app_deps}")
|
||||
|
||||
function(npm_install path)
|
||||
add_custom_command(
|
||||
OUTPUT ${path}/package-lock.json
|
||||
COMMAND "npm" ARGS "install" "--include=dev"
|
||||
DEPENDS ${path}/package.json
|
||||
WORKING_DIRECTORY ${path}
|
||||
COMMENT "Run 'npm install' in ${path}")
|
||||
endfunction()
|
||||
|
||||
npm_install(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_tsconfig}
|
||||
COMMAND ${_venv_exec}
|
||||
ARGS
|
||||
${_venv_python}
|
||||
${_gen_tsconfig_py}
|
||||
--config-base ${_tsconfig_base}
|
||||
--config-out ${_tsconfig}
|
||||
--build-out ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS
|
||||
${_venv_exec}
|
||||
${_venv_python}
|
||||
${_gen_tsconfig_py}
|
||||
${_tsconfig_base}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json
|
||||
)
|
||||
|
||||
protobuf_generate_js(
|
||||
TARGET_NAME generate_js_protos
|
||||
PROTO_INCLUDE_DIRS
|
||||
..
|
||||
../../externals/linux/include
|
||||
PROTO_SOURCES ${${PROJECT_NAME}_PROTO_SOURCES}
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/proto.js
|
||||
)
|
||||
|
||||
protobuf_generate_fs(
|
||||
TARGET_NAME generate_fs_protos
|
||||
PROTO_INCLUDE_DIRS
|
||||
..
|
||||
../../externals/linux/include
|
||||
PROTO_SOURCES ${${PROJECT_NAME}_PROTO_SOURCES}
|
||||
OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/fable
|
||||
)
|
||||
|
||||
# Each input file maps to multiple output files with different extensions
|
||||
# (js, js.map, d.ts, fs). Transpile ts -> d.ts (and js), then d.ts -> fs.
|
||||
# Who knew front-end development could be so complicated? `\_(=_=)_/`
|
||||
file(
|
||||
GLOB_RECURSE ${PROJECT_NAME}_TS_SOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
src/*.ts
|
||||
)
|
||||
set(${PROJECT_NAME}_JS_PROTOS)
|
||||
set(${PROJECT_NAME}_TS_PROTOS)
|
||||
set(${PROJECT_NAME}_FS_PROTOS)
|
||||
foreach(_ts_source ${${PROJECT_NAME}_TS_SOURCES})
|
||||
get_filename_component(_ts_source_we ${_ts_source} NAME_WE)
|
||||
set(_prefix ${CMAKE_CURRENT_BINARY_DIR}/${_ts_source_we})
|
||||
list(APPEND ${PROJECT_NAME}_JS_PROTOS ${_prefix}.js ${_prefix}.js.map)
|
||||
list(APPEND ${PROJECT_NAME}_TS_PROTOS ${_prefix}.d.ts ${_prefix}.d.ts.map)
|
||||
list(APPEND ${PROJECT_NAME}_FS_PROTOS ${_prefix}.fs)
|
||||
add_custom_command(
|
||||
OUTPUT ${_prefix}.fs
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND npx --no-install ts2fable ${_prefix}.d.ts ${_prefix}.fs
|
||||
DEPENDS ${_prefix}.d.ts
|
||||
)
|
||||
endforeach()
|
||||
${_venv_python}
|
||||
${_gen_tsconfig_py}
|
||||
--config-base ${_tsconfig_base}
|
||||
--config-out ${_tsconfig}
|
||||
--build-out ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS ${_gen_tsconfig_deps})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${${PROJECT_NAME}_JS_PROTOS}
|
||||
${${PROJECT_NAME}_TS_PROTOS}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND npx
|
||||
--no-install tsc
|
||||
-p ${_tsconfig}
|
||||
DEPENDS
|
||||
${_tsconfig}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/proto.js
|
||||
)
|
||||
add_custom_target(
|
||||
transpile_type_script
|
||||
ALL
|
||||
DEPENDS
|
||||
${${PROJECT_NAME}_JS_PROTOS}
|
||||
${${PROJECT_NAME}_TS_PROTOS}
|
||||
)
|
||||
add_custom_target(generate_fsts_stubs ALL DEPENDS ${${PROJECT_NAME}_FS_PROTOS})
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bundle.js
|
||||
COMMAND ${_quiet_exec}
|
||||
ARGS
|
||||
${_venv_exec}
|
||||
${_venv_python}
|
||||
${_build_admin_web_app_py}
|
||||
--protos ${_proto_abs_SOURCES}
|
||||
--tsconfig ${_tsconfig}
|
||||
--mode ${WEBPACK_MODE}
|
||||
--output-dir ${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMENT "Building Spark.Admin.WebApp"
|
||||
DEPENDS ${_build_admin_web_app_deps})
|
||||
|
||||
sym_link_dir(
|
||||
TARGET_NAME link_webapp_public
|
||||
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/public
|
||||
DEST ${CMAKE_CURRENT_BINARY_DIR}/public
|
||||
)
|
||||
sym_link_dir(
|
||||
TARGET_NAME link_webapp_root
|
||||
SOURCE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEST ${CMAKE_SOURCE_DIR}/build/Spark.Admin.WebApp
|
||||
)
|
||||
|
||||
file(
|
||||
GLOB_RECURSE ${PROJECT_NAME}_FS_SOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
src/*.fs
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/bundle.js
|
||||
$<$<CONFIG:DEBUG>:${CMAKE_CURRENT_BINARY_DIR}/bundle.js.map>
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
COMMAND dotnet restore
|
||||
COMMAND dotnet tool restore
|
||||
COMMAND export SPARK_ADMIN_WEB_APP_OUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR}
|
||||
COMMAND dotnet fable -o ${CMAKE_CURRENT_BINARY_DIR} --verbose
|
||||
COMMAND npm run build -- --mode $<IF:$<CONFIG:Debug>,"development","production">
|
||||
DEPENDS
|
||||
${${PROJECT_NAME}_FS_SOURCES}
|
||||
${${PROJECT_NAME}_FS_PROTOS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Spark.Admin.WebApp.fsproj
|
||||
)
|
||||
add_custom_target(
|
||||
bundle_spark_admin_webapp ALL
|
||||
DEPENDS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/bundle.js
|
||||
$<$<CONFIG:DEBUG>:${CMAKE_CURRENT_BINARY_DIR}/bundle.js.map>
|
||||
COMMENT "Bundling Spark.Admin.WebApp"
|
||||
)
|
||||
|
||||
# Exclude 'public' dir because it is a symlink
|
||||
install(
|
||||
DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
PATTERN "public" EXCLUDE
|
||||
)
|
||||
# Install actual (non-symlinked) 'public' dir
|
||||
install(
|
||||
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/public"
|
||||
DESTINATION "${CMAKE_INSTALL_BINDIR}/${PROJECT_NAME}"
|
||||
)
|
||||
add_custom_target(admin_web_app_bundle ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/bundle.js)
|
||||
|
||||
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" DESTINATION "${SPARK_INSTALL_PREFIX}/bin")
|
||||
Generated
+15226
-2751
File diff suppressed because it is too large.
Load diff
@@ -42,7 +42,7 @@
|
||||
"ts-loader": "^9.4.2",
|
||||
"tsutils": "^3.21.0",
|
||||
"typescript": "^4.9.5",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.11.1",
|
||||
"ws": "^8.12.1"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ type Tab =
|
||||
| PositionManagementTab
|
||||
| MarginTab
|
||||
|
||||
let venues = [| Venue.BINANCE; Venue.BinanceUs; Venue.BinanceUsdsFutures; Venue.CBOE; Venue.COINBASE; Venue.DERIBIT; Venue.OKX; Venue.GLBX; Venue.ICE; Venue.TAIFEX; Venue.SIM; |]
|
||||
let venues = [| Venue.BINANCE; Venue.BinanceUs; Venue.BinanceUsdsFutures; Venue.CBOE; Venue.COINBASE; Venue.DERIBIT; Venue.GLBX; Venue.ICE; Venue.TAIFEX; Venue.SIM; |]
|
||||
|
||||
let securityTypes = [| SecurityType.SPOT; SecurityType.FUTURE; SecurityType.OPTION; SecurityType.SPREAD; |]
|
||||
|
||||
@@ -74,11 +74,6 @@ type TaifexExchangeField =
|
||||
| Origin of CustomerOrFirm
|
||||
| ClearingAccount of string
|
||||
|
||||
type OkxExchangeField =
|
||||
| CTI of CTICode
|
||||
| Origin of CustomerOrFirm
|
||||
| ClearingAccount of string
|
||||
|
||||
type SIMExchangeField =
|
||||
| CTI of CTICode
|
||||
| Origin of CustomerOrFirm
|
||||
|
||||
@@ -8,7 +8,6 @@ using MathNet.Numerics.Providers.FourierTransform;
|
||||
using BCG;
|
||||
using System.Windows.Automation;
|
||||
using bts.collections;
|
||||
using mbts.co2;
|
||||
|
||||
namespace mbts.spark {
|
||||
// Publishes theos for all options (on the side, also publishes the theos for TC2).
|
||||
@@ -115,53 +114,11 @@ namespace mbts.spark {
|
||||
}
|
||||
sym_theos.set_data(k, tp);
|
||||
}
|
||||
_override_theos(ref rv);
|
||||
foreach (var kv in rv) {
|
||||
_bb.post(SparkTags.TC2Tags.LiveTheosTag(kv.Key), kv.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void _override_theos(ref Dictionary<(string, Venue), ExpStrikeKeyedData<TheoPoint>> theos) {
|
||||
if (_compute_midmarket) {
|
||||
SystemContractData sc_data = _bb.read_state(SparkTags.SystemContractsTag);
|
||||
foreach (var kv in theos) {
|
||||
string sym = kv.Key.Item1;
|
||||
Venue exchange = kv.Key.Item2;
|
||||
foreach (var t in kv.Value.get_data_linearly()) {
|
||||
DateTime exp = t.first;
|
||||
double strike = t.second;
|
||||
TheoPoint tp = t.third;
|
||||
var call_sec_md = sc_data.get_option(exchange, sym, exp, strike, PutOrCall.Call);
|
||||
{
|
||||
NativePriceSize call_bid, call_ask;
|
||||
ulong time = 0;
|
||||
call_sec_md.Value.md.get_bbo(ref time, out call_bid, out call_ask);
|
||||
double call_mid = (call_bid.price + call_ask.price) / 2;
|
||||
tp.call = call_mid;
|
||||
}
|
||||
{
|
||||
var put_sec_md = sc_data.get_option(exchange, sym, exp, strike, PutOrCall.Put);
|
||||
NativePriceSize put_bid, put_ask;
|
||||
ulong time = 0;
|
||||
put_sec_md.Value.md.get_bbo(ref time, out put_bid, out put_ask);
|
||||
double put_mid = (put_bid.price + put_ask.price) / 2;
|
||||
tp.put = put_mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
//replace theos with market bid
|
||||
// get it from the bus and override
|
||||
} else {
|
||||
// do nothing, passes unchanged
|
||||
}
|
||||
}
|
||||
|
||||
private bool _compute_midmarket {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void _interp_and_publish() {
|
||||
var timer = Stopwatch.StartNew();
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
namespace mbts.spark {
|
||||
using bts.api;
|
||||
|
||||
using Spark.Api.Data;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -25,14 +23,14 @@ namespace mbts.spark {
|
||||
foreach (var kv in driver_map.get_price_map()) {
|
||||
var exp = kv.Key;
|
||||
var dmd = kv.Value;
|
||||
IEnumerable<SecurityMD> exp_secs = sc_data.get_securities((sec_md) => {
|
||||
var s = sec_md.security;
|
||||
return s.security_type() == SecurityType.Option &&
|
||||
s.Symbol == driver_map.option_symbol &&
|
||||
s.earliest_expiration() == (Security.is_perpetual_exp(exp.expiration)
|
||||
? ExpirationDate.Perpetual
|
||||
: ExpirationDate.FixedDate(exp.expiration));
|
||||
});
|
||||
IEnumerable<SecurityMD> exp_secs = sc_data.get_securities(
|
||||
(sec_md) => {
|
||||
var s = sec_md.security;
|
||||
return s.security_type() == SecurityType.Option &&
|
||||
s.Symbol == driver_map.option_symbol &&
|
||||
s.earliest_expiration() == exp.expiration;
|
||||
}
|
||||
);
|
||||
foreach (var sec_md in exp_secs) {
|
||||
rv[sec_md.security.Id] = kv.Value;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace mbts.spark {
|
||||
case SecurityType.Future:
|
||||
case SecurityType.Option:
|
||||
rv.GetOrAdd((sec.Exchange, sec.security_type(), sec.Symbol), _ => new())
|
||||
.Add(sec.earliest_expiration().Value);
|
||||
.Add(sec.earliest_expiration());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,16 +281,5 @@ namespace mbts.spark {
|
||||
else
|
||||
return tp.put + (tp.pdelta * driver_diff) + (0.5 * tp.pgamma * driver_diff * driver_diff);
|
||||
}
|
||||
|
||||
public static TheoPoint extrapolate(TheoPoint tp, double driver, bool is_call) {
|
||||
TheoPoint rv = tp.Clone() as TheoPoint;
|
||||
double h = driver - tp.driver;
|
||||
if (is_call) {
|
||||
rv.call = tp.call + h * (tp.cdelta);
|
||||
} else {
|
||||
rv.put = tp.put + h * (tp.cdelta);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 803 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user