Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b320a1075 | ||
|
|
e838413541 | ||
|
|
7d6d72b423 | ||
|
|
891d674ca4 | ||
|
|
92c1508b8c | ||
|
|
466915f6e9 | ||
|
|
1c68cfa08e | ||
|
|
cc75872c04 | ||
|
|
7e93866596 | ||
|
|
f4213eefe9 | ||
|
|
72bfafb376 | ||
|
|
5dbacfddd5 | ||
|
|
e29ea5d89b | ||
|
|
2885d929a8 | ||
|
|
a3e5bc4fba | ||
|
|
7944338516 | ||
|
|
bb19f737d5 | ||
|
|
77854a3cf0 | ||
|
|
d29ec26beb | ||
|
|
d64810e234 | ||
|
|
f3d2c9e5b9 | ||
|
|
63ac084a17 | ||
|
|
a21739a866 | ||
|
|
29f7c24a00 | ||
|
|
7d694f5c04 | ||
|
|
58c298fed8 | ||
|
|
ee825f76c7 | ||
|
|
dfb33efd45 | ||
|
|
dd7ebc54a2 | ||
|
|
14e08cf508 | ||
|
|
8f99d8d9ca | ||
|
|
c411a0c792 | ||
|
|
bc8513778b | ||
|
|
501dc37e94 | ||
|
|
c58b5fb0e6 | ||
|
|
f89f2b8ad0 | ||
|
|
5e3e85641d | ||
|
|
12349ef8b7 | ||
|
|
4a5f71e7f2 | ||
|
|
92d7503528 | ||
|
|
773f3db976 | ||
|
|
c99ee9e2d1 | ||
|
|
da71ec4c0f | ||
|
|
edd8fe7604 | ||
|
|
925bd72825 | ||
|
|
3ab2b132f6 | ||
|
|
f35a9662fd | ||
|
|
dd5b489e8f | ||
|
|
7bda1cc1cc | ||
|
|
58e88812b1 | ||
|
|
db80631901 | ||
|
|
593944266d | ||
|
|
b8883fc8ae | ||
|
|
efac4a6077 | ||
|
|
cb22d21f70 | ||
|
|
f6b17d9541 | ||
|
|
7a1298e015 | ||
|
|
0a81521e6e | ||
|
|
8771281954 | ||
|
|
b50381d386 | ||
|
|
91345cf9d2 | ||
|
|
19b3ba6615 | ||
|
|
6b68029b6d | ||
|
|
15c8a8bf28 | ||
|
|
2b2fe02315 | ||
|
|
1f4c91a344 | ||
|
|
92f8f74d8f | ||
|
|
ad2869ea6f | ||
|
|
979506d5be | ||
|
|
bc6e792855 | ||
|
|
5df90f27c8 | ||
|
|
d571642454 | ||
|
|
0695ddc33e | ||
|
|
c97e7675fd | ||
|
|
526805680a | ||
|
|
03e3549895 | ||
|
|
ebbc48771b | ||
|
|
2d6fb5c15c |
No files matched your search
@@ -22,4 +22,6 @@ node_modules
|
||||
paket-files
|
||||
project.lock.json
|
||||
src/server/sparkd/orderman/perf_analysis/data
|
||||
src/server/sparkd/orderman/perf_analysis/logs/
|
||||
src/server/sparkd/orderman/perf_analysis/trace_data/
|
||||
src/lib/orderman/perf_analysis/logs/latency_data/
|
||||
@@ -54,6 +54,8 @@ else ()
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/web ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/data_files ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/lib/libspark.so ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/server/plugins
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/sdk/examples/order_plugin_example.so ${CMAKE_BINARY_DIR}/server/plugins/
|
||||
COMMENT "Creating server runtime layout"
|
||||
DEPENDS sparkd data_files_dir)
|
||||
|
||||
|
||||
+59
-55
@@ -4,7 +4,7 @@ VisualStudioVersion = 15.0.27130.2024
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_api", "src\client\spark_api\spark_api.csproj", "{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libspark", "build\src\lib\libspark.vcxproj", "{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libspark", "build\src\lib\libspark.vcxproj", "{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spark", "src\client\spark\Spark.csproj", "{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}"
|
||||
EndProject
|
||||
@@ -12,11 +12,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sparkcmd", "src\client\spar
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_core", "src\client\spark_core\spark_core.csproj", "{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "build\ZERO_CHECK.vcxproj", "{9AD1A867-93A9-301D-BF77-0113E18E9E39}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZERO_CHECK", "build\ZERO_CHECK.vcxproj", "{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_sdk", "src\client\spark_sdk\spark_sdk.csproj", "{6963C314-83C4-4667-B0D0-C2F7AE208C29}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3} = {8530E0E8-3768-37EC-B1E1-8248C5A92FE3}
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C} = {69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_test", "src\client\spark_test\spark_test.csproj", "{ECD78CC5-138F-4809-A764-2358C2AC2E82}"
|
||||
@@ -57,22 +57,22 @@ Global
|
||||
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.Build.0 = Release|x64
|
||||
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x86.ActiveCfg = Release|x64
|
||||
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x86.Build.0 = Release|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.Debug|x64.Build.0 = Debug|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.Release|x64.ActiveCfg = Release|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.Release|x64.Build.0 = Release|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.Release|x86.ActiveCfg = Release|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{8530E0E8-3768-37EC-B1E1-8248C5A92FE3}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.Debug|x64.Build.0 = Debug|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.Release|x64.ActiveCfg = Release|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.Release|x64.Build.0 = Release|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.Release|x86.ActiveCfg = Release|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{69D73CF1-9D7A-38CA-9817-0D0C3E3BCB3C}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
|
||||
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x64.Build.0 = Debug|x64
|
||||
@@ -93,26 +93,30 @@ Global
|
||||
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|x64.Build.0 = Release|x64
|
||||
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|x86.ActiveCfg = Release|x64
|
||||
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|x86.Build.0 = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x64.Build.0 = Debug|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|Any CPU.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|Any CPU.Build.0 = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x64.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x64.Build.0 = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x86.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x86.Build.0 = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x64.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x64.Build.0 = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x86.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|Any CPU.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|Any CPU.Build.0 = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x64.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x64.Build.0 = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x86.ActiveCfg = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x86.Build.0 = Release|x64
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x86.Build.0 = Debug|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x64.Build.0 = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x86.Build.0 = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
|
||||
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
|
||||
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|x64.Build.0 = Debug|x64
|
||||
@@ -133,22 +137,22 @@ Global
|
||||
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x64.Build.0 = Release|x64
|
||||
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x86.ActiveCfg = Release|x64
|
||||
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x86.Build.0 = Release|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.Debug|x64.Build.0 = Debug|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.Release|x64.ActiveCfg = Release|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.Release|x64.Build.0 = Release|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.Release|x86.ActiveCfg = Release|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{9AD1A867-93A9-301D-BF77-0113E18E9E39}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.Debug|x64.Build.0 = Debug|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.Debug|x86.ActiveCfg = Debug|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.Release|x64.ActiveCfg = Release|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.Release|x64.Build.0 = Release|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.Release|x86.ActiveCfg = Release|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{33E7E6C5-04E3-36A8-A751-639BE5E72B9B}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64
|
||||
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|x64.Build.0 = Debug|x64
|
||||
|
||||
@@ -5,11 +5,9 @@ using mbts.collections;
|
||||
using mbts.spark.utilities;
|
||||
using mbts.ui;
|
||||
using mbts.ui.controls;
|
||||
using mbts.ui.settings;
|
||||
using mbts.ui.spark;
|
||||
using mbts.ui.utility;
|
||||
using mbts.utils;
|
||||
using bts.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -18,7 +16,6 @@ using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Windows.Input;
|
||||
|
||||
|
||||
namespace mbts.spark {
|
||||
partial class MarketViewVM {
|
||||
public class Row : SecurityMDRow, IDisposable, IEquatable<Row>, DIYGrid.IRowVM, DIYGrid.IActionableRowVM {
|
||||
@@ -78,16 +75,29 @@ namespace mbts.spark {
|
||||
ask_price_click = new DelegateCommand(() => _show_order_ticket(MarketViewView.Columns.Ask));
|
||||
ask_size_click = new DelegateCommand(() => _show_order_ticket(MarketViewView.Columns.AskSize));
|
||||
working_asks_click = new DelegateCommand(() => _show_order_book(MarketViewView.Columns.WorkingAsks));
|
||||
|
||||
_position.value_set += position_value_set;
|
||||
_inside_bids.value_set += inside_bids_value_set;
|
||||
_inside_asks.value_set += inside_asks_value_set;
|
||||
_day_change.Changed += day_change_Changed;
|
||||
_animation.AnimationsChanged += on_animations_changed;
|
||||
void on_animations_changed() => RaisePropertyChanged(nameof(animations));
|
||||
|
||||
_dispose = Disposable.Create(
|
||||
_orders_model.on_security_root_orders(security.Id).OnDispatcher().Subscribe(_on_orders),
|
||||
_position.OnDispatcher().Subscribe(v => _animation.animate_position(v.newval > v.oldval)),
|
||||
_inside_bids.OnDispatcher().Subscribe(v => _animation.animate_working_bids_inside(v.newval)),
|
||||
_inside_asks.OnDispatcher().Subscribe(v => _animation.animate_working_asks_inside(v.newval)),
|
||||
_day_change.OnDispatcher().Subscribe(v => _animation.animate_day_change(v.newval > v.oldval)),
|
||||
Disposable.Create(() => _animation.AnimationsChanged -= on_animations_changed)
|
||||
Disposable.Create(() => {
|
||||
_position.value_set -= position_value_set;
|
||||
_inside_bids.value_set -= inside_bids_value_set;
|
||||
_inside_asks.value_set -= inside_asks_value_set;
|
||||
_day_change.Changed -= day_change_Changed;
|
||||
_animation.AnimationsChanged -= on_animations_changed;
|
||||
})
|
||||
);
|
||||
|
||||
void position_value_set((int oldval, int newval) v) => _animation.animate_position(v.newval > v.oldval);
|
||||
void inside_bids_value_set((bool oldval, bool newval) v) => _animation.animate_working_bids_inside(v.newval);
|
||||
void inside_asks_value_set((bool oldval, bool newval) v) => _animation.animate_working_asks_inside(v.newval);
|
||||
void day_change_Changed(double oldval, double newval) => _animation.animate_day_change(newval > oldval);
|
||||
void on_animations_changed() => RaisePropertyChanged(nameof(animations));
|
||||
}
|
||||
|
||||
public event Action invalidated;
|
||||
@@ -129,27 +139,52 @@ namespace mbts.spark {
|
||||
|
||||
public void raise_invalidated() => invalidated?.Invoke();
|
||||
|
||||
public void refresh() {
|
||||
/// <summary>
|
||||
/// Returns a list of IDisposable 'update jobs.' Each item represents a job that will be executed when disposed; all jobs should be executed on the dispatcher thread.
|
||||
/// </summary>
|
||||
// Note: not guarenteed to be on the dispatcher thread, so all view-notifying actions should be wrapped in a IDisposable.
|
||||
// Having said that, perform as much work as possible locally.
|
||||
public List<IDisposable> refresh() {
|
||||
var update_jobs = new List<IDisposable>();
|
||||
bool dirty = false;
|
||||
if (md.md.get_bbo(ref _bbo_ref, out NativePriceSize b, out NativePriceSize a)) {
|
||||
_bid_price.set(b.price);
|
||||
_bid_size.set(b.size);
|
||||
_ask_price.set(a.price);
|
||||
_ask_size.set(a.size);
|
||||
_inside_bids.on_next_distinct(_bid_price.Value >= _working_best_bid.value, ref dirty);
|
||||
_inside_asks.on_next_distinct(_ask_price.Value <= _working_best_ask.value, ref dirty);
|
||||
prop_job(_bid_price, b.price);
|
||||
prop_job(_bid_size, b.size);
|
||||
prop_job(_ask_price, a.price);
|
||||
prop_job(_ask_size, a.size);
|
||||
cell_prop_job(_inside_bids, b.price >= _working_best_bid.value);
|
||||
cell_prop_job(_inside_asks, a.price >= _working_best_ask.value);
|
||||
}
|
||||
if (md.md.get_last_trade(ref _last_ref, out NativePriceSize ps, out DateTime ts, out ulong v)) {
|
||||
_last_price.set(ps.price);
|
||||
_last_size.on_next_distinct(ps.size, ref dirty);
|
||||
_volume.on_next_distinct(v, ref dirty);
|
||||
double new_last_price = last_price;
|
||||
if (md.md.get_last_trade(ref _last_ref, out NativePriceSize ps, out ulong v)) {
|
||||
new_last_price = ps.price;
|
||||
prop_job(_last_price, new_last_price);
|
||||
cell_prop_job(_last_size, ps.size);
|
||||
cell_prop_job(_volume, v);
|
||||
}
|
||||
double new_settlement = md.md.settlement_price;
|
||||
prop_job(_settlement, new_settlement);
|
||||
prop_job(_session_low, md.md.session_low);
|
||||
prop_job(_session_high, md.md.session_high);
|
||||
prop_job(_day_change, new_last_price - new_settlement);
|
||||
|
||||
if (dirty) {
|
||||
update_jobs.Add(Disposable.Create(() => {
|
||||
invalidated?.Invoke();
|
||||
}));
|
||||
}
|
||||
return update_jobs;
|
||||
|
||||
void prop_job<T>(Property<T> p, T newval) {
|
||||
var uj = p.set_as_job(newval);
|
||||
if (uj != null)
|
||||
update_jobs.Add(uj);
|
||||
}
|
||||
void cell_prop_job<T>(CellProperty<T> p, T newval) {
|
||||
var uj = p.on_next_distinct_as_job(newval, ref dirty);
|
||||
if (uj != null)
|
||||
update_jobs.Add(uj);
|
||||
}
|
||||
_settlement.set(md.md.settlement_price);
|
||||
_session_low.set(md.md.session_low);
|
||||
_session_high.set(md.md.session_high);
|
||||
_day_change.set(last_price - settlement);
|
||||
if (dirty)
|
||||
invalidated?.Invoke();
|
||||
}
|
||||
|
||||
public bool Equals(Row other) =>
|
||||
|
||||
@@ -3,10 +3,13 @@ using mbts.spark.filters;
|
||||
using mbts.ui;
|
||||
using mbts.ui.utility;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using static bts.shell.MarketViewWindowFactory;
|
||||
@@ -14,7 +17,7 @@ using static mbts.ui.controls.DIYGrid;
|
||||
using static mbts.ui.spark.MarketViewView;
|
||||
|
||||
namespace mbts.spark {
|
||||
partial class MarketViewVM : SecurityMDGrid<MarketViewVM.Row, SecurityMD> {
|
||||
partial class MarketViewVM : SecurityMDGrid<MarketViewVM.Row, SecurityMD>, IPrepareUpdateForDispatcher {
|
||||
readonly IBus _bus;
|
||||
readonly OrdersModel _orders_model;
|
||||
|
||||
@@ -112,8 +115,7 @@ namespace mbts.spark {
|
||||
}), DataGridFilterHelper.hook_filters(rows_view,
|
||||
security_filter, bid_price_filter, bid_size_filter, ask_price_filter, ask_size_filter, last_price_filter, last_size_filter, day_change_filter, settlement_filter,
|
||||
session_low_filter, session_high_filter, position_filter, working_bid_volume_filter, working_ask_volume_filter, volume_filter, security_key_filter),
|
||||
securities_connectable.Connect(),
|
||||
WorkLoop.Start("MarketView", _refresh)
|
||||
securities_connectable.Connect()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -159,6 +161,25 @@ namespace mbts.spark {
|
||||
}
|
||||
#endregion
|
||||
|
||||
public IDisposable prepare_update() {
|
||||
ConcurrentBag<List<IDisposable>> to_update = new ConcurrentBag<List<IDisposable>>();
|
||||
try {
|
||||
Parallel.For(0, _row_vms.Count, i => {
|
||||
var r = _row_vms[i];
|
||||
var update_jobs = r.refresh();
|
||||
if (update_jobs.Count > 0)
|
||||
to_update.Add(update_jobs);
|
||||
});
|
||||
} catch (IndexOutOfRangeException) {
|
||||
// since rows (securities) will only be added/removed through rare user intervention,
|
||||
// it is worth catching the occassional exception in exchange for lock-free code.
|
||||
// if a row misses an update, or gets updated more than once, that's okay too;
|
||||
// in 100ms it will tick again, so the data should never be more than a few 100 ms old, and rarely older than 100.
|
||||
}
|
||||
// return null, rather than an empty IDisposable; this signals to the UpdateMaster that it may skip the call to Dispatcher.InvokeAsync() as there is nothing to dispose.
|
||||
return to_update.Count == 0 ? null : Disposable.Create(() => to_update.SelectMany(_ => _).DisposeAll());
|
||||
}
|
||||
|
||||
protected override Row row_factory(SecurityMD smd) => new Row(_bus, smd, _orders_model);
|
||||
protected override void on_row_removed(Row row) => row.Dispose();
|
||||
protected override IEnumerable<SortingCriteria> get_default_sorting() { yield return new SortingCriteria(nameof(Row.security), true); }
|
||||
@@ -167,4 +188,4 @@ namespace mbts.spark {
|
||||
foreach (var r in _row_vms) r.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,16 +14,18 @@ using System.Windows;
|
||||
namespace mbts.spark {
|
||||
class MarketViewWindow : SparkWindow<MarketViewWindowFactory.StartupData>, ISharedWindow {
|
||||
const string _window_type = "MarketView", _thread_id = "MarketView", _window_type_display_name = "Market View";
|
||||
readonly DispatcherUpdateMaster _dispatcher_update_master;
|
||||
readonly OrdersModel _orders_model;
|
||||
readonly AllowOnce _init_guard = new AllowOnce("MarketView");
|
||||
MarketViewVM _vm;
|
||||
MarketViewView _view;
|
||||
MarketViewWindowFactory.StartupData _state;
|
||||
IReadOnlyList<SparkCommand> _commands;
|
||||
IDisposable _subscriptions;
|
||||
IDisposable _resources;
|
||||
|
||||
public MarketViewWindow(MarketViewWindowFactory factory, IBus bus, OrdersModel orders_model, MarketViewWindowFactory.StartupData state)
|
||||
public MarketViewWindow(MarketViewWindowFactory factory, DispatcherUpdateMaster dispatcher_update_master, IBus bus, OrdersModel orders_model, MarketViewWindowFactory.StartupData state)
|
||||
: base("Market View", bus, factory, SparkCommands.ShowMarketView.icon) {
|
||||
_dispatcher_update_master = dispatcher_update_master;
|
||||
_orders_model = orders_model;
|
||||
_state = state;
|
||||
Icon.Freeze();
|
||||
@@ -57,12 +59,14 @@ namespace mbts.spark {
|
||||
SparkCommands.ShowSyntheticCreate.complete(_vm.selected_securities_observable(), secs => secs.Count > 0 && secs.Count <= 24, secs => new SecurityCriteria(secs)),
|
||||
SparkCommands.change_securities_command(() => (update_securities_cmd, _state.security_criteria))
|
||||
};
|
||||
_subscriptions = _bus.subscribe(update_securities_cmd.tag).OnDispatcher().Subscribe(c =>
|
||||
_state_changed?.Invoke(_state = new MarketViewWindowFactory.StartupData(c, _vm.rows_view.GetSortingCriteria(), _vm.get_filter_states())));
|
||||
_resources = Disposable.Create(
|
||||
_bus.subscribe(update_securities_cmd.tag).OnDispatcher().Subscribe(
|
||||
c => _state_changed?.Invoke(_state = new MarketViewWindowFactory.StartupData(c, _vm.rows_view.GetSortingCriteria(), _vm.get_filter_states()))),
|
||||
_dispatcher_update_master.attach(_vm));
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
Disposable.dispose(ref _subscriptions);
|
||||
Disposable.dispose(ref _resources);
|
||||
_vm.Dispose();
|
||||
Commands.OfType<IDisposable>().DisposeAll();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace bts.shell {
|
||||
class MarketViewWindowFactory : ShellWindowFactory<MarketViewWindowFactory.StartupData> {
|
||||
readonly IBus _bus;
|
||||
readonly OrdersModel _orders_model;
|
||||
readonly DispatcherUpdateMaster _dispatcher_update_master = new DispatcherUpdateMaster("MarketView DispatcherUpdateMaster");
|
||||
|
||||
public MarketViewWindowFactory(MarketShellModule module, IBus bus, OrdersModel orders_model) : base(module, "MarketView") {
|
||||
_bus = bus;
|
||||
@@ -25,7 +26,7 @@ namespace bts.shell {
|
||||
void _show(SecurityCriteria criteria) =>
|
||||
_bus.post(SparkTags.ShowWindow, _create(new StartupData(criteria, new List<SortingCriteria> { new SortingCriteria(nameof(MarketViewVM.Row.security), true) }, null)));
|
||||
|
||||
IShellWindow _create(StartupData state) => new MarketViewWindow(this, _bus, _orders_model, state);
|
||||
IShellWindow _create(StartupData state) => new MarketViewWindow(this, _dispatcher_update_master, _bus, _orders_model, state);
|
||||
|
||||
[ProtoContract]
|
||||
public class StartupData {
|
||||
|
||||
@@ -134,7 +134,9 @@ namespace bts.spark {
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (neworder, oldorder) in update.changes) {
|
||||
foreach (var order in update.changes) {
|
||||
var neworder = order.New;
|
||||
var oldorder = order.Old;
|
||||
(var security, var spec) = get_security(neworder.Def.SecurityKey);
|
||||
//
|
||||
// description
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using bts;
|
||||
using bts.api;
|
||||
using bts.api.orderman;
|
||||
using bts.utils;
|
||||
using mbts.ui;
|
||||
using mbts.ui.shell;
|
||||
using System;
|
||||
@@ -11,6 +12,60 @@ using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
|
||||
namespace mbts.spark {
|
||||
struct OrderTemplateKey : IEquatable<OrderTemplateKey> {
|
||||
public readonly CustomOrderDefinition.CustomOneofCase type;
|
||||
public readonly string name;
|
||||
|
||||
public OrderTemplateKey(CustomOrderDefinition.CustomOneofCase type)
|
||||
: this(type, OrderUtils.order_type_display_name(type)) { }
|
||||
|
||||
public OrderTemplateKey(CustomOrderDefinition.CustomOneofCase type, string name) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public bool Equals(OrderTemplateKey other) =>
|
||||
type == other.type &&
|
||||
name == other.name;
|
||||
|
||||
public override bool Equals(object obj) =>
|
||||
obj is OrderTemplateKey other && Equals(other);
|
||||
|
||||
public override int GetHashCode() =>
|
||||
EqualityComparer.aggregate_hash(
|
||||
type.GetHashCode(),
|
||||
name == null ? 0 : name.GetHashCode());
|
||||
|
||||
public override string ToString() => $"{name}:{type}";
|
||||
|
||||
public static bool operator ==(OrderTemplateKey a, OrderTemplateKey b) => a.Equals(b);
|
||||
public static bool operator !=(OrderTemplateKey a, OrderTemplateKey b) => !a.Equals(b);
|
||||
}
|
||||
|
||||
struct OrderTemplateHeader : IEquatable<OrderTemplateHeader> {
|
||||
public readonly OrderTemplateKey key;
|
||||
// Note: display_name is NOT part of EQUALITY
|
||||
public readonly string display_name;
|
||||
|
||||
public OrderTemplateHeader(CustomOrderDefinition.CustomOneofCase type)
|
||||
: this(new OrderTemplateKey(type), OrderUtils.order_type_display_name(type)) { }
|
||||
|
||||
public OrderTemplateHeader(OrderTemplateKey key, string display_name) {
|
||||
this.key = key;
|
||||
this.display_name = display_name;
|
||||
}
|
||||
|
||||
public bool Equals(OrderTemplateHeader other) =>
|
||||
key.Equals(other.key);
|
||||
|
||||
public override bool Equals(object obj) =>
|
||||
obj is OrderTemplateHeader other && Equals(other);
|
||||
|
||||
public override int GetHashCode() => key.GetHashCode();
|
||||
|
||||
public override string ToString() => $"{display_name} ({key})";
|
||||
}
|
||||
|
||||
class InlineOrderProperties {
|
||||
public readonly InlineUserProperty<AccountTuple> account;
|
||||
public readonly InlineUserProperty<TimeInForce> time_in_force;
|
||||
@@ -39,7 +94,7 @@ namespace mbts.spark {
|
||||
class OrderPropertiesEditorVM : DisposableViewModelBase {
|
||||
readonly OrdersModel _model;
|
||||
readonly Property<SecurityImmutable> _security;
|
||||
readonly SelectorProperty<AccountTuple> _accounts;
|
||||
readonly SelectorProperty<AccountTuple, AccountTuple?> _accounts;
|
||||
readonly SelectorProperty<TimeInForce> _time_in_force;
|
||||
readonly SelectorProperty<IOrderTypeVM> _order_type;
|
||||
IDisposable _order_type_param_errors_sub;
|
||||
@@ -58,14 +113,21 @@ namespace mbts.spark {
|
||||
nameof(selected_account),
|
||||
model.factory.subscribe_account_tuples(),
|
||||
order_properties.Select(ops => ops.account),
|
||||
() => accounts?.FirstOrDefault() ?? default,
|
||||
val => (!string.IsNullOrWhiteSpace(val.name) && accounts.Contains(val), "Please select an account"));
|
||||
a => new AccountTuple?(a),
|
||||
() => {
|
||||
foreach (var a in accounts) {
|
||||
return a;
|
||||
}
|
||||
return new AccountTuple?();
|
||||
},
|
||||
EqualityComparer<AccountTuple?>.Default,
|
||||
new[] { new PropertyValidation<AccountTuple?>(a => (a.HasValue && !string.IsNullOrWhiteSpace(a.Value.name) && accounts.Contains(a.Value), "Please select an account")) }.ToReadOnlyList());
|
||||
_order_type = backing(
|
||||
nameof(selected_order_type),
|
||||
security_source.Select(s => model.factory.default_order_type_defs(s).Select(create_order_type_vm)),
|
||||
security_source.Select(s => model.factory.default_order_type_templates(s).Select(kv => create_order_type_vm(kv.Value, kv.Key.key.name, kv.Key.display_name))),
|
||||
order_properties.Select(get_order_type_vm_prop),
|
||||
get_default_order_type_vm,
|
||||
(a, b) => a.order_type == b.order_type);
|
||||
EqualityComparer.null_check_wrapper(OrderTypeVMExtensions.key_comparer));
|
||||
_order_type.Changed += on_selected_order_type_changed;
|
||||
_time_in_force = backing(
|
||||
nameof(selected_time_in_force),
|
||||
@@ -77,19 +139,22 @@ namespace mbts.spark {
|
||||
tif => time_in_forces.Contains(tif));
|
||||
_dispose = Disposable.Create(() => _order_type.Changed -= on_selected_order_type_changed);
|
||||
// local methods
|
||||
IOrderTypeVM create_order_type_vm(CustomOrderDefinitionImmutable cd) {
|
||||
IOrderTypeVM create_order_type_vm(CustomOrderDefinitionImmutable cd, string id, string display_name) {
|
||||
IOrderTypeVM vm = null;
|
||||
if(cd.CustomCase == CustomOrderDefinition.CustomOneofCase.Dynamic)
|
||||
vm = OrderTypeVMFactory.create(cd.CustomCase, model, security_md_source, cd.Dynamic.DynamicOrderType);
|
||||
vm = OrderTypeVMFactory.create(cd.CustomCase, id, display_name, model, security_md_source, cd.Dynamic.DynamicOrderType);
|
||||
else
|
||||
vm = OrderTypeVMFactory.create(cd.CustomCase, model, security_md_source);
|
||||
vm = OrderTypeVMFactory.create(cd.CustomCase, id, display_name, model, security_md_source);
|
||||
vm.load_from(cd);
|
||||
return vm;
|
||||
}
|
||||
InlineUserProperty<IOrderTypeVM> get_order_type_vm_prop(InlineOrderProperties p) {
|
||||
if (!p.order_type_def.has_value)
|
||||
return new InlineUserProperty<IOrderTypeVM>();
|
||||
return new InlineUserProperty<IOrderTypeVM>(create_order_type_vm(p.order_type_def.value), p.order_type_def.force_override);
|
||||
return new InlineUserProperty<IOrderTypeVM>(
|
||||
create_order_type_vm(p.order_type_def.value, p.order_type_def.value.CustomCase.ToString(),
|
||||
OrderUtils.order_type_display_name(p.order_type_def.value.CustomCase)),
|
||||
p.order_type_def.force_override);
|
||||
}
|
||||
IOrderTypeVM get_default_order_type_vm() {
|
||||
var ot = model.factory.default_order_type(security);
|
||||
@@ -114,13 +179,13 @@ namespace mbts.spark {
|
||||
|
||||
public SecurityImmutable security => _security.Value;
|
||||
public ReadOnlyObservableCollection<AccountTuple> accounts => _accounts.items;
|
||||
public AccountTuple selected_account { get => _accounts.selected_item; set => _accounts.selected_item = value; }
|
||||
public AccountTuple? selected_account { get => _accounts.selected_item; set => _accounts.selected_item = value; }
|
||||
public ReadOnlyObservableCollection<TimeInForce> time_in_forces => _time_in_force.items;
|
||||
public TimeInForce selected_time_in_force { get => _time_in_force.selected_item; set => _time_in_force.selected_item = value; }
|
||||
public ReadOnlyObservableCollection<IOrderTypeVM> order_types => _order_type.items;
|
||||
public IOrderTypeVM selected_order_type { get => _order_type.selected_item; set => _order_type.selected_item = value; }
|
||||
|
||||
public IObservable<AccountTuple> observe_account(bool start_immediately = false) =>
|
||||
public IObservable<AccountTuple?> observe_account(bool start_immediately = false) =>
|
||||
_accounts.observe_current(start_immediately);
|
||||
|
||||
public IObservable<TimeInForce> observe_time_in_force(bool start_immediately = false) =>
|
||||
|
||||
@@ -17,22 +17,22 @@ namespace mbts.spark
|
||||
{
|
||||
class InlineCoverOrderProperties
|
||||
{
|
||||
public InlineCoverOrderProperties(CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types)
|
||||
public InlineCoverOrderProperties(OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
{
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
|
||||
var hedgetype = CustomOneofCase.Limit;
|
||||
this.selected_hedge_order_type = new InlineUserProperty<CustomOneofCase>(hedgetype, true);
|
||||
this.hedge_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_hedge_order_type = new InlineUserProperty<OrderTemplateHeader>(new OrderTemplateHeader(hedgetype), true);
|
||||
this.hedge_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
|
||||
hedge_ticks = new InlineUserProperty<int>(1, false);
|
||||
}
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_hedge_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> hedge_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_hedge_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> hedge_order_types;
|
||||
|
||||
public readonly InlineUserProperty<int> hedge_ticks;
|
||||
|
||||
@@ -42,25 +42,25 @@ namespace mbts.spark
|
||||
{
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineCoverOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _hedge_order_choices;
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _hedge_order_choices;
|
||||
IOrderTypeVM _hedge_order;
|
||||
IDisposable _hedge_order_errors_sub;
|
||||
|
||||
public int hedge_ticks { get; set; } = 1;
|
||||
|
||||
public CoverOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
public CoverOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineCoverOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList())))
|
||||
new InlineCoverOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name)
|
||||
{ }
|
||||
|
||||
public CoverOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineCoverOrderProperties> inline_properties) : base(model)
|
||||
IObservable<InlineCoverOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
{
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
@@ -75,11 +75,11 @@ namespace mbts.spark
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override))
|
||||
{
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (_hedge_order_choices != null && (_hedge_order == null || p.selected_hedge_order_type.force_override))
|
||||
{
|
||||
_select_hedge_order(p.selected_hedge_order_type.value);
|
||||
_select_hedge_order(p.selected_hedge_order_type.value.key.type);
|
||||
}
|
||||
if (p.hedge_ticks.force_override)
|
||||
{
|
||||
@@ -116,7 +116,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_child_order_choices == null)
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_hedge_order_choices == null)
|
||||
_hedge_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_hedge_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _hedge_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -200,7 +200,7 @@ namespace mbts.spark
|
||||
void _select_child_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
@@ -216,7 +216,7 @@ namespace mbts.spark
|
||||
void _select_hedge_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_hedge_order_type.has_value ?
|
||||
_inline_props.selected_hedge_order_type.value :
|
||||
_inline_props.selected_hedge_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_hedge_order(ot);
|
||||
}
|
||||
|
||||
@@ -20,23 +20,23 @@ namespace mbts.spark
|
||||
public static void add_dynamic_order_defs(List<CustomOrderDefinitionImmutable> defs,
|
||||
Func<CustomOrderDefinition.CustomOneofCase, CustomOrderDefinition> factory)
|
||||
{
|
||||
var dyntypes = _list.Value;
|
||||
foreach (var d in dyntypes.dynamic_orders)
|
||||
{
|
||||
var dorder = factory(CustomOrderDefinition.CustomOneofCase.Dynamic);
|
||||
dorder.Dynamic.DynamicOrderType = d.type_name;
|
||||
foreach (var p in d.parameter_keys)
|
||||
dorder.Dynamic.Parameters.Add(p, string.Empty);
|
||||
defs.Add(new CustomOrderDefinitionImmutable(dorder));
|
||||
}
|
||||
// var dyntypes = _list.Value;
|
||||
// foreach (var d in dyntypes.dynamic_orders)
|
||||
// {
|
||||
// var dorder = factory(CustomOrderDefinition.CustomOneofCase.Dynamic);
|
||||
// dorder.Dynamic.DynamicOrderType = d.type_name;
|
||||
// foreach (var p in d.parameter_keys)
|
||||
// dorder.Dynamic.Parameters.Add(p, string.Empty);
|
||||
// defs.Add(new CustomOrderDefinitionImmutable(dorder));
|
||||
// }
|
||||
}
|
||||
|
||||
internal static List<NameValueVM> get_parameters(string dyntype)
|
||||
{
|
||||
List<NameValueVM> par = new List<NameValueVM>();
|
||||
var order = _list.Value.dynamic_orders.FirstOrDefault(x => x.type_name == dyntype);
|
||||
if (order != null)
|
||||
par.AddRange(order.parameter_keys.Select(x => new NameValueVM() { name = x, value = string.Empty }));
|
||||
// var order = _list.Value.dynamic_orders.FirstOrDefault(x => x.type_name == dyntype);
|
||||
// if (order != null)
|
||||
// par.AddRange(order.parameter_keys.Select(x => new NameValueVM() { name = x, value = string.Empty }));
|
||||
return par;
|
||||
}
|
||||
}
|
||||
@@ -53,14 +53,14 @@ namespace mbts.spark
|
||||
{
|
||||
class InlineDynamicOrderProperties
|
||||
{
|
||||
public InlineDynamicOrderProperties(CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types)
|
||||
public InlineDynamicOrderProperties(OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
{
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
}
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
}
|
||||
|
||||
class DynamicOrderVM : OrderTypeVMBase<DynamicOrderDefinition>, IHierarchicalOrderTypeVM, IDisposable
|
||||
@@ -68,8 +68,8 @@ namespace mbts.spark
|
||||
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineDynamicOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
@@ -77,13 +77,13 @@ namespace mbts.spark
|
||||
string _dyn_type;
|
||||
List<NameValueVM> _parameters;
|
||||
|
||||
public DynamicOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string dyn_type)
|
||||
public DynamicOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string dyn_type, string id, string display_name)
|
||||
: this(model, security_md_source, dyn_type, security_md_source.Select(smd =>
|
||||
new InlineDynamicOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList())))
|
||||
new InlineDynamicOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name)
|
||||
{ }
|
||||
|
||||
public DynamicOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string dyn_type,
|
||||
IObservable<InlineDynamicOrderProperties> inline_properties) : base(model)
|
||||
IObservable<InlineDynamicOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
{
|
||||
_security_md_source = security_md_source;
|
||||
_dyn_type = dyn_type;
|
||||
@@ -100,7 +100,7 @@ namespace mbts.spark
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override))
|
||||
{
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
_inline_props = p;
|
||||
_validate();
|
||||
@@ -115,17 +115,17 @@ namespace mbts.spark
|
||||
|
||||
public override void assign_to(CustomOrderDefinition value)
|
||||
{
|
||||
if (_child_order == null)
|
||||
_select_child_order(model.factory.default_order_type(_security.Value, true));
|
||||
_validate();
|
||||
if (!HasErrors)
|
||||
{
|
||||
var i = factory.dynamic_order();
|
||||
i.DynamicOrderType = _dyn_type;
|
||||
set_parameter_dictionary(i.Parameters);
|
||||
child_order.assign_to(i.Child);
|
||||
value.Dynamic = i;
|
||||
}
|
||||
// if (_child_order == null)
|
||||
// _select_child_order(model.factory.default_order_type(_security.Value, true));
|
||||
// _validate();
|
||||
// if (!HasErrors)
|
||||
// {
|
||||
// var i = factory.dynamic_order();
|
||||
// i.DynamicOrderType = _dyn_type;
|
||||
// set_parameter_dictionary(i.Parameters);
|
||||
// child_order.assign_to(i.Child);
|
||||
// value.Dynamic = i;
|
||||
// }
|
||||
}
|
||||
|
||||
void set_parameter_dictionary(Google.Protobuf.Collections.MapField<string, string> par)
|
||||
@@ -139,7 +139,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_child_order_choices == null)
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -185,7 +185,7 @@ namespace mbts.spark
|
||||
void _select_child_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
@@ -208,4 +208,4 @@ namespace mbts.spark
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
using bts.api.orderman;
|
||||
using bts.spark;
|
||||
using bts.utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Input;
|
||||
using static bts.api.orderman.CustomOrderDefinition;
|
||||
|
||||
namespace mbts.spark {
|
||||
interface IOrderTypeVM : IPropertyWrapperVM<CustomOrderDefinition, CustomOrderDefinitionImmutable> {
|
||||
string id { get; }
|
||||
CustomOneofCase order_type { get; }
|
||||
string type_name { get; }
|
||||
bool is_bts_type { get; }
|
||||
@@ -21,4 +23,12 @@ namespace mbts.spark {
|
||||
ICollection<IOrderTypeVM> child_order_types { get; }
|
||||
IOrderTypeVM child_order { get; }
|
||||
}
|
||||
|
||||
static class OrderTypeVMExtensions {
|
||||
public static IEqualityComparer<IOrderTypeVM> key_comparer =>
|
||||
EqualityComparer.Create<IOrderTypeVM, OrderTemplateKey>(a => a.key());
|
||||
|
||||
public static OrderTemplateKey key(this IOrderTypeVM vm) =>
|
||||
new OrderTemplateKey(vm.order_type, vm.id);
|
||||
}
|
||||
}
|
||||
@@ -14,34 +14,34 @@ using static bts.api.orderman.CustomOrderDefinition;
|
||||
namespace mbts.spark {
|
||||
static partial class OrderTypeVMFactory {
|
||||
class InlineIcebergOrderProperties {
|
||||
public InlineIcebergOrderProperties(CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types) {
|
||||
public InlineIcebergOrderProperties(OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types) {
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
show_quantity = new InlineUserProperty<double>(1, true);
|
||||
}
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
public readonly InlineUserProperty<double> show_quantity;
|
||||
}
|
||||
|
||||
class IcebergOrderVM : OrderTypeVMBase<IcebergOrderDefinition>, IHierarchicalOrderTypeVM, IDisposable {
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineIcebergOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
|
||||
public IcebergOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
public IcebergOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineIcebergOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList()))) { }
|
||||
new InlineIcebergOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name) { }
|
||||
|
||||
public IcebergOrderVM(OrdersModel model,
|
||||
IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineIcebergOrderProperties> inline_properties)
|
||||
: base(model) {
|
||||
IObservable<InlineIcebergOrderProperties> inline_properties, string id, string display_name)
|
||||
: base(model, id, display_name) {
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
security_md_source.OnDispatcher()
|
||||
@@ -52,7 +52,7 @@ namespace mbts.spark {
|
||||
_order_types.SetItems(p.child_order_types.value);
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override)) {
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (p.show_quantity.force_override) {
|
||||
show_quantity = p.show_quantity.value;
|
||||
@@ -68,7 +68,7 @@ namespace mbts.spark {
|
||||
public ICollection<IOrderTypeVM> child_order_types {
|
||||
get {
|
||||
if (_child_order_choices == null) {
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
}
|
||||
return _child_order_choices;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ namespace mbts.spark {
|
||||
|
||||
void _select_child_order() {
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
|
||||
@@ -17,19 +17,19 @@ namespace mbts.spark
|
||||
{
|
||||
class InlineJoinOrderProperties
|
||||
{
|
||||
public InlineJoinOrderProperties (CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types)
|
||||
public InlineJoinOrderProperties (OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
{
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
|
||||
var hedgetype = CustomOneofCase.Lean;
|
||||
if(!child_order_types.Contains(hedgetype))
|
||||
if(!child_order_types.Any(t => t.key.type == hedgetype))
|
||||
hedgetype = CustomOneofCase.Limit;
|
||||
|
||||
//ExceptionAssert.InvalidOperation.That(child_order_types.Contains(hedgetype), $"Hedge order type {hedgetype} is not in hedge_order_types");
|
||||
this.selected_hedge_order_type = new InlineUserProperty<CustomOneofCase>(hedgetype, true);
|
||||
this.hedge_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_hedge_order_type = new InlineUserProperty<OrderTemplateHeader>(new OrderTemplateHeader(hedgetype), true);
|
||||
this.hedge_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
|
||||
tick_offset_on_deploy = new InlineUserProperty<uint>(0, false);
|
||||
join_threshold = new InlineUserProperty<bts.spark.QuantityMeasure>(
|
||||
@@ -37,10 +37,10 @@ namespace mbts.spark
|
||||
enable_hedge = new InlineUserProperty<bool>(false, false);
|
||||
hedge_ticks = new InlineUserProperty<int>(1, false);
|
||||
}
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_hedge_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> hedge_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_hedge_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> hedge_order_types;
|
||||
|
||||
|
||||
public readonly InlineUserProperty<uint> tick_offset_on_deploy;
|
||||
@@ -55,13 +55,13 @@ namespace mbts.spark
|
||||
{
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineJoinOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _hedge_order_choices;
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _hedge_order_choices;
|
||||
IOrderTypeVM _hedge_order;
|
||||
IDisposable _hedge_order_errors_sub;
|
||||
|
||||
@@ -79,12 +79,12 @@ namespace mbts.spark
|
||||
}
|
||||
public int hedge_ticks { get; set; } = 1;
|
||||
|
||||
public JoinOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
public JoinOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineJoinOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList()))) { }
|
||||
new InlineJoinOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name) { }
|
||||
|
||||
public JoinOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineJoinOrderProperties> inline_properties) : base(model)
|
||||
IObservable<InlineJoinOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
{
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
@@ -98,11 +98,11 @@ namespace mbts.spark
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override))
|
||||
{
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (_hedge_order_choices != null && (_hedge_order == null || p.selected_hedge_order_type.force_override))
|
||||
{
|
||||
_select_hedge_order(p.selected_hedge_order_type.value);
|
||||
_select_hedge_order(p.selected_hedge_order_type.value.key.type);
|
||||
}
|
||||
if (p.tick_offset_on_deploy.force_override)
|
||||
{
|
||||
@@ -157,7 +157,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_child_order_choices == null)
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_hedge_order_choices == null)
|
||||
_hedge_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_hedge_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _hedge_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -241,7 +241,7 @@ namespace mbts.spark
|
||||
void _select_child_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ namespace mbts.spark
|
||||
void _select_hedge_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_hedge_order_type.has_value ?
|
||||
_inline_props.selected_hedge_order_type.value :
|
||||
_inline_props.selected_hedge_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_hedge_order(ot);
|
||||
}
|
||||
|
||||
@@ -17,17 +17,17 @@ namespace mbts.spark
|
||||
{
|
||||
class InlineLeanOrderProperties
|
||||
{
|
||||
public InlineLeanOrderProperties (CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types)
|
||||
public InlineLeanOrderProperties (OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
{
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
cross_threshold = new InlineUserProperty<bts.spark.QuantityMeasure>(
|
||||
new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1}, false);
|
||||
max_chase_ticks = new InlineUserProperty<uint>(10, false);
|
||||
}
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
|
||||
public readonly InlineUserProperty<bts.spark.QuantityMeasure> cross_threshold;
|
||||
public readonly InlineUserProperty<uint> max_chase_ticks;
|
||||
@@ -37,8 +37,8 @@ namespace mbts.spark
|
||||
{
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineLeanOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
@@ -46,12 +46,12 @@ namespace mbts.spark
|
||||
public bts.spark.QuantityMeasure cross_threshold { get; set; } = new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1 };
|
||||
public uint max_chase_ticks { get; set; } = 10;
|
||||
|
||||
public LeanOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
public LeanOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineLeanOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList()))) { }
|
||||
new InlineLeanOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name) { }
|
||||
|
||||
public LeanOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineLeanOrderProperties> inline_properties) : base(model)
|
||||
IObservable<InlineLeanOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
{
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
@@ -65,7 +65,7 @@ namespace mbts.spark
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override))
|
||||
{
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (p.cross_threshold.force_override)
|
||||
{
|
||||
@@ -104,7 +104,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_child_order_choices == null)
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -150,7 +150,7 @@ namespace mbts.spark
|
||||
void _select_child_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace mbts.spark {
|
||||
static partial class OrderTypeVMFactory {
|
||||
private class LimitOrderVM : OrderTypeVMBase<LimitOrderDefinition> {
|
||||
internal LimitOrderVM(OrdersModel model) : base(model) { }
|
||||
internal LimitOrderVM(OrdersModel model) : base(model, "Limit", OrderUtils.order_type_display_name(CustomOrderDefinition.CustomOneofCase.Limit)) { }
|
||||
|
||||
public override void assign_to(CustomOrderDefinition value) =>
|
||||
value.Limit = factory.limit_order();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace mbts.spark {
|
||||
static partial class OrderTypeVMFactory {
|
||||
private class MarketOrderVM : OrderTypeVMBase<MarketOrderDefinition> {
|
||||
internal MarketOrderVM(OrdersModel model) : base(model) { }
|
||||
internal MarketOrderVM(OrdersModel model) : base(model, "Market", OrderUtils.order_type_display_name(CustomOrderDefinition.CustomOneofCase.Market)) { }
|
||||
|
||||
public override void assign_to(CustomOrderDefinition parent) =>
|
||||
parent.Market = factory.market_order();
|
||||
|
||||
@@ -12,36 +12,36 @@ namespace mbts.spark {
|
||||
static partial class OrderTypeVMFactory {
|
||||
public static IOrderTypeVM market(OrdersModel model) => new MarketOrderVM(model);
|
||||
public static IOrderTypeVM limit(OrdersModel model) => new LimitOrderVM(model);
|
||||
public static IOrderTypeVM stop(OrdersModel model) => new StopOrderVM(model);
|
||||
public static IOrderTypeVM stop_limit(OrdersModel model, IObservable<SecurityMD> security_md_source) => new StopLimitOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM time_box(OrdersModel model, IObservable<SecurityMD> security_md_source) => new TimeBoxOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM tick(OrdersModel model, IObservable<SecurityMD> security_md_source) => new TickOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM lean(OrdersModel model, IObservable<SecurityMD> security_md_source) => new LeanOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM join(OrdersModel model, IObservable<SecurityMD> security_md_source) => new JoinOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM top(OrdersModel model, IObservable<SecurityMD> security_md_source) => new TopOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM cover(OrdersModel model, IObservable<SecurityMD> security_md_source) => new CoverOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM trigger(OrdersModel model, IObservable<SecurityMD> security_md_source) => new TriggerOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM iceberg(OrdersModel model, IObservable<SecurityMD> security_md_source) => new IcebergOrderVM(model, security_md_source);
|
||||
public static IOrderTypeVM spreader(OrdersModel model, IObservable<SecurityImmutable> security_source) => new SpreaderOrderVM(model, security_source);
|
||||
public static IOrderTypeVM dynamic(OrdersModel model, IObservable<SecurityMD> security_md_source, string type) => new DynamicOrderVM(model, security_md_source, type);
|
||||
public static IOrderTypeVM stop(OrdersModel model, string id, string display_name) => new StopOrderVM(model, id, display_name);
|
||||
public static IOrderTypeVM stop_limit(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new StopLimitOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM time_box(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new TimeBoxOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM tick(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new TickOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM lean(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new LeanOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM join(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new JoinOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM top(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new TopOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM cover(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new CoverOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM trigger(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new TriggerOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM iceberg(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new IcebergOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM spreader(OrdersModel model, IObservable<SecurityImmutable> security_source, string id, string display_name) => new SpreaderOrderVM(model, security_source, id, display_name);
|
||||
public static IOrderTypeVM dynamic(OrdersModel model, IObservable<SecurityMD> security_md_source, string dynamic_type, string id, string display_name) => new DynamicOrderVM(model, security_md_source, dynamic_type, id, display_name);
|
||||
|
||||
public static IOrderTypeVM create(CustomOneofCase order_type, OrdersModel model,
|
||||
public static IOrderTypeVM create(CustomOneofCase order_type, string id, string display_name, OrdersModel model,
|
||||
IObservable<SecurityMD> security_md_source, string dynamic_type = null ) {
|
||||
switch (order_type) {
|
||||
case CustomOneofCase.Market: return market(model);
|
||||
case CustomOneofCase.Limit: return limit(model);
|
||||
case CustomOneofCase.Stop: return stop(model);
|
||||
case CustomOneofCase.StopLimit: return stop_limit(model, security_md_source);
|
||||
case CustomOneofCase.TimeBox: return time_box(model, security_md_source);
|
||||
case CustomOneofCase.Tick: return tick(model, security_md_source);
|
||||
case CustomOneofCase.Lean: return lean(model, security_md_source);
|
||||
case CustomOneofCase.Join: return join(model, security_md_source);
|
||||
case CustomOneofCase.Top: return top(model, security_md_source);
|
||||
case CustomOneofCase.Cover: return cover(model, security_md_source);
|
||||
case CustomOneofCase.Trigger: return trigger(model, security_md_source);
|
||||
case CustomOneofCase.Iceberg: return iceberg(model, security_md_source);
|
||||
case CustomOneofCase.Spreader: return spreader(model, security_md_source.Select(smd => smd.security));
|
||||
case CustomOneofCase.Dynamic: return dynamic(model, security_md_source, dynamic_type);
|
||||
case CustomOneofCase.Stop: return stop(model, id, display_name);
|
||||
case CustomOneofCase.StopLimit: return stop_limit(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.TimeBox: return time_box(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Tick: return tick(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Lean: return lean(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Join: return join(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Top: return top(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Cover: return cover(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Trigger: return trigger(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Iceberg: return iceberg(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Spreader: return spreader(model, security_md_source.Select(smd => smd.security), id, display_name);
|
||||
case CustomOneofCase.Dynamic: return dynamic(model, security_md_source, dynamic_type, id, display_name);
|
||||
default: throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -51,12 +51,17 @@ namespace mbts.spark {
|
||||
protected readonly OrdersModel model;
|
||||
protected OrderFactory factory => model.factory;
|
||||
|
||||
protected OrderTypeVMBase(OrdersModel model) => this.model = model;
|
||||
protected OrderTypeVMBase(OrdersModel model, string id, string display_name) {
|
||||
this.model = model;
|
||||
this.id = id;
|
||||
this.display_name = display_name;
|
||||
}
|
||||
|
||||
public abstract CustomOneofCase order_type { get; }
|
||||
public abstract string type_name { get; }
|
||||
public bool is_bts_type => display_name.StartsWith("BTS");
|
||||
public string display_name => OrderUtils.order_type_display_name(order_type);
|
||||
public string id { get; }
|
||||
public string display_name { get; }
|
||||
public OrderMetadata meta => factory.get_metadata(order_type);
|
||||
public virtual bool has_editable_properties => !meta.NoProps;
|
||||
public virtual bool editable_properties_open { get; set; }
|
||||
@@ -76,7 +81,7 @@ namespace mbts.spark {
|
||||
}
|
||||
|
||||
private abstract class OrderTypeVMBase<T> : OrderTypeVMBase where T : Google.Protobuf.IMessage, new() {
|
||||
protected OrderTypeVMBase(OrdersModel model) : base(model) { }
|
||||
protected OrderTypeVMBase(OrdersModel model, string id, string display_name) : base(model, id, display_name) { }
|
||||
|
||||
public override CustomOneofCase order_type =>
|
||||
OrderDataHelper.get_order_type(new T());
|
||||
|
||||
@@ -13,20 +13,20 @@ namespace mbts.spark {
|
||||
readonly StrategyEditorWrapper _strategy_editor_wrapper;
|
||||
IDisposable _dispose;
|
||||
|
||||
public SpreaderOrderVM(OrdersModel model, IObservable<SecurityImmutable> security_source)
|
||||
public SpreaderOrderVM(OrdersModel model, IObservable<SecurityImmutable> security_source, string id, string display_name)
|
||||
: this(model, security_source, security_source.SelectMany(s => model.spreader.security_strategy(s.Id)
|
||||
.Select(strategy => {
|
||||
var so = model.factory.spreader_order();
|
||||
so.Security = s.CloneToMutable();
|
||||
so.ExecutionStrategy = strategy.CloneToMutable();
|
||||
return new InlineUserProperty<SpreaderOrderDefinitionImmutable>(so, true);
|
||||
}))) { }
|
||||
})), id, display_name) { }
|
||||
|
||||
public SpreaderOrderVM(
|
||||
OrdersModel model,
|
||||
IObservable<SecurityImmutable> security_source,
|
||||
IObservable<InlineUserProperty<SpreaderOrderDefinitionImmutable>> order_template_source)
|
||||
: base(model) {
|
||||
IObservable<InlineUserProperty<SpreaderOrderDefinitionImmutable>> order_template_source, string id, string display_name)
|
||||
: base(model, id, display_name) {
|
||||
_template = backing(nameof(template), new SpreaderOrderDefinitionImmutable?());
|
||||
_strategy_editor_wrapper = new StrategyEditorWrapper(this);
|
||||
_dispose = Disposable.Create(
|
||||
|
||||
@@ -29,10 +29,11 @@ namespace mbts.spark {
|
||||
InlineStopLimitOrderProperties _inline_props;
|
||||
IDisposable _dispose;
|
||||
|
||||
internal StopLimitOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
: this(model, security_md_source.Select(smd => smd.security.spec_or_default()), InlineStopLimitOrderProperties.subscribe(security_md_source)) { }
|
||||
internal StopLimitOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source.Select(smd => smd.security.spec_or_default()), InlineStopLimitOrderProperties.subscribe(security_md_source), id, display_name) { }
|
||||
|
||||
internal StopLimitOrderVM(OrdersModel model, IObservable<ContractSpecificationImmutable> spec_source, IObservable<InlineStopLimitOrderProperties> inline_properties) : base(model) {
|
||||
internal StopLimitOrderVM(OrdersModel model, IObservable<ContractSpecificationImmutable> spec_source, IObservable<InlineStopLimitOrderProperties> inline_properties, string id, string display_name)
|
||||
: base(model, id, display_name) {
|
||||
_stop_price = new UserProperty<double>(backing(nameof(stop_price), double.NaN));
|
||||
_dispose = Disposable.Create(
|
||||
spec_source.OnDispatcher().Subscribe(s => {
|
||||
|
||||
@@ -6,8 +6,7 @@ namespace mbts.spark {
|
||||
private class StopOrderVM : OrderTypeVMBase<StopOrderDefinition> {
|
||||
double _stop_price = 0;
|
||||
|
||||
internal StopOrderVM(OrdersModel model) : base(model) { }
|
||||
|
||||
internal StopOrderVM(OrdersModel model, string id, string display_name) : base(model, id, display_name) { }
|
||||
|
||||
public double stop_price {
|
||||
get => _stop_price;
|
||||
|
||||
@@ -17,11 +17,11 @@ namespace mbts.spark
|
||||
{
|
||||
class InlineTickOrderProperties
|
||||
{
|
||||
public InlineTickOrderProperties (CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types)
|
||||
public InlineTickOrderProperties (OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
{
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
tick_offset_on_deploy = new InlineUserProperty<uint>(0, false);
|
||||
cross_threshold = new InlineUserProperty<bts.spark.QuantityMeasure>(
|
||||
new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1}, false);
|
||||
@@ -29,8 +29,8 @@ namespace mbts.spark
|
||||
max_chase_ticks = new InlineUserProperty<uint>(10, false);
|
||||
detach_on_toward = new InlineUserProperty<bool>(true, false);
|
||||
}
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
|
||||
public readonly InlineUserProperty<uint> tick_offset_on_deploy;
|
||||
public readonly InlineUserProperty<bts.spark.QuantityMeasure> cross_threshold;
|
||||
@@ -43,8 +43,8 @@ namespace mbts.spark
|
||||
{
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineTickOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
@@ -55,12 +55,12 @@ namespace mbts.spark
|
||||
public uint max_chase_ticks { get; set; } = 10;
|
||||
public bool detach_on_toward { get; set; } = true;
|
||||
|
||||
public TickOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
public TickOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineTickOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList()))) { }
|
||||
new InlineTickOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name) { }
|
||||
|
||||
public TickOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineTickOrderProperties> inline_properties) : base(model)
|
||||
IObservable<InlineTickOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
{
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
@@ -74,7 +74,7 @@ namespace mbts.spark
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override))
|
||||
{
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (p.tick_offset_on_deploy.force_override)
|
||||
{
|
||||
@@ -131,7 +131,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_child_order_choices == null)
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@ namespace mbts.spark
|
||||
void _select_child_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@ using static bts.api.orderman.CustomOrderDefinition;
|
||||
namespace mbts.spark {
|
||||
static partial class OrderTypeVMFactory {
|
||||
class InlineTimeBoxOrderProperties {
|
||||
public InlineTimeBoxOrderProperties(CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types) {
|
||||
public InlineTimeBoxOrderProperties(OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types) {
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
start = new InlineUserProperty<DateTime>(DateTime.Now, true);
|
||||
stop = new InlineUserProperty<DateTime>(DateTime.Now.AddMinutes(5), true);
|
||||
}
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
public readonly InlineUserProperty<DateTime> start, stop;
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace mbts.spark {
|
||||
const double _start_immediately_delay_ms = 500;
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineTimeBoxOrderProperties _inline_props;
|
||||
TimeTextTuple _absolute_start = TimeTextTuple.FromDateTime(DateTime.Now.AddMinutes(5)), _absolute_stop = TimeTextTuple.FromDateTime(DateTime.Now.AddMinutes(10));
|
||||
TimeSpan? _relative_start = TimeSpan.FromMinutes(5), _relative_stop = TimeSpan.FromMinutes(5);
|
||||
@@ -40,14 +40,14 @@ namespace mbts.spark {
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
|
||||
public TimeBoxOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
public TimeBoxOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineTimeBoxOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList()))) { }
|
||||
new InlineTimeBoxOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name) { }
|
||||
|
||||
public TimeBoxOrderVM(OrdersModel model,
|
||||
IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineTimeBoxOrderProperties> inline_properties)
|
||||
: base(model) {
|
||||
IObservable<InlineTimeBoxOrderProperties> inline_properties, string id, string display_name)
|
||||
: base(model, id, display_name) {
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
security_md_source.OnDispatcher()
|
||||
@@ -58,7 +58,7 @@ namespace mbts.spark {
|
||||
_order_types.SetItems(p.child_order_types.value);
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override)) {
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (p.start.force_override) {
|
||||
absolute_start = TimeTextTuple.FromDateTime(p.start.value);
|
||||
@@ -94,7 +94,7 @@ namespace mbts.spark {
|
||||
public ICollection<IOrderTypeVM> child_order_types {
|
||||
get {
|
||||
if (_child_order_choices == null) {
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
}
|
||||
return _child_order_choices;
|
||||
}
|
||||
@@ -173,7 +173,7 @@ namespace mbts.spark {
|
||||
|
||||
void _select_child_order() {
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
|
||||
@@ -17,17 +17,17 @@ namespace mbts.spark
|
||||
{
|
||||
class InlineTopOrderProperties
|
||||
{
|
||||
public InlineTopOrderProperties(CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types)
|
||||
public InlineTopOrderProperties(OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
{
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
|
||||
var hedgetype = CustomOneofCase.Lean;
|
||||
if(!child_order_types.Contains(hedgetype))
|
||||
if(!child_order_types.Any(ct => ct.key.type == hedgetype))
|
||||
hedgetype = CustomOneofCase.Limit;
|
||||
this.selected_hedge_order_type = new InlineUserProperty<CustomOneofCase>(hedgetype, true);
|
||||
this.hedge_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_hedge_order_type = new InlineUserProperty<OrderTemplateHeader>(new OrderTemplateHeader(hedgetype), true);
|
||||
this.hedge_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
|
||||
watch_level_tick_offset = new InlineUserProperty<uint>(0, false);
|
||||
top_threshold = new InlineUserProperty<bts.spark.QuantityMeasure>(
|
||||
@@ -35,10 +35,10 @@ namespace mbts.spark
|
||||
enable_hedge = new InlineUserProperty<bool>(false, false);
|
||||
hedge_ticks = new InlineUserProperty<int>(1, false);
|
||||
}
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_hedge_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> hedge_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_hedge_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> hedge_order_types;
|
||||
|
||||
|
||||
public readonly InlineUserProperty<uint> watch_level_tick_offset;
|
||||
@@ -53,13 +53,13 @@ namespace mbts.spark
|
||||
{
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineTopOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _hedge_order_choices;
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _hedge_order_choices;
|
||||
IOrderTypeVM _hedge_order;
|
||||
IDisposable _hedge_order_errors_sub;
|
||||
|
||||
@@ -77,13 +77,13 @@ namespace mbts.spark
|
||||
}
|
||||
public int hedge_ticks { get; set; } = 1;
|
||||
|
||||
public TopOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
public TopOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineTopOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList())))
|
||||
new InlineTopOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name)
|
||||
{ }
|
||||
|
||||
public TopOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineTopOrderProperties> inline_properties) : base(model)
|
||||
IObservable<InlineTopOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
{
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
@@ -98,11 +98,11 @@ namespace mbts.spark
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override))
|
||||
{
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (_hedge_order_choices != null && (_hedge_order == null || p.selected_hedge_order_type.force_override))
|
||||
{
|
||||
_select_hedge_order(p.selected_hedge_order_type.value);
|
||||
_select_hedge_order(p.selected_hedge_order_type.value.key.type);
|
||||
}
|
||||
if (p.watch_level_tick_offset.force_override)
|
||||
{
|
||||
@@ -157,7 +157,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_child_order_choices == null)
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ namespace mbts.spark
|
||||
get
|
||||
{
|
||||
if (_hedge_order_choices == null)
|
||||
_hedge_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_hedge_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _hedge_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -241,7 +241,7 @@ namespace mbts.spark
|
||||
void _select_child_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ namespace mbts.spark
|
||||
void _select_hedge_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_hedge_order_type.has_value ?
|
||||
_inline_props.selected_hedge_order_type.value :
|
||||
_inline_props.selected_hedge_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_hedge_order(ot);
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ using static bts.api.orderman.CustomOrderDefinition;
|
||||
namespace mbts.spark {
|
||||
static partial class OrderTypeVMFactory {
|
||||
class InlineTriggerOrderProperties {
|
||||
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
public readonly InlineUserProperty<TriggerPriceType> trigger_price_type;
|
||||
public readonly InlineUserProperty<TriggerPayupPrice.Types.TriggerPayupPriceType> payup_price_type;
|
||||
public readonly InlineUserProperty<double> fixed_price;
|
||||
@@ -23,10 +23,10 @@ namespace mbts.spark {
|
||||
public readonly InlineUserProperty<bool> use_fixed_price, is_priceout_checked, is_timeout_checked;
|
||||
public readonly InlineUserProperty<int> timeout_secs;
|
||||
|
||||
public InlineTriggerOrderProperties(CustomOneofCase selected_child_order_type, IReadOnlyCollection<CustomOneofCase> child_order_types) {
|
||||
public InlineTriggerOrderProperties(OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types) {
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<CustomOneofCase>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<CustomOneofCase>>(child_order_types, true);
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
trigger_price_type = new InlineUserProperty<TriggerPriceType>(TriggerPriceType.Bid, false);
|
||||
payup_price_type = new InlineUserProperty<TriggerPayupPrice.Types.TriggerPayupPriceType>();
|
||||
use_fixed_price = new InlineUserProperty<bool>(false);
|
||||
@@ -47,19 +47,20 @@ namespace mbts.spark {
|
||||
readonly UserProperty<bool> _use_fixed_price, _is_timeout_checked, _is_priceout_checked;
|
||||
SecurityMD? _security_md;
|
||||
SecurityImmutable? _security => _security_md.security();
|
||||
ObservableCollection<CustomOneofCase> _order_types = new ObservableCollection<CustomOneofCase>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase> _child_order_choices;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineTriggerOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
ulong _bbo_ref = 0, _last_trade_ref = 0;
|
||||
double _best_bid = double.NaN, _best_ask = double.NaN, _last_trade_price = double.NaN;
|
||||
|
||||
public TriggerOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
|
||||
public TriggerOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineTriggerOrderProperties(model.factory.default_order_type(smd.security), model.factory.default_order_types(smd.security).ToList()))) { }
|
||||
new InlineTriggerOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name) { }
|
||||
|
||||
public TriggerOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, IObservable<InlineTriggerOrderProperties> inline_properties) : base(model) {
|
||||
public TriggerOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, IObservable<InlineTriggerOrderProperties> inline_properties, string id, string display_name)
|
||||
: base(model, id, display_name) {
|
||||
_trigger_price_type = create_user_prop(nameof(trigger_price_type), TriggerPriceType.Bid);
|
||||
_use_fixed_price = create_user_prop(nameof(use_fixed_price), true);
|
||||
_fixed_price = create_user_prop(nameof(fixed_price), double.NaN);
|
||||
@@ -88,7 +89,7 @@ namespace mbts.spark {
|
||||
_order_types.SetItems(p.child_order_types.value);
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override)) {
|
||||
_select_child_order(p.selected_child_order_type.value);
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
// trigger price
|
||||
_trigger_price_type.on_inline_prop(p.trigger_price_type);
|
||||
@@ -135,7 +136,7 @@ namespace mbts.spark {
|
||||
public ICollection<IOrderTypeVM> child_order_types {
|
||||
get {
|
||||
if (_child_order_choices == null)
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, CustomOneofCase>(_order_types, ot => create(ot, model, _security_md_source));
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
@@ -210,13 +211,13 @@ namespace mbts.spark {
|
||||
_security_md.Value.md.get_bbo(ref _bbo_ref, out co2.NativePriceSize bid, out co2.NativePriceSize ask);
|
||||
_best_bid = bid.price;
|
||||
_best_ask = ask.price;
|
||||
_security_md.Value.md.get_last_trade(ref _last_trade_ref, out co2.NativePriceSize ps, out DateTime ts, out ulong v);
|
||||
_security_md.Value.md.get_last_trade(ref _last_trade_ref, out co2.NativePriceSize ps, out ulong v);
|
||||
}
|
||||
}
|
||||
|
||||
void _select_child_order() {
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value :
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
|
||||
@@ -205,14 +205,27 @@ namespace mbts.spark {
|
||||
.StartWith(false);
|
||||
|
||||
public static IObservable<double> security_total_position(this OrdersModel orders_model, uint security_key, string account) =>
|
||||
// PositionUnit.Account is actually the clearing account; this code assumes that clearing account and account are equivalent.
|
||||
// However, it still must match account to PositionUnit.Account.Trimmed() because the exchange likes to slap spaces on the end.
|
||||
orders_model.on_security_positions(security_key)
|
||||
.filter(p => p.Account == account)
|
||||
// the state should always have 1 element, since the PositionUnit-identity is security + account
|
||||
.Scan(0.0, (pos, table) => pos + (table.added.Sum(p => p.total_pos()) - table.removed.Sum(p => p.total_pos())))
|
||||
.Select(t => {
|
||||
foreach (var kv in t.state) {
|
||||
if (kv.Value.Account == account)
|
||||
return kv.Value.total_pos();
|
||||
}
|
||||
return double.NaN;
|
||||
}).DistinctUntilChanged()
|
||||
.StartWith(double.NaN);
|
||||
|
||||
// DO NOT REMOVE (BEGIN)
|
||||
//public static IObservable<double> security_total_position(this OrdersModel orders_model, uint security_key, string account) =>
|
||||
// // PositionUnit.Account is actually the clearing account; this code assumes that clearing account and account are equivalent.
|
||||
// // However, it still must match account to PositionUnit.Account.Trimmed() because the exchange likes to slap spaces on the end.
|
||||
// orders_model.on_security_positions(security_key)
|
||||
// .filter(p => p.Account == account)
|
||||
// // the state should always have 1 element, since the PositionUnit-identity is security + account
|
||||
// .Scan(0.0, (pos, table) => pos + (table.added.Sum(p => p.total_pos()) - table.removed.Sum(p => p.total_pos())))
|
||||
// .StartWith(double.NaN);
|
||||
// DO NOT REMOVE (END)
|
||||
|
||||
public static IObservable<ITableUpdateTransform<OrderRecordImmutable, uint>> on_security_root_orders(this OrdersModel orders_model, uint security_key) =>
|
||||
orders_model.on_security_orders(security_key).Scan(new RootOrderData(), (rod, table) => {
|
||||
// ** using HashSet/List pairs, rather than a Dictionary, because TableUpdateTransform calls for IReadOnlyLists, while Dictionary.Values only implements IReadOnlyCollection.
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
using bts;
|
||||
using bts.utils;
|
||||
using mbts.collections;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace mbts.spark {
|
||||
interface IPrepareUpdateForDispatcher {
|
||||
IDisposable prepare_update();
|
||||
}
|
||||
|
||||
class DispatcherUpdateMaster : IDisposable {
|
||||
readonly string _name;
|
||||
readonly DispatcherPriority _invocation_priority;
|
||||
SetMap<Dispatcher, IPrepareUpdateForDispatcher> _vms;
|
||||
int _state = States.ReadyForUpdate;
|
||||
IDisposable _dispose;
|
||||
|
||||
public DispatcherUpdateMaster(string name)
|
||||
: this(name, WorkLoop.default_interval, WorkLoop.default_priority) { }
|
||||
|
||||
public DispatcherUpdateMaster(string name, TimeSpan period, DispatcherPriority invocation_priority) {
|
||||
_name = name;
|
||||
_vms = new SetMap<Dispatcher, IPrepareUpdateForDispatcher>(EqualityComparer.Create<Dispatcher, int>(d => d.Thread.ManagedThreadId));
|
||||
_dispose = ThreadPoolScheduler.Instance.SchedulePeriodic(period, _update_async);
|
||||
_invocation_priority = invocation_priority;
|
||||
}
|
||||
|
||||
public IDisposable attach(IPrepareUpdateForDispatcher vm, Dispatcher dispatcher) {
|
||||
var clone = _vms.clone();
|
||||
clone.add(dispatcher, vm);
|
||||
_vms = clone;
|
||||
return Disposable.Create(() => _detach(vm, dispatcher));
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
Thread.VolatileWrite(ref _state, States.Disposed);
|
||||
Disposable.dispose(ref _dispose);
|
||||
}
|
||||
|
||||
void _detach(IPrepareUpdateForDispatcher preper, Dispatcher dispatcher) {
|
||||
var clone = _vms.clone();
|
||||
clone.remove(dispatcher, preper);
|
||||
_vms = clone;
|
||||
}
|
||||
|
||||
async void _update_async() {
|
||||
if (Interlocked.CompareExchange(ref _state, States.UpdateInProgress, States.ReadyForUpdate) != States.ReadyForUpdate) {
|
||||
return;
|
||||
}
|
||||
var temp = _vms;
|
||||
try {
|
||||
ConcurrentBag<(Dispatcher dispatcher, ConcurrentBag<IDisposable> update)> update_jobs =
|
||||
new ConcurrentBag<(Dispatcher dispatcher, ConcurrentBag<IDisposable> update_jobs)>();
|
||||
await Task.Run(() => {
|
||||
Parallel.ForEach(temp, dispatcher_group => {
|
||||
ConcurrentBag<IDisposable> update = new ConcurrentBag<IDisposable>();
|
||||
Parallel.ForEach(dispatcher_group, vm => {
|
||||
// need to check for null, that indicates an empty update (rather than an actual empty enumerable)
|
||||
var ujs = vm.prepare_update();
|
||||
if (ujs != null)
|
||||
update.Add(ujs);
|
||||
});
|
||||
if (update.Count > 0)
|
||||
update_jobs.Add((dispatcher_group.Key, update));
|
||||
});
|
||||
});
|
||||
await Task.WhenAll(update_jobs.Select(_update_dispatcher_group_async));
|
||||
} catch (Exception ex) {
|
||||
Log.Ui.error($"{_name} error during parallel update: {ex}");
|
||||
} finally {
|
||||
// signal that the update is complete, and we are ready for another
|
||||
Interlocked.CompareExchange(ref _state, States.ReadyForUpdate, States.UpdateInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
async Task _update_dispatcher_group_async((Dispatcher dispatcher, ConcurrentBag<IDisposable> update_jobs) t) =>
|
||||
await t.dispatcher.InvokeAsync(() => t.update_jobs.DisposeAll(), _invocation_priority);
|
||||
|
||||
static class States {
|
||||
public const int
|
||||
ReadyForUpdate = 0,
|
||||
UpdateInProgress = 1,
|
||||
Disposed = 2;
|
||||
}
|
||||
}
|
||||
|
||||
static class DispatcherUpdateMasterExtensions {
|
||||
public static IDisposable attach(this DispatcherUpdateMaster dum, IPrepareUpdateForDispatcher preparer) =>
|
||||
dum.attach(preparer, Dispatcher.CurrentDispatcher);
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using bts;
|
||||
using bts.api;
|
||||
|
||||
namespace mbts.ui.utility
|
||||
{
|
||||
class ExpirationFormatter
|
||||
{
|
||||
private static class DateFormatter
|
||||
{
|
||||
private static string[] month_codes = new string[] { "F", "G", "H", "J", "K", "M", "N", "Q", "U", "V", "X", "Z" };
|
||||
private static string[] month_three_letters = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
public static string format_condensed(DateTime date, bool use_month_code, bool show_year)
|
||||
{
|
||||
return String.Format("{0}{1}{2}", date.Day, month_codes[date.Month - 1], show_year ? (date.Year - 2000).ToString() : String.Empty);
|
||||
}
|
||||
|
||||
public static string format(DateTime date, bool use_month_code, bool show_day) {
|
||||
string month_text = use_month_code ? "{0}{1:00}".fmt(month_codes[date.Month - 1], date.Year - 2000) : "{0} {1:00}".fmt(month_three_letters[date.Month - 1], date.Year - 2000);
|
||||
return show_day ? "{0} {1}".fmt(date.Day, month_text) : month_text;
|
||||
}
|
||||
|
||||
public static string format_standard(DateTime date) { return "{0} {1} {2:00}".fmt(date.Day, month_three_letters[date.Month - 1], date.Year - 2000); }
|
||||
public static string format_coded(DateTime date) { return "{0} {1}{2:00}".fmt(date.Day, month_codes[date.Month - 1], date.Year - 2000); }
|
||||
public static string format_coded_hide_day(DateTime date) { return "{0}{1}".fmt(month_codes[date.Month - 1], date.Year - 2000); }
|
||||
|
||||
public static DateTime parse_standard(string date_text) {
|
||||
string[] split = date_text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int year = 0;
|
||||
int month = Array.IndexOf(month_three_letters, split[1]) + 1;
|
||||
int day = 0;
|
||||
int.TryParse(split[2], out year);
|
||||
int.TryParse(split[0], out day);
|
||||
return new DateTime(year + 2000, month, day);
|
||||
}
|
||||
|
||||
public static DateTime parse_coded(string date_text) {
|
||||
string[] split = date_text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string year_text = split[1].Substring(1);
|
||||
string month_text = split[1].Substring(0, 1);
|
||||
string day_text = split[0];
|
||||
int month = Array.IndexOf(month_codes, month_text) + 1;
|
||||
int day, year;
|
||||
int.TryParse(year_text, out year);
|
||||
int.TryParse(day_text, out day);
|
||||
return new DateTime(year + 2000, month, day);
|
||||
}
|
||||
|
||||
public static DateTime parse_coded_hide_day(string date_text) {
|
||||
string year_text = date_text.Substring(1);
|
||||
string month_text = date_text.Substring(0, 1);
|
||||
int month = Array.IndexOf(month_codes, month_text) + 1;
|
||||
int year;
|
||||
int.TryParse(year_text, out year);
|
||||
return new DateTime(year + 2000, month, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private static IDictionary<SecurityType, IDictionary<string, bts.config.ExpirationDisplayOffsetEntry>> _offset_map;
|
||||
|
||||
static ExpirationFormatter()
|
||||
{
|
||||
try
|
||||
{
|
||||
_offset_map = new Dictionary<SecurityType, IDictionary<string, bts.config.ExpirationDisplayOffsetEntry>>();
|
||||
_offset_map[SecurityType.Option] = new Dictionary<string, bts.config.ExpirationDisplayOffsetEntry>();
|
||||
_offset_map[SecurityType.Future] = new Dictionary<string, bts.config.ExpirationDisplayOffsetEntry>();
|
||||
|
||||
bts.config.ExpirationDisplayOffset offset_list = mbts.config.Configuration.get<bts.config.ExpirationDisplayOffset>();
|
||||
foreach (bts.config.ExpirationDisplayOffsetEntry e in offset_list.entries)
|
||||
{
|
||||
string security_name = e.security_name;
|
||||
string security_type_text = e.security_type;
|
||||
SecurityType security_type = SecurityType.Unset;
|
||||
Enum.TryParse<SecurityType>(security_type_text, true, out security_type);
|
||||
if (security_type == SecurityType.Option || security_type == SecurityType.Future)
|
||||
_offset_map[security_type][security_name] = e;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Ui.error(String.Format("Exception message = {0}", ex.Message));
|
||||
}
|
||||
}
|
||||
|
||||
private static bts.config.ExpirationDisplayOffsetEntry _get_offset_entry(SecurityType security_type, string security_name)
|
||||
{
|
||||
bts.config.ExpirationDisplayOffsetEntry rv = null;
|
||||
IDictionary<string, bts.config.ExpirationDisplayOffsetEntry> this_security_type_map = null;
|
||||
if (_offset_map.TryGetValue(security_type, out this_security_type_map))
|
||||
if (this_security_type_map.TryGetValue(security_name, out rv))
|
||||
return rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static DateTime convert_real_to_mapped(SecurityType security_type, string security_name, DateTime security_expiration)
|
||||
{
|
||||
bts.config.ExpirationDisplayOffsetEntry offset_entry = _get_offset_entry(security_type, security_name);
|
||||
DateTime rv = security_expiration;
|
||||
if (offset_entry != null)
|
||||
{
|
||||
if (offset_entry.addition_type == bts.config.ExpirationOffsetType.type.Month)
|
||||
rv = security_expiration.AddMonths(offset_entry.addition_count);
|
||||
else if (offset_entry.addition_type == bts.config.ExpirationOffsetType.type.MonthMoveToStart)
|
||||
{
|
||||
rv = security_expiration.AddMonths(offset_entry.addition_count);
|
||||
rv = new DateTime(rv.Year, rv.Month, 1);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public static string format_expiration_standard(SecurityType security_type, string security_name, DateTime security_expiration, bool map_expiration) {
|
||||
return format_expiration_standard(security_type, security_name, security_expiration, map_expiration, false);
|
||||
}
|
||||
|
||||
public static string format_expiration_standard(SecurityType security_type, string security_name, DateTime security_expiration, bool map_expiration, bool use_month_code) {
|
||||
return format_expiration_standard(security_type, security_name, security_expiration, map_expiration, use_month_code, true);
|
||||
}
|
||||
|
||||
public static string format_expiration_standard(SecurityType security_type, string security_name, DateTime security_expiration, bool map_expiration, bool use_month_code, bool show_day) {
|
||||
DateTime mapped_expiration = map_expiration ? convert_real_to_mapped(security_type, security_name, security_expiration) : security_expiration;
|
||||
return DateFormatter.format(mapped_expiration, use_month_code, show_day);
|
||||
}
|
||||
|
||||
public static string format_symbol_expiration_standard (SecurityType security_type, string security_name, DateTime security_expiration, bool map_expiration) {
|
||||
return format_symbol_expiration_standard(security_type, security_name, security_expiration, map_expiration, false, false, true);
|
||||
}
|
||||
|
||||
public static string format_symbol_expiration_standard (SecurityType security_type, string security_name, DateTime security_expiration, bool map_expiration, bool show_security_type) {
|
||||
return format_symbol_expiration_standard(security_type, security_name, security_expiration, map_expiration, show_security_type, false, true);
|
||||
}
|
||||
|
||||
public static string format_symbol_expiration_standard(SecurityType security_type, string security_name, DateTime security_expiration, bool map_expiration, bool show_security_type, bool use_month_code) {
|
||||
return format_symbol_expiration_standard(security_type, security_name, security_expiration, map_expiration, show_security_type, use_month_code, true);
|
||||
}
|
||||
|
||||
public static string format_symbol_expiration_standard (SecurityType security_type, string security_name, DateTime security_expiration, bool map_expiration, bool show_security_type, bool use_month_code, bool show_day) {
|
||||
string exp_text = format_expiration_standard(security_type, security_name, security_expiration, map_expiration, use_month_code, show_day);
|
||||
return !show_security_type ? String.Format("{0} {1}", security_name, exp_text) : String.Format("{0} {1} {2}", security_type.ToString().ToUpper(), security_name, exp_text);
|
||||
}
|
||||
|
||||
public static string format_option_expiration_condensed(string option_name, DateTime option_expiration, bool map_expiration, bool show_symbol_name, bool show_year)
|
||||
{
|
||||
DateTime mapped_expiration = map_expiration ? convert_real_to_mapped(SecurityType.Option, option_name, option_expiration) : option_expiration;
|
||||
return String.Format("{0}{1}", show_symbol_name ? option_name : String.Empty, DateFormatter.format_condensed(mapped_expiration, true, show_year));
|
||||
}
|
||||
|
||||
public static DateTime parse_standard_formatted_expiration(SecurityType security_type, string security_name, string security_expiration) { return DateFormatter.parse_standard(security_expiration); }
|
||||
}
|
||||
}
|
||||
@@ -156,15 +156,13 @@ namespace mbts.ui.shell
|
||||
public string name => _propname;
|
||||
|
||||
public void set(T value) {
|
||||
if (!Equals(value, _value)) {
|
||||
Changing?.Invoke(_value, value);
|
||||
var old = _value;
|
||||
_value = value;
|
||||
Changed?.Invoke(old, value);
|
||||
_owner.RaisePropertyChanged(_propname);
|
||||
}
|
||||
if (!Equals(value, _value))
|
||||
_apply_new_value(value);
|
||||
}
|
||||
|
||||
public IDisposable set_as_job(T value) =>
|
||||
Equals(value, _value) ? null : Disposable.Create(() => _apply_new_value(value));
|
||||
|
||||
public IDisposable Subscribe(IObserver<(T oldval, T newval)> observer) {
|
||||
Changed += pch;
|
||||
return Disposable.Create(() => Changed -= pch);
|
||||
@@ -182,6 +180,14 @@ namespace mbts.ui.shell
|
||||
get { return _value; }
|
||||
set { set(value); }
|
||||
}
|
||||
|
||||
void _apply_new_value(T new_value) {
|
||||
Changing?.Invoke(_value, new_value);
|
||||
var old = _value;
|
||||
_value = new_value;
|
||||
Changed?.Invoke(old, new_value);
|
||||
_owner.RaisePropertyChanged(_propname);
|
||||
}
|
||||
}
|
||||
|
||||
protected class DelegateProperty<T> : Property<T> {
|
||||
@@ -529,7 +535,7 @@ namespace mbts.ui.shell
|
||||
/// <para/>If the user has not selected an item, but the current items do not contain the desired item, it will re-evaluate whether or not to select the item when new items arrive.
|
||||
/// </summary>
|
||||
protected SelectorProperty<T> backing<T>(string name, IObservable<IEnumerable<T>> items, IObservable<InlineUserProperty<T>> desired_item, Func<T> select_default, IReadOnlyList<PropertyValidation<T>> validation_steps) =>
|
||||
backing(name, items, desired_item, select_default, null, validation_steps);
|
||||
backing(name, items, desired_item, select_default, EqualityComparer<T>.Default, validation_steps);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a SelectorProperty<T> that observes an items source, and a desired item. When either observable ticks, it determines whether or not to assign the selected_item property.
|
||||
@@ -541,8 +547,8 @@ namespace mbts.ui.shell
|
||||
/// <param name="desired_item">The observable sequence of a desired item.</param>
|
||||
/// <param name="select_default">The fallback function to select an item by default.</param>
|
||||
/// <param name="items_match">The item-matching function used to preserve a selected item when new items arrive.</param>
|
||||
protected SelectorProperty<T> backing<T>(string name, IObservable<IEnumerable<T>> items, IObservable<InlineUserProperty<T>> desired_item, Func<T> select_default, Func<T, T, bool> items_match) =>
|
||||
backing(name, items, desired_item, select_default, items_match, new List<PropertyValidation<T>>(0));
|
||||
protected SelectorProperty<T> backing<T>(string name, IObservable<IEnumerable<T>> items, IObservable<InlineUserProperty<T>> desired_item, Func<T> select_default, IEqualityComparer<T> comparer) =>
|
||||
backing(name, items, desired_item, select_default, comparer, new List<PropertyValidation<T>>(0));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a SelectorProperty<T> that observes an items source, and a desired item. When either observable ticks, it determines whether or not to assign the selected_item property.
|
||||
@@ -555,14 +561,24 @@ namespace mbts.ui.shell
|
||||
/// <param name="select_default">The fallback function to select an item by default.</param>
|
||||
/// <param name="items_match">The item-matching function used to preserve a selected item when new items arrive.</param>
|
||||
/// <param name="validation_steps">The validation steps to take when selected_item changes.</param>
|
||||
protected SelectorProperty<T> backing<T>(string name, IObservable<IEnumerable<T>> items, IObservable<InlineUserProperty<T>> desired_item, Func<T> select_default, Func<T, T, bool> items_match, IReadOnlyList<PropertyValidation<T>> validation_steps) {
|
||||
if (_observable_properties == null) _observable_properties = new List<IDisposable>();
|
||||
var prop = new SelectorProperty<T>(this, name, select_default, items_match, validation_steps);
|
||||
_observable_properties.Add(items.OnDispatcher().Subscribe(prop));
|
||||
_observable_properties.Add(desired_item.OnDispatcher().Subscribe(prop));
|
||||
protected SelectorProperty<T> backing<T>(string name, IObservable<IEnumerable<T>> items, IObservable<InlineUserProperty<T>> desired_item, Func<T> select_default, IEqualityComparer<T> comparer, IReadOnlyList<PropertyValidation<T>> validation_steps) {
|
||||
var prop = new SelectorProperty<T>(this, name, select_default, comparer, validation_steps);
|
||||
attach(prop, items, desired_item);
|
||||
return prop;
|
||||
}
|
||||
|
||||
protected SelectorProperty<T, V> backing<T, V>(string name, IObservable<IEnumerable<T>> items, IObservable<InlineUserProperty<T>> desired_item, Func<T, V> item_to_value, Func<V> select_default, IEqualityComparer<V> comparer, IReadOnlyList<PropertyValidation<V>> validation_steps) {
|
||||
var prop = new SelectorProperty<T, V>(this, name, item_to_value, select_default, comparer, validation_steps);
|
||||
attach(prop, items, desired_item);
|
||||
return prop;
|
||||
}
|
||||
|
||||
protected void attach<T, V>(SelectorProperty<T, V> selector_property, IObservable<IEnumerable<T>> items, IObservable<InlineUserProperty<T>> desired_item) {
|
||||
if (_observable_properties == null) _observable_properties = new List<IDisposable>();
|
||||
_observable_properties.Add(items.OnDispatcher().Subscribe(selector_property));
|
||||
_observable_properties.Add(desired_item.OnDispatcher().Subscribe(selector_property));
|
||||
}
|
||||
|
||||
protected void set_dispose(IDisposable disposable) {
|
||||
if (_dispose != null) throw new InvalidOperationException("Cannot set disposable twice");
|
||||
_dispose = disposable;
|
||||
@@ -579,37 +595,44 @@ namespace mbts.ui.shell
|
||||
OnDisposed?.Invoke(true);
|
||||
}
|
||||
|
||||
protected class SelectorProperty<T> : SelectorProperty<T, T> {
|
||||
public SelectorProperty(DisposableViewModelBase owner, string prop_name, Func<T> select_default, IEqualityComparer<T> comparer, IReadOnlyList<PropertyValidation<T>> validation_steps)
|
||||
: base(owner, prop_name, i => i, select_default, comparer, validation_steps) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Designed to observe an items source, and a [settings-driven] desired item. When a new desired item is observed, it will evaluate it's current state and determine if it should be assigned to the selected_item.
|
||||
/// <para/>Notes: If the user has selected an item (ie the selected_item has been assigned through the public setter), the desired item will be ignored unless force_override is true.
|
||||
/// <para/>If the user has not selected an item, but the current items do not contain the desired item, it will re-evaluate whether or not to select the item when new items arrive.
|
||||
/// </summary>
|
||||
protected class SelectorProperty<T> : IObserver<InlineUserProperty<T>>, IObserver<IEnumerable<T>>, IObservable<(T oldval, T newval)> {
|
||||
protected class SelectorProperty<TItem, TValue> : IObserver<InlineUserProperty<TItem>>, IObserver<IEnumerable<TItem>>, IObservable<(TValue oldval, TValue newval)> {
|
||||
readonly DisposableViewModelBase _owner;
|
||||
readonly string _prop_name;
|
||||
readonly IReadOnlyList<PropertyValidation<T>> _validation_steps;
|
||||
readonly ObservableCollection<T> _items = new ObservableCollection<T>();
|
||||
readonly Func<T> _select_default;
|
||||
readonly Func<T, T, bool> _items_match; // used to maintain selected_item through an items-change
|
||||
T _selected_item;
|
||||
InlineUserProperty<T> _desired_item;
|
||||
readonly IReadOnlyList<PropertyValidation<TValue>> _validation_steps;
|
||||
readonly ObservableCollection<TItem> _items = new ObservableCollection<TItem>();
|
||||
readonly Func<TValue> _select_default;
|
||||
readonly IEqualityComparer<TValue> _value_comparer;
|
||||
readonly Func<TItem, TValue> _item_to_value;
|
||||
TValue _selected_item;
|
||||
InlineUserProperty<TItem> _desired_item = new InlineUserProperty<TItem>();
|
||||
bool _is_user_selected_item;
|
||||
|
||||
public SelectorProperty(DisposableViewModelBase owner, string prop_name, Func<T> select_default, Func<T, T, bool> items_match, IReadOnlyList<PropertyValidation<T>> validation_steps) {
|
||||
public SelectorProperty(DisposableViewModelBase owner, string prop_name, Func<TItem, TValue> item_to_value, Func<TValue> select_default, IEqualityComparer<TValue> value_comparer, IReadOnlyList<PropertyValidation<TValue>> validation_steps) {
|
||||
_owner = owner;
|
||||
_prop_name = prop_name;
|
||||
_item_to_value = item_to_value;
|
||||
_select_default = select_default;
|
||||
_items_match = items_match;
|
||||
_value_comparer = value_comparer ?? EqualityComparer<TValue>.Default;
|
||||
_validation_steps = validation_steps;
|
||||
items = new ReadOnlyObservableCollection<T>(_items);
|
||||
items = new ReadOnlyObservableCollection<TItem>(_items);
|
||||
}
|
||||
|
||||
public event PropertyChange<T> Changing;
|
||||
public event PropertyChange<T> Changed;
|
||||
public event PropertyChange<TValue> Changing;
|
||||
public event PropertyChange<TValue> Changed;
|
||||
|
||||
public ReadOnlyObservableCollection<T> items { get; }
|
||||
public ReadOnlyObservableCollection<TItem> items { get; }
|
||||
|
||||
public T selected_item {
|
||||
public TValue selected_item {
|
||||
get => _selected_item;
|
||||
set {
|
||||
_is_user_selected_item = true;
|
||||
@@ -617,31 +640,31 @@ namespace mbts.ui.shell
|
||||
}
|
||||
}
|
||||
|
||||
public IDisposable Subscribe(IObserver<(T oldval, T newval)> observer) {
|
||||
public IDisposable Subscribe(IObserver<(TValue oldval, TValue newval)> observer) {
|
||||
Changed += pch;
|
||||
return Disposable.Create(() => Changed -= pch);
|
||||
void pch(T o, T n) => observer.OnNext((o, n));
|
||||
void pch(TValue o, TValue n) => observer.OnNext((o, n));
|
||||
}
|
||||
|
||||
public IObservable<T> observe_current(bool start_now = false) {
|
||||
public IObservable<TValue> observe_current(bool start_now = false) {
|
||||
var source = this.Select(vals => vals.newval);
|
||||
if (start_now)
|
||||
source = source.StartWith(_selected_item);
|
||||
source = source.StartWith(selected_item);
|
||||
return source;
|
||||
}
|
||||
|
||||
void IObserver<InlineUserProperty<T>>.OnNext(InlineUserProperty<T> iup) {
|
||||
void IObserver<InlineUserProperty<TItem>>.OnNext(InlineUserProperty<TItem> iup) {
|
||||
_desired_item = iup;
|
||||
_try_auto_select();
|
||||
}
|
||||
void IObserver<InlineUserProperty<T>>.OnError(Exception error) { }
|
||||
void IObserver<InlineUserProperty<T>>.OnCompleted() { }
|
||||
void IObserver<InlineUserProperty<TItem>>.OnError(Exception error) { }
|
||||
void IObserver<InlineUserProperty<TItem>>.OnCompleted() { }
|
||||
|
||||
void IObserver<IEnumerable<T>>.OnNext(IEnumerable<T> value) {
|
||||
if (_items_match != null && _is_user_selected_item) {
|
||||
void IObserver<IEnumerable<TItem>>.OnNext(IEnumerable<TItem> value) {
|
||||
if (_is_user_selected_item) {
|
||||
var curr_selected_item = selected_item;
|
||||
_items.sync_with(value);
|
||||
if (_try_match_item(curr_selected_item, out T match))
|
||||
if (_try_match_item(curr_selected_item, out TValue match))
|
||||
selected_item = match;
|
||||
else {
|
||||
_is_user_selected_item = false;
|
||||
@@ -649,18 +672,13 @@ namespace mbts.ui.shell
|
||||
}
|
||||
} else {
|
||||
_items.sync_with(value);
|
||||
if (_is_user_selected_item) {
|
||||
_is_user_selected_item = _items.Contains(_selected_item);
|
||||
}
|
||||
if (!_is_user_selected_item) {
|
||||
_try_auto_select();
|
||||
}
|
||||
_try_auto_select();
|
||||
}
|
||||
}
|
||||
void IObserver<IEnumerable<T>>.OnError(Exception error) { }
|
||||
void IObserver<IEnumerable<T>>.OnCompleted() { }
|
||||
void IObserver<IEnumerable<TItem>>.OnError(Exception error) { }
|
||||
void IObserver<IEnumerable<TItem>>.OnCompleted() { }
|
||||
|
||||
void _run_validation(T val) {
|
||||
void _run_validation(TValue val) {
|
||||
var invalid_steps = _validation_steps.Select(v => v.validate(val)).Where(r => !r.valid);
|
||||
if (invalid_steps.Count() > 0) {
|
||||
var error_msg = string.Join("\n", invalid_steps.Where(r => !string.IsNullOrEmpty(r.msg)).Select(r => r.msg));
|
||||
@@ -670,15 +688,15 @@ namespace mbts.ui.shell
|
||||
|
||||
void _try_auto_select() {
|
||||
if (_is_user_selected_item) {
|
||||
if (desired_item_valid() && _desired_item.force_override && _try_match_item(_desired_item.value, out T match)) {
|
||||
if (desired_item_valid() && _desired_item.force_override && _try_match_item(_desired_item.value, out TValue match)) {
|
||||
_set_selected_item(match);
|
||||
return;
|
||||
}
|
||||
} else if (desired_item_valid() && _try_match_item(_desired_item.value, out T match)) {
|
||||
} else if (desired_item_valid() && _try_match_item(_desired_item.value, out TValue match)) {
|
||||
_set_selected_item(match);
|
||||
return;
|
||||
}
|
||||
if (_try_match_item(_select_default(), out T default_match))
|
||||
if (_try_match_item(_select_default(), out TValue default_match))
|
||||
_set_selected_item(default_match);
|
||||
else {
|
||||
// the _set_selected_item has never been entered, so validation has never ran, force it here
|
||||
@@ -688,8 +706,8 @@ namespace mbts.ui.shell
|
||||
bool desired_item_valid() => (_desired_item?.has_value).GetValueOrDefault();
|
||||
}
|
||||
|
||||
void _set_selected_item(T value) {
|
||||
if (!Equals(value, _selected_item)) {
|
||||
void _set_selected_item(TValue value) {
|
||||
if (!_value_comparer.Equals(value, _selected_item)) {
|
||||
Changing?.Invoke(_selected_item, value);
|
||||
var old = _selected_item;
|
||||
_selected_item = value;
|
||||
@@ -699,10 +717,20 @@ namespace mbts.ui.shell
|
||||
}
|
||||
}
|
||||
|
||||
bool _try_match_item(T item, out T match) =>
|
||||
_items_match != null ?
|
||||
_items.TryGetFirst(i => _items_match(i, item), out match) :
|
||||
_items.TryGetFirst(i => i.Equals(item), out match);
|
||||
bool _try_match_item(TValue value, out TValue match) {
|
||||
foreach (TItem item in _items) {
|
||||
TValue v = _item_to_value(item);
|
||||
if (_value_comparer.Equals(v, value)) {
|
||||
match = v;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
match = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _try_match_item(TItem item, out TValue match) =>
|
||||
_try_match_item(_item_to_value(item), out match);
|
||||
}
|
||||
|
||||
public event Action<bool> OnDisposed;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace mbts.spark {
|
||||
value = initial_value;
|
||||
}
|
||||
|
||||
event Action<(T oldval, T newval)> _value_set;
|
||||
public event Action<(T oldval, T newval)> value_set;
|
||||
|
||||
public T value { get; private set; }
|
||||
public string text => _text ?? (_text = _format(value));
|
||||
@@ -27,14 +27,22 @@ namespace mbts.spark {
|
||||
}
|
||||
}
|
||||
|
||||
public IDisposable on_next_distinct_as_job(T value, ref bool dirty) {
|
||||
if (!value.Equals(this.value)) {
|
||||
dirty = true;
|
||||
return Disposable.Create(() => OnNext(value));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void OnCompleted() { }
|
||||
public void OnError(Exception error) { }
|
||||
public void OnNext(T value) {
|
||||
if (_value_set != null) {
|
||||
if (value_set != null) {
|
||||
T prev = this.value;
|
||||
this.value = value;
|
||||
_text = null;
|
||||
_value_set.Invoke((prev, value));
|
||||
value_set.Invoke((prev, value));
|
||||
} else {
|
||||
this.value = value;
|
||||
_text = null;
|
||||
@@ -42,7 +50,7 @@ namespace mbts.spark {
|
||||
}
|
||||
|
||||
public IDisposable Subscribe(IObserver<(T oldval, T newval)> observer) =>
|
||||
Observable.FromEvent<Action<(T oldval, T newval)>, (T oldval, T newval)>(cb => _value_set += cb, cb => _value_set -= cb)
|
||||
Observable.FromEvent<Action<(T oldval, T newval)>, (T oldval, T newval)>(cb => value_set += cb, cb => value_set -= cb)
|
||||
.Subscribe(observer);
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@
|
||||
</ComboBox.GroupStyle>
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<usp:OrderTypeItem OrderType="{Binding order_type}" Metadata="{Binding meta}"/>
|
||||
<usp:OrderTypeItem OrderType="{Binding order_type}" DisplayName="{Binding display_name}" Metadata="{Binding meta}"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
Width="15"
|
||||
Height="10"
|
||||
/>
|
||||
<TextBlock
|
||||
<TextBlock x:Name="text"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Margin="20,0,0,0"
|
||||
|
||||
@@ -3,23 +3,49 @@ using bts.spark;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace mbts.ui.spark
|
||||
{
|
||||
namespace mbts.ui.spark {
|
||||
/// <summary>
|
||||
/// Interaction logic for OrderTypeItem.xaml
|
||||
/// </summary>
|
||||
public partial class OrderTypeItem : Control
|
||||
{
|
||||
static OrderTypeItem() {
|
||||
partial class OrderTypeItem : Control {
|
||||
static OrderTypeItem() =>
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(OrderTypeItem), new FrameworkPropertyMetadata(typeof(OrderTypeItem)));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty OrderTypeProperty = DependencyProperty.Register(nameof(OrderType), typeof(CustomOrderDefinition.CustomOneofCase), typeof(OrderTypeItem),
|
||||
new PropertyMetadata(CustomOrderDefinition.CustomOneofCase.None));
|
||||
public CustomOrderDefinition.CustomOneofCase OrderType { get => (CustomOrderDefinition.CustomOneofCase)GetValue(OrderTypeProperty); set => SetValue(OrderTypeProperty, value); }
|
||||
|
||||
public static readonly DependencyProperty DisplayNameProperty =
|
||||
WPFHelper.create_dp<string, OrderTypeItem>(nameof(DisplayName), (o, v) => {
|
||||
o._display_name = v;
|
||||
o._update_text();
|
||||
});
|
||||
|
||||
public string DisplayName {
|
||||
get => GetValue(DisplayNameProperty) as string;
|
||||
set => SetValue(DisplayNameProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MetadataProperty = DependencyProperty.Register(nameof(Metadata), typeof(OrderMetadata), typeof(OrderTypeItem),
|
||||
new PropertyMetadata(new OrderMetadata { Color = 0, KeyBinding = string.Empty }));
|
||||
public OrderMetadata Metadata { get => GetValue(MetadataProperty) as OrderMetadata; set => SetValue(MetadataProperty, value); }
|
||||
|
||||
string _display_name;
|
||||
TextBlock _text;
|
||||
|
||||
public override void OnApplyTemplate() {
|
||||
this.try_get_template_child("text", out _text);
|
||||
_update_text();
|
||||
}
|
||||
|
||||
void _update_text() {
|
||||
if (_text != null) {
|
||||
if (string.IsNullOrEmpty(_display_name)) {
|
||||
_text.ClearValue(TextBlock.TextProperty);
|
||||
} else {
|
||||
_text.SetCurrentValue(TextBlock.TextProperty, _display_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using bts.api;
|
||||
using mbts.ui.utility;
|
||||
using System;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace mbts.ui.converters
|
||||
{
|
||||
public class SecurityTypeStringConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
|
||||
return SecurityDisplay.format_security_type((SecurityType)value);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
using bts.api;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace mbts.ui.converters
|
||||
{
|
||||
[ValueConversion(typeof(SecurityType), typeof(Brush))]
|
||||
public class SecurityTypeForegroundConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
|
||||
if (value is SecurityType) return _convert((SecurityType)value);
|
||||
//else if (value is SecurityTuple) return _convert(((SecurityTuple)value).security_type);
|
||||
//else if (value is SecurityExpiration) return _convert(((SecurityExpiration)value).security_type);
|
||||
else return SystemColors.ControlTextBrush;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Brush _convert(SecurityType type) {
|
||||
switch (type) {
|
||||
case SecurityType.Option: return (Brush)BTSColors.header_text;
|
||||
case SecurityType.Future: return new SolidColorBrush(Colors.Gold);
|
||||
case SecurityType.Spread: return new SolidColorBrush(Colors.SlateBlue);
|
||||
default: return new SolidColorBrush(Colors.PaleGreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,6 @@
|
||||
<cv:CellPathConverter x:Key="CellPathConverter" />
|
||||
<cv:CellKeyConverter x:Key="CellKeyConverter" />
|
||||
<cv:SecurityDisplayTextConverter x:Key="SecurityTextConverter"/>
|
||||
<cv:SecurityTypeForegroundConverter x:Key="SecurityTypeForegroundConverter" />
|
||||
<cv:SecurityTypeStringConverter x:Key="SecurityTypeStringConverter" />
|
||||
<cv:NumericSignBrushConverter x:Key="NumericSignBrushConverter" />
|
||||
<cv:TickDisplayTextConverter x:Key="TickTextConverter" />
|
||||
<cv:DoubleTextConverter x:Key="DoubleTextConverter" />
|
||||
|
||||
@@ -386,7 +386,7 @@ namespace mbts.spark {
|
||||
void _tick() {
|
||||
if (_settings != null) {
|
||||
ulong unused = 0;
|
||||
bool last_trade_changed = _vm.md.get_last_trade(ref unused, out _last_trade, out DateTime _, out ulong __);
|
||||
bool last_trade_changed = _vm.md.get_last_trade(ref unused, out _last_trade, out ulong __);
|
||||
bool depth_changed = _vm.md.get_depth(ref _prices_updated, ref _bids, ref _asks);
|
||||
_mkt_break_lines.refresh();
|
||||
bool prices_changed =
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace mbts.spark {
|
||||
_dispose = Disposable.Create(
|
||||
settings_command,
|
||||
order_properties_vm,
|
||||
order_properties_vm.observe_account(true).Select(a => a.name).Subscribe(account_positions),
|
||||
order_properties_vm.observe_account(true).Select(a => a?.name ?? string.Empty).Subscribe(account_positions),
|
||||
account_positions,
|
||||
size_calculator = new CalculatorLogic(0, _settings_manager.subscribe_current().Select(s => s.calculator_buttons)),
|
||||
bus.subscribe(SparkTags.LogActivity).OnDispatcher().Subscribe(status_update),
|
||||
@@ -275,7 +275,7 @@ namespace mbts.spark {
|
||||
_open.set(md.open_price);
|
||||
_settlement.set(md.settlement_price);
|
||||
ulong unused = 0;
|
||||
md.get_last_trade(ref unused, out NativePriceSize last, out DateTime time, out ulong volume);
|
||||
md.get_last_trade(ref unused, out NativePriceSize last, out ulong volume);
|
||||
if (!double.IsNaN(last.price)) {
|
||||
_change.set(last.price - md.settlement_price);
|
||||
} else {
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace mbts.spark {
|
||||
if (!sec_md.md.get_bbo(ref bbo_time, out NativePriceSize bid, out NativePriceSize ask)) return false;
|
||||
// last is only used in waterfall and last calculations, so if neither of those types are selected
|
||||
// we should not exit early if last is somehow not avaialble
|
||||
if (!sec_md.md.get_last_trade(ref last_trade_time, out NativePriceSize last, out DateTime unused1, out ulong unused2) && pnl_request.HasFlag(pnl_calc_type.waterfall | pnl_calc_type.last)) return false;
|
||||
if (!sec_md.md.get_last_trade(ref last_trade_time, out NativePriceSize last, out ulong unused2) && pnl_request.HasFlag(pnl_calc_type.waterfall | pnl_calc_type.last)) return false;
|
||||
|
||||
if (pnl_request.HasFlag(pnl_calc_type.waterfall)) {
|
||||
// last price is available and withing range of available bid and ask
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace mbts.spark.utilities
|
||||
internal interface ISecurityMDPump
|
||||
{
|
||||
IObservable<(double bid, uint bid_size, double ask, uint ask_size)> bbo { get; }
|
||||
IObservable<(double last, uint last_size, DateTime time_stamp, ulong volume)> last_trade { get; }
|
||||
IObservable<(double last, uint last_size, ulong volume)> last_trade { get; }
|
||||
IObservable<double> bid_price { get; }
|
||||
IObservable<uint> bid_size { get; }
|
||||
IObservable<double> ask_price { get; }
|
||||
@@ -61,7 +61,6 @@ namespace mbts.spark.utilities
|
||||
private double _bid_price, _ask_price, _last_price;
|
||||
private uint _bid_size, _ask_size, _last_size;
|
||||
private ulong _volume;
|
||||
private DateTime _last_time;
|
||||
|
||||
private bool _refresh_bbo(MDConsumerHandle md) {
|
||||
if (md.get_bbo(ref _bbo_ref, out NativePriceSize b, out NativePriceSize a)) {
|
||||
@@ -75,10 +74,9 @@ namespace mbts.spark.utilities
|
||||
}
|
||||
|
||||
private bool _refresh_last(MDConsumerHandle md) {
|
||||
if (md.get_last_trade(ref _last_ref, out NativePriceSize ps, out DateTime ts, out ulong v)) {
|
||||
if (md.get_last_trade(ref _last_ref, out NativePriceSize ps, out ulong v)) {
|
||||
_last_price = ps.price;
|
||||
_last_size = ps.size;
|
||||
_last_time = ts;
|
||||
_volume = v;
|
||||
return true;
|
||||
}
|
||||
@@ -86,17 +84,16 @@ namespace mbts.spark.utilities
|
||||
}
|
||||
|
||||
private (double, uint, double, uint) _select_bbo() { return (_bid_price, _bid_size, _ask_price, _ask_size); }
|
||||
private (double, uint, DateTime, ulong) _select_last() { return (_last_price, _last_size, _last_time, _volume); }
|
||||
private (double, uint, ulong) _select_last() { return (_last_price, _last_size, _volume); }
|
||||
|
||||
public IObservable<(double bid, uint bid_size, double ask, uint ask_size)> bbo => _bbo_pump.Select(_ => _select_bbo()).StartWith(_select_bbo());
|
||||
public IObservable<(double last, uint last_size, DateTime time_stamp, ulong volume)> last_trade => _last_pump.Select(_ => _select_last()).StartWith(_select_last());
|
||||
public IObservable<(double last, uint last_size, ulong volume)> last_trade => _last_pump.Select(_ => _select_last()).StartWith(_select_last());
|
||||
public IObservable<double> bid_price => _bbo_pump.Select(_ => _bid_price).DistinctUntilChanged().StartWith(_bid_price);
|
||||
public IObservable<uint> bid_size => _bbo_pump.Select(_ => _bid_size).DistinctUntilChanged().StartWith(_bid_size);
|
||||
public IObservable<double> ask_price => _bbo_pump.Select(_ => _ask_price).DistinctUntilChanged().StartWith(_ask_price);
|
||||
public IObservable<uint> ask_size => _bbo_pump.Select(_ => _ask_size).DistinctUntilChanged().StartWith(_ask_size);
|
||||
public IObservable<double> last_price => _bbo_pump.Select(_ => _last_price).DistinctUntilChanged().StartWith(_last_price);
|
||||
public IObservable<uint> last_size => _bbo_pump.Select(_ => _last_size).DistinctUntilChanged().StartWith(_last_size);
|
||||
public IObservable<DateTime> last_time => _last_pump.Select(_ => _last_time).DistinctUntilChanged().StartWith(_last_time);
|
||||
public IObservable<ulong> volume => _last_pump.Select(_ => _volume).DistinctUntilChanged().StartWith(_volume);
|
||||
public IObservable<double> session_low => _root_pump.Select(md => md.session_low).DistinctUntilChanged();
|
||||
public IObservable<double> session_high => _root_pump.Select(md => md.session_high).DistinctUntilChanged();
|
||||
|
||||
@@ -110,6 +110,29 @@ namespace mbts.spark.utilities {
|
||||
return defs;
|
||||
}
|
||||
|
||||
public Dictionary<OrderTemplateHeader, CustomOrderDefinitionImmutable> default_order_type_templates(SecurityImmutable security, bool is_child = false) {
|
||||
const int name_ref_seed = 1;
|
||||
// standard types
|
||||
var defs = default_order_types(security, is_child)
|
||||
.Except(new[] { CustomOrderDefinition.CustomOneofCase.Dynamic })
|
||||
.ToDictionary(ot => new OrderTemplateHeader(new OrderTemplateKey(ot), OrderUtils.order_type_display_name(ot)), ot => new CustomOrderDefinitionImmutable(custom_order(ot)));
|
||||
// TODO: replace with better naming scheme (right now, the order type ref count 'n' is appended to the order-type name)
|
||||
var order_type_ref_count = defs.ToDictionary(kv => kv.Key, kv => name_ref_seed);
|
||||
var dynamic_defs = new List<CustomOrderDefinitionImmutable>();
|
||||
DynamicOrderHelper.add_dynamic_order_defs(dynamic_defs, ot => custom_order(ot));
|
||||
foreach (var ddef in dynamic_defs) {
|
||||
var header = new OrderTemplateHeader(new OrderTemplateKey(ddef.CustomCase, ddef.Dynamic.DynamicOrderType), ddef.Dynamic.DynamicOrderType );
|
||||
// if (order_type_ref_count.TryGetValue(header, out int count)) {
|
||||
// order_type_ref_count[header]++;
|
||||
// header = new OrderTemplateHeader(new OrderTemplateKey(header.key.type, $"{header.key.name}{count}"), $"{header.display_name}{count}");
|
||||
// } else {
|
||||
// order_type_ref_count[header] = name_ref_seed;
|
||||
// }
|
||||
defs.Add(header, ddef);
|
||||
}
|
||||
return defs;
|
||||
}
|
||||
|
||||
public IEnumerable<CustomOrderDefinition.CustomOneofCase> default_order_types(SecurityImmutable? security, bool is_child=false) =>
|
||||
security.HasValue ? default_order_types(security.Value, is_child) : default_order_types();
|
||||
|
||||
@@ -212,7 +235,7 @@ namespace mbts.spark.utilities {
|
||||
|
||||
public DynamicOrderDefinition dynamic_order() => new DynamicOrderDefinition
|
||||
{
|
||||
Child = custom_order(),
|
||||
//Child = custom_order(),
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ using System.Windows.Threading;
|
||||
namespace mbts.spark {
|
||||
static class WorkLoop {
|
||||
public const double default_excessive_cycle_ratio = 1.2;
|
||||
static readonly DispatcherPriority default_priority;
|
||||
static readonly TimeSpan default_interval;
|
||||
public static readonly TimeSpan default_interval;
|
||||
public static readonly DispatcherPriority default_priority;
|
||||
|
||||
static WorkLoop() {
|
||||
var timer_params = config.Configuration.get<bts.config.LadderKnobs>();
|
||||
|
||||
@@ -48,20 +48,23 @@ namespace mbts.ui.utility
|
||||
return null;
|
||||
}
|
||||
|
||||
static (int width,int height) screen_size() {
|
||||
static Int32Rect screen_size() {
|
||||
var config = Configuration.get<bts.config.System>();
|
||||
double width = SystemParameters.VirtualScreenWidth * config.dpi_ratio;
|
||||
double height = SystemParameters.VirtualScreenHeight * config.dpi_ratio;
|
||||
return ((int)width, (int)height);
|
||||
var dpi = config.dpi_ratio;
|
||||
return new Int32Rect(
|
||||
(int)(SystemParameters.VirtualScreenLeft * dpi),
|
||||
(int)(SystemParameters.VirtualScreenTop * dpi),
|
||||
(int)(SystemParameters.VirtualScreenWidth * dpi),
|
||||
(int)(SystemParameters.VirtualScreenHeight * dpi));
|
||||
}
|
||||
|
||||
private static BitmapSource capture() {
|
||||
(int width, int height) = screen_size();
|
||||
var screen = screen_size();
|
||||
IntPtr screen_dc = NativeMethods.GetDC(IntPtr.Zero);
|
||||
IntPtr mem_dc = NativeMethods.CreateCompatibleDC(screen_dc);
|
||||
IntPtr hbitmap = NativeMethods.CreateCompatibleBitmap(screen_dc, width, height);
|
||||
IntPtr hbitmap = NativeMethods.CreateCompatibleBitmap(screen_dc, screen.Width, screen.Height);
|
||||
NativeMethods.SelectObject(mem_dc, hbitmap);
|
||||
bool success = NativeMethods.BitBlt(mem_dc, 0, 0, width, height, screen_dc, 0, 0);
|
||||
bool success = NativeMethods.BitBlt(mem_dc, 0, 0, screen.Width, screen.Height, screen_dc, screen.X, screen.Y);
|
||||
BitmapSource bsource = Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
|
||||
NativeMethods.DeleteObject(hbitmap);
|
||||
NativeMethods.ReleaseDC(IntPtr.Zero, screen_dc);
|
||||
@@ -71,13 +74,13 @@ namespace mbts.ui.utility
|
||||
|
||||
|
||||
private static BitmapSource capture(int width_dest, int height_dest) {
|
||||
(int width_src, int height_src) = screen_size();
|
||||
var screen = screen_size();
|
||||
IntPtr screen_dc = NativeMethods.GetDC(IntPtr.Zero);
|
||||
IntPtr mem_dc = NativeMethods.CreateCompatibleDC(screen_dc);
|
||||
IntPtr hbitmap = NativeMethods.CreateCompatibleBitmap(screen_dc, width_dest, height_dest);
|
||||
NativeMethods.SelectObject(mem_dc, hbitmap);
|
||||
NativeMethods.SetStretchBltMode(mem_dc, 4/*HALFTONE*/);
|
||||
bool success = NativeMethods.StretchBlt(mem_dc, 0, 0, width_dest, height_dest, screen_dc, 0, 0, width_src, height_src);
|
||||
bool success = NativeMethods.StretchBlt(mem_dc, 0, 0, width_dest, height_dest, screen_dc, screen.X, screen.Y, screen.Width, screen.Height);
|
||||
BitmapSource bsource = Imaging.CreateBitmapSourceFromHBitmap(hbitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
|
||||
NativeMethods.DeleteObject(hbitmap);
|
||||
NativeMethods.ReleaseDC(IntPtr.Zero, screen_dc);
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
using bts.api;
|
||||
using mbts.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
namespace mbts.ui.utility
|
||||
{
|
||||
public enum DateFormat { Standard, DayMonthAbvDiff2000, DayMonthCodeDiff2000 }
|
||||
static class SecurityDisplay
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a shorthand string representation of a security type appropriate for UIs.
|
||||
/// </summary>
|
||||
public static string format_security_type(SecurityType type) {
|
||||
switch (type) {
|
||||
case SecurityType.Option: return "Opt";
|
||||
case SecurityType.Future: return "Fut";
|
||||
case SecurityType.Stock: return "Stk";
|
||||
case SecurityType.Spread: return "Spd";
|
||||
default: return type.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a concise string representation of a security expiration appropriate for UIs (e.g. es March 22, 2019: es 22 Mar 19).
|
||||
/// </summary>
|
||||
public static string format_expiration(SecurityType sec_type, string symbol, DateTime exp_date) { return format_expiration(sec_type, symbol, exp_date, false, true, true, DateFormat.DayMonthAbvDiff2000); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a concise string representation of a security expiration (using symbol-mapped expiration dates, and single-letter month codes) appropriate for UIs (e.g. es March 22, 2019: [Opt] [es] 22 Mar 19).
|
||||
/// </summary>
|
||||
public static string format_expiration(SecurityType sec_type, string symbol, DateTime exp_date, bool show_type, bool show_symbol, bool use_mapped_exp) { return format_expiration(sec_type, symbol, exp_date, show_type, show_symbol, use_mapped_exp, DateFormat.Standard); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a concise string representation of a security expiration (using symbol-mapped expiration dates, and single-letter month codes) appropriate for UIs (e.g. es March 22, 2019: [Opt] [es] 22 Mar 19, or [Opt] [es] 22 H19).
|
||||
/// </summary>
|
||||
public static string format_expiration(SecurityType sec_type, string symbol, DateTime exp_date, bool show_type, bool show_symbol, bool use_mapped_exp, DateFormat date_format) {
|
||||
if (use_mapped_exp) exp_date = ExpirationFormatter.convert_real_to_mapped(sec_type, symbol, exp_date);
|
||||
string result = format_date(exp_date);
|
||||
if (show_symbol) result = (symbol + " " + result);
|
||||
if (show_type) result = (format_security_type(sec_type) + " " + result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a concise string representation of a future trade appropriate for UIs.
|
||||
/// </summary>
|
||||
public static string format_future_trade(string symbol, DateTime exp_date, int size, double marginal_price) { return "{0} {1} lots @ {2:C}".fmt(format_expiration(SecurityType.Future, symbol, exp_date, false, true, true), size, marginal_price); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a concise string representation of an option trade appropriate for UIs.
|
||||
/// </summary>
|
||||
public static string format_option_trade(string symbol, DateTime exp_date, double strike, bool is_call, int size, double marginal_price) {
|
||||
return "{0} {1} {2} {3} lots @ {4:C}".fmt(format_expiration(SecurityType.Option, symbol, exp_date, false, true, true), strike, is_call ? "C" : "P", size, marginal_price);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a concise string representation of a date (using standard month abbreviations) appropriate for UIs (e.g. March 22, 2019: 22 Mar 19).
|
||||
/// </summary>
|
||||
public static string format_date(DateTime date) { return format_date(date.Year, date.Month, date.Day, DateFormat.DayMonthAbvDiff2000); }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a concise string representation of a date (using single-letter month codes) appropriate for UIs (e.g. March 22, 2019: 22 Mar 19, or 22 H19).
|
||||
/// </summary>
|
||||
public static string format_date(int year, int month, int day, DateFormat format) {
|
||||
switch(format) {
|
||||
case DateFormat.DayMonthAbvDiff2000: return "{0} {1} {2}".fmt(day, get_month_abv(month), year - 2000);
|
||||
case DateFormat.DayMonthCodeDiff2000: return "{0} {1}{2}".fmt(day, get_month_code(month), year - 2000);
|
||||
case DateFormat.Standard: goto default;
|
||||
default: return "{0}/{1}/{2}".fmt(day, month, year);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the option industry standard month code.
|
||||
/// </summary>
|
||||
public static string get_month_code(int month) { _check_month(month); return _month_codes[month - 1]; }
|
||||
/// <summary>
|
||||
/// Returns the standard month abbreviation (Jan, Feb, Mar, etc.).
|
||||
/// </summary>
|
||||
public static string get_month_abv(int month) { _check_month(month); return _month_abvs[month - 1]; }
|
||||
#region Private Members
|
||||
private static void _check_month(int month) { if (month < 1 || month > 12) throw new ArgumentException("There are only twelve months in a year", "month"); }
|
||||
private static string[] _month_codes = new string[] { "F", "G", "H", "J", "K", "M", "N", "Q", "U", "V", "X", "Z" };
|
||||
private static string[] _month_abvs = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
@@ -53,28 +54,43 @@ namespace bts.api.core {
|
||||
#endif
|
||||
}
|
||||
|
||||
public readonly struct Change<T> {
|
||||
public Change(T o, T n) {
|
||||
Old = o;
|
||||
New = n;
|
||||
}
|
||||
public readonly T Old;
|
||||
public readonly T New;
|
||||
public Change<T> merge(Change<T> newer) {
|
||||
return new Change<T>(Old, newer.New);
|
||||
}
|
||||
public override string ToString() {
|
||||
return $"{{{Old}=>{New}}}";
|
||||
}
|
||||
}
|
||||
|
||||
public class Update<T, TKey> where TKey : IEquatable<TKey> {
|
||||
private Func<T, TKey> _key;
|
||||
internal Update(
|
||||
IReadOnlyCollection<T> all,
|
||||
IEnumerable<T> added,
|
||||
IEnumerable<(T New,T Old)> changes,
|
||||
IEnumerable<Change<T>> changes,
|
||||
IEnumerable<T> removed,
|
||||
Func<T, TKey> key_extractor) {
|
||||
this.added = added ?? new T[0];
|
||||
this.removed = removed ?? new T[0];
|
||||
this.changes = changes ?? new (T,T)[0];
|
||||
this.changes = changes ?? new Change<T>[0];
|
||||
this.all = all;
|
||||
_key = key_extractor;
|
||||
}
|
||||
|
||||
public static Update<T, TKey> empty(Func<T, TKey> key_extractor) =>
|
||||
new Update<T, TKey>(new T[0], new T[0], new (T,T)[0], new T[0], key_extractor);
|
||||
new Update<T, TKey>(new T[0], new T[0], new Change<T>[0], new T[0], key_extractor);
|
||||
|
||||
public Update<T,TKey> merge(Update<T, TKey> next) {
|
||||
var comp = new RowEqualityComparer<T, TKey>(_key);
|
||||
var added = this.added as HashSet<T> ?? new HashSet<T>(this.added, comp);
|
||||
var changes = this.changed as HashSet<(T New,T Old)> ?? new HashSet<(T,T)>(this.changes, comp);
|
||||
var changes = this.changed as ChangeDict<T,TKey> ?? new ChangeDict<T,TKey>(this.changes, _key);
|
||||
var removed = this.removed as HashSet<T> ?? new HashSet<T>(this.removed, comp);
|
||||
|
||||
// Add
|
||||
@@ -87,9 +103,7 @@ namespace bts.api.core {
|
||||
added.Add(c.New);
|
||||
}
|
||||
else {
|
||||
// Remove does not error if it was not present
|
||||
changes.Remove(c);
|
||||
changes.Add(c);
|
||||
changes.AddOrMerge(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +112,7 @@ namespace bts.api.core {
|
||||
if (!added.Remove(r)) {
|
||||
removed.Add(r);
|
||||
}
|
||||
changes.Remove((r,r));
|
||||
changes.Remove(_key(r));
|
||||
}
|
||||
|
||||
return new Update<T, TKey>(
|
||||
@@ -110,7 +124,7 @@ namespace bts.api.core {
|
||||
|
||||
public IReadOnlyCollection<T> all { get; }
|
||||
public IEnumerable<T> added { get; }
|
||||
public IEnumerable<(T New,T Old)> changes { get; }
|
||||
public IEnumerable<Change<T>> changes { get; }
|
||||
public IEnumerable<T> changed => changes.Select(c => c.New);
|
||||
public IEnumerable<T> removed { get; }
|
||||
|
||||
@@ -127,7 +141,40 @@ namespace bts.api.core {
|
||||
#endif
|
||||
}
|
||||
|
||||
struct RowEqualityComparer<T,TKey> : IEqualityComparer<T>, IEqualityComparer<(T,T)>
|
||||
class ChangeDict<T, TKey> : IEnumerable<Change<T>> {
|
||||
Dictionary<TKey, Change<T>> _changes;
|
||||
Func<Change<T>, TKey> _key;
|
||||
|
||||
public ChangeDict(IEnumerable<Change<T>> changes, Func<T, TKey> key) {
|
||||
_key = x => key(x.New);
|
||||
_changes = changes.ToDictionary(_key);
|
||||
}
|
||||
|
||||
public Change<T>? AddOrMerge(Change<T> newer) {
|
||||
var key = _key(newer);
|
||||
if (_changes.TryGetValue(key, out Change<T> old)) {
|
||||
_changes[key] = old.merge(newer);
|
||||
return old;
|
||||
}
|
||||
_changes.Add(key, newer);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Remove(TKey key) {
|
||||
_changes.Remove(key);
|
||||
}
|
||||
|
||||
#region IEnumerable
|
||||
public IEnumerator<Change<T>> GetEnumerator() {
|
||||
return _changes.Values.GetEnumerator();
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return _changes.Values.GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
struct RowEqualityComparer<T,TKey> : IEqualityComparer<T>, IEqualityComparer<Change<T>>
|
||||
where TKey : IEquatable<TKey> {
|
||||
readonly Func<T,TKey> _key;
|
||||
|
||||
@@ -139,16 +186,16 @@ namespace bts.api.core {
|
||||
return _key(x).Equals(_key(y));
|
||||
}
|
||||
|
||||
public bool Equals((T, T) x, (T, T) y) {
|
||||
return Equals(x.Item1, y.Item1);
|
||||
public bool Equals(Change<T> x, Change<T> y) {
|
||||
return Equals(x.New, y.New);
|
||||
}
|
||||
|
||||
public int GetHashCode(T obj) {
|
||||
return _key(obj).GetHashCode();
|
||||
}
|
||||
|
||||
public int GetHashCode((T, T) obj) {
|
||||
return GetHashCode(obj.Item1);
|
||||
public int GetHashCode(Change<T> c) {
|
||||
return GetHashCode(c.New);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +206,7 @@ namespace bts.api.core {
|
||||
internal TableUpdate(
|
||||
ImmutableDictionary<TKey, T> init,
|
||||
IEnumerable<T> added,
|
||||
IEnumerable<(T,T)> changed,
|
||||
IEnumerable<Change<T>> changed,
|
||||
IEnumerable<T> removed) {
|
||||
_state = init;
|
||||
this.added = added;
|
||||
@@ -169,7 +216,7 @@ namespace bts.api.core {
|
||||
|
||||
public IReadOnlyDictionary<TKey, T> state { get { return _state; } }
|
||||
public IEnumerable<T> added { get; }
|
||||
public IEnumerable<(T New,T Old)> changes { get; }
|
||||
public IEnumerable<Change<T>> changes { get; }
|
||||
public IEnumerable<T> changed => changes.Select(c => c.New);
|
||||
|
||||
public IEnumerable<T> removed { get; }
|
||||
@@ -185,7 +232,7 @@ namespace bts.api.core {
|
||||
}
|
||||
|
||||
internal TableUpdate<T, TKey> as_snapshot() {
|
||||
return new TableUpdate<T, TKey>(_state, _state.Values.ToList(), new (T,T)[0], new T[0]);
|
||||
return new TableUpdate<T, TKey>(_state, _state.Values.ToList(), new Change<T>[0], new T[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +255,7 @@ namespace bts.api.core {
|
||||
if (raw.is_reset) {
|
||||
var removed = state.Values.ToList();
|
||||
state.Clear();
|
||||
return new Update<T, TKey>(new T[0], new T[0], new (T,T)[0], removed, key_extractor);
|
||||
return new Update<T, TKey>(new T[0], new T[0], new Change<T>[0], removed, key_extractor);
|
||||
}
|
||||
else {
|
||||
var removed = new List<T>(raw.removed_keys.Count);
|
||||
@@ -222,11 +269,11 @@ namespace bts.api.core {
|
||||
for (int x = 0; x < raw.added_items.Count; ++x) {
|
||||
state[raw.added_keys[x]] = raw.added_items[x];
|
||||
}
|
||||
List<(T, T)> changes = new List<(T, T)>(raw.changed_items.Count);
|
||||
var changes = new List<Change<T>>(raw.changed_items.Count);
|
||||
for (int x = 0; x < raw.changed_items.Count; ++x) {
|
||||
var old = state[raw.changed_keys[x]];
|
||||
state[raw.changed_keys[x]] = raw.changed_items[x];
|
||||
changes.Add((raw.changed_items[x], old));
|
||||
changes.Add(new Change<T>(old, raw.changed_items[x]));
|
||||
}
|
||||
return new Update<T, TKey>(state.Values.ToList(), raw.added_items.ToList(), changes, removed, key_extractor);
|
||||
}
|
||||
@@ -235,7 +282,7 @@ namespace bts.api.core {
|
||||
|
||||
public static IObservable<TableUpdate<T,TKey>> Table<T,TKey>(this IObservable<Update<T,TKey>> source) where TKey : IEquatable<TKey> =>
|
||||
source.Scan(
|
||||
new TableUpdate<T,TKey>(ImmutableDictionary<TKey,T>.Empty, new T[0], new (T,T)[0], new T[0]),
|
||||
new TableUpdate<T,TKey>(ImmutableDictionary<TKey,T>.Empty, new T[0], new Change<T>[0], new T[0]),
|
||||
(table, update) => TableUpdate<T,TKey>.update(table,update));
|
||||
|
||||
// Fold updates and emit at max 1/interval
|
||||
|
||||
@@ -31,7 +31,8 @@ namespace bts {
|
||||
Mercury,
|
||||
Testing,
|
||||
Latency,
|
||||
DataFlow
|
||||
DataFlow,
|
||||
Plugin
|
||||
// Please keep this list in sync with logging.h/logging.cpp
|
||||
}
|
||||
readonly struct Logger {
|
||||
|
||||
@@ -72,7 +72,12 @@ namespace mbts.co2
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool get_last_trade(ref ulong time, out NativePriceSize ps, out DateTime timestamp, out ulong total_volume) {
|
||||
public bool get_last_trade(ref ulong time, out NativePriceSize ps, out ulong total_volume) {
|
||||
total_volume = _cold->total_volume;
|
||||
return (_cold->last_trade.load_if_new(ref time, out ps));
|
||||
}
|
||||
|
||||
public bool get_last_trade(ref ulong time, out NativePriceSize ps, out utils.LLDateTime timestamp, out ulong total_volume) {
|
||||
timestamp = _cold->last_trade_time;
|
||||
total_volume = _cold->total_volume;
|
||||
return (_cold->last_trade.load_if_new(ref time, out ps));
|
||||
@@ -88,15 +93,15 @@ namespace mbts.co2
|
||||
public ulong total_volume { get { return _cold->total_volume; } }
|
||||
|
||||
public double settlement_price { get { return _cold->settlement_price;} }
|
||||
public DateTime settlement_date { get { return _cold->settlement_date;} }
|
||||
public utils.LLDate settlement_date { get { return _cold->settlement_date;} }
|
||||
public double previous_settlement_price { get { return _cold->previous_settlement_price;} }
|
||||
public DateTime previous_settlement_date { get { return _cold->previous_settlement_date;} }
|
||||
public utils.LLDate previous_settlement_date { get { return _cold->previous_settlement_date;} }
|
||||
|
||||
public double open_price { get { return _cold->open_price;} }
|
||||
public DateTime open_date { get { return _cold->open_date; } }
|
||||
public utils.LLDate open_date { get { return _cold->open_date; } }
|
||||
|
||||
public double close_price { get { return _cold->close_price;} }
|
||||
public DateTime close_date { get { return _cold->close_date; } }
|
||||
public utils.LLDate close_date { get { return _cold->close_date; } }
|
||||
public double session_high { get { return _cold->session_high;} }
|
||||
public double session_low { get { return _cold->session_low; } }
|
||||
public double open_interest { get { return _cold->open_interest; } }
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace bts.utils {
|
||||
public static IEqualityComparer<T?> CreateNullable<T>(Func<T, T, bool> equals) where T : struct =>
|
||||
new AnonymousEqualityComparer<T?>(nullable_equals);
|
||||
|
||||
public static IEqualityComparer<T> null_check_wrapper<T>(IEqualityComparer<T> comparer) where T : class =>
|
||||
new AnonymousEqualityComparer<T>((a, b) => NullCheckEquals(a, b, comparer.Equals), comparer.GetHashCode);
|
||||
|
||||
public static bool safe_sequence_equals<T>(IEnumerable<T> source, IEnumerable<T> other) =>
|
||||
NullCheckEquals(source, other, (a, b) => a.SequenceEqual(b));
|
||||
|
||||
|
||||
@@ -210,19 +210,24 @@ namespace mbts.co2.tests
|
||||
Assert.IsTrue(ask.size == 202);
|
||||
|
||||
time = 0;
|
||||
DateTime trade_date;
|
||||
ulong total_volume;
|
||||
NativePriceSize last_trade;
|
||||
Assert.IsTrue(handle.get_last_trade(ref time, out last_trade, out trade_date, out total_volume));
|
||||
Assert.IsTrue(handle.get_last_trade(ref time, out NativePriceSize last_trade, out utils.LLDateTime ll_trade_date, out ulong total_volume));
|
||||
// trade date
|
||||
DateTime trade_date = ll_trade_date;
|
||||
Assert.IsTrue(last_trade.price == 5.5 && last_trade.size == 505);
|
||||
Assert.IsTrue(trade_date.Year == 2015 && trade_date.Month == 9 && trade_date.Day == 22);
|
||||
Assert.IsTrue(total_volume == 4200);
|
||||
Assert.IsTrue(handle.settlement_date.Year == 2000 && handle.settlement_date.Day == 9 && handle.settlement_date.Month == 8);
|
||||
// settlement date
|
||||
DateTime settlement_dt = handle.settlement_date;
|
||||
Assert.IsTrue(settlement_dt.Year == 2000 && settlement_dt.Day == 9 && settlement_dt.Month == 8);
|
||||
Assert.IsTrue(handle.settlement_price == 6.6);
|
||||
Assert.IsTrue(handle.open_price == 7.7);
|
||||
Assert.IsTrue(handle.open_date.Year == 2001 && handle.open_date.Month == 1 && handle.open_date.Day == 2);
|
||||
// open date
|
||||
DateTime open_dt = handle.open_date;
|
||||
Assert.IsTrue(open_dt.Year == 2001 && open_dt.Month == 1 && open_dt.Day == 2);
|
||||
Assert.IsTrue(handle.close_price == 8.8);
|
||||
Assert.IsTrue(handle.close_date.Year == 2002 && handle.close_date.Month == 3 && handle.close_date.Day == 4);
|
||||
// close date
|
||||
DateTime close_dt = handle.close_date;
|
||||
Assert.IsTrue(close_dt.Year == 2002 && close_dt.Month == 3 && close_dt.Day == 4);
|
||||
|
||||
Assert.IsTrue(handle.session_high == 9.9);
|
||||
Assert.IsTrue(handle.session_low == 10.1);
|
||||
|
||||
@@ -227,5 +227,15 @@ namespace mbts.api.Test {
|
||||
await validate_naggle(raw);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void test_merge_begin_end_state() {
|
||||
int key(string s) => s[0];
|
||||
var empty = new string[0];
|
||||
var a2 = new Update<string, int>(new[] { "a2" }, empty, new[] { new Change<string>("a1", "a2") }, empty, key);
|
||||
var a3 = new Update<string, int>(new[] { "a3" }, empty, new[] { new Change<string>("a2", "a3") }, empty, key);
|
||||
var merged = a2.merge(a3);
|
||||
Assert.SequenceEqual(new[] { new Change<string>("a1", "a3") }, merged.changes);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,5 @@ namespace sparkcmd {
|
||||
ConsoleCommandDispatcher.DispatchCommand(commands, args, Console.Out);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,8 @@
|
||||
<Authors>Blue Trading Systems</Authors>
|
||||
<Company>Blue Trading Systems</Company>
|
||||
<Product>Spark</Product>
|
||||
<Platforms>x64</Platforms>
|
||||
<Platform>x64</Platform>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<Version>1.0.0</Version>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1 +1 @@
|
||||
set(sources /home/ppinto/Dropbox/bts/spark/src/data_files/files/Onixs.BTS.lic;/home/ppinto/Dropbox/bts/spark/src/data_files/files/cert_secure_logon.txt)
|
||||
set(sources /home/ppinto/Dropbox/bts/spark/src/data_files/files/Onixs.BTS.lic;/home/ppinto/Dropbox/bts/spark/src/data_files/files/Onixs.BTS.lic.orig;/home/ppinto/Dropbox/bts/spark/src/data_files/files/cert_secure_logon.txt)
|
||||
@@ -1 +1 @@
|
||||
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/services/AdminService.proto;api/services/ApiUnitTestService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/services/UserService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/Executor.conf;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cpp_config.conf;config/defaults/dynamic_orders.conf;config/defaults/edge.conf;config/defaults/expiration_display_offset.conf;config/defaults/jetfix.conf;config/defaults/logging.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cpp_config.proto;config/protos/dynamic_orders.proto;config/protos/environment.proto;config/protos/expiration_display_offset.proto;config/protos/jetfix.proto;config/protos/logging.proto;config/protos/orders_fills_cleanup.proto;config/protos/quickbus_cfg.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPriceLantencyTester.cpp;md/Diag/ShmDumper.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MDRecoverableConsumer.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/md2_tests.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/Dispatcher.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/datetime.cpp;utils/download.cpp;utils/file_utils.cpp;utils/init_spark_lib.cpp;utils/is_unittest_environment.cpp)
|
||||
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/services/AdminService.proto;api/services/ApiUnitTestService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/services/UserService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/Executor.conf;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/dynamic_orders.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/logging.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/dynamic_orders.proto;config/protos/environment.proto;config/protos/jetfix.proto;config/protos/logging.proto;config/protos/orders_fills_cleanup.proto;config/protos/quickbus_cfg.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;jetfix/codec/FIXArray.cpp;jetfix/common/OutFIX.cpp;jetfix/connection/AsyncReader.cpp;jetfix/connection/IConnection.cpp;jetfix/connection/SocketConnection.cpp;jetfix/gateway/CoreGateway.cpp;jetfix/gateway/JetFIXGateway.cpp;jetfix/gateway/Session.cpp;jetfix/store/FIXFileStore.cpp;jetfix/store/session_name.cpp;jetfix/tests/async_reader_tests.cpp;jetfix/tests/decoding_tests.cpp;jetfix/tests/fix_encoding_stream_tests.cpp;jetfix/tests/fix_fragment_tests.cpp;jetfix/tests/jetfix_performance_tests.cpp;jetfix/tests/sample_fix.cpp;jetfix/tests/store_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPriceLantencyTester.cpp;md/Diag/ShmDumper.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MDRecoverableConsumer.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/md2_tests.cpp;md/test/synthetic_book_merge_tests.cpp;mercury/actors/Actor.cpp;mercury/broker/AsyncEventBroker.cpp;mercury/broker/CoreEventBroker.cpp;mercury/broker/IEventBroker.cpp;mercury/events/TimerEvent.cpp;mercury/mercury_utils/Executor.cpp;mercury/mercury_utils/IPollableActor.cpp;mercury/mercury_utils/mercury_common.cpp;mercury/synopsis/SynopsisBuilder.cpp;mercury/topics/ITopic.cpp;metrics/metrics.cpp;metrics/system_metrics.cpp;orderman/actors/AsyncFactory.cpp;orderman/actors/ExecutionGateway.cpp;orderman/actors/FillStore.cpp;orderman/actors/OrderStore.cpp;orderman/actors/SODPosition.cpp;orderman/actors/SecuritySrc.cpp;orderman/actors/ServiceBridge.cpp;orderman/actors/order_manager/OrderBuilder.cpp;orderman/actors/order_manager/OrderManager.cpp;orderman/actors/order_manager/OrderServicesData.cpp;orderman/events/CancelRejectEvent.cpp;orderman/events/NewExecutionReportEvent.cpp;orderman/limiter/LimitStore.cpp;orderman/limiter/Limiter.cpp;orderman/limiter/ProductLimitNode.cpp;orderman/limiter/ProductLimitTree.cpp;orderman/limiter/SecurityLimitNode.cpp;orderman/limiter/SecurityLimitTree.cpp;orderman/limiter/tests/limit_tests.cpp;orderman/order_factory/DynamicOrderRegistry.cpp;ordermanLine truncated
|
||||
@@ -1,34 +1,40 @@
|
||||
#include "lib/api/services/AdminService.server.pb.h"
|
||||
#include "lib/api/service_helpers/AdminServiceUtils.h"
|
||||
#include "lib/md/get_symbols.h"
|
||||
#include "lib/config/protos/cme_reference_data.pb.h"
|
||||
#include "lib/config/protos/jetfix.pb.h"
|
||||
#include "lib/config/config.h"
|
||||
#include <sstream>
|
||||
|
||||
namespace bts{
|
||||
namespace admin{
|
||||
////////////////////////////////////////////
|
||||
// connection accessors ////////////////////
|
||||
////////////////////////////////////////////
|
||||
uint32_t AdminServiceUtils::find_max_connection_id (const bts::api::admin::AdminData& data){
|
||||
uint32_t AdminServiceUtils::find_max_connection_id (const AdminData& data){
|
||||
uint32_t rv = 0;
|
||||
for(const auto &conn : data.connections())
|
||||
if (conn.id() > rv)
|
||||
rv = conn.id();
|
||||
return rv;
|
||||
}
|
||||
const bts::api::admin::ExchangeConnection* AdminServiceUtils::find_connection(const bts::api::admin::AdminData& data,
|
||||
const std::string& connection_name){
|
||||
const ExchangeConnection* AdminServiceUtils::find_connection(
|
||||
const AdminData& data,
|
||||
const std::string& connection_name){
|
||||
for(const auto& connection : data.connections())
|
||||
if(connection.name()==connection_name)
|
||||
return &connection;
|
||||
return nullptr;
|
||||
}
|
||||
bool AdminServiceUtils::has_exchange(const bts::api::admin::ExchangeConnection& conn,
|
||||
bts::api::Venue exchange){
|
||||
bool AdminServiceUtils::has_exchange(const ExchangeConnection& conn,
|
||||
api::Venue exchange){
|
||||
bool rv = false;
|
||||
switch(exchange)
|
||||
{
|
||||
case api::Venue::VENUE_GLBX:
|
||||
rv = conn.has_cme_connection() &&
|
||||
(conn.cme_connection().has_cgw_connection() || conn.cme_connection().has_msgw_connection());
|
||||
(conn.cme_connection().has_cgw_connection() ||
|
||||
conn.cme_connection().has_msgw_connection());
|
||||
break;
|
||||
case api::Venue::VENUE_UNSET:
|
||||
case api::Venue::VENUE_SIM:
|
||||
@@ -870,6 +876,89 @@ void AdminServiceUtils::validate_user_exchange_data (const bts::api::admin::BTSU
|
||||
}
|
||||
}
|
||||
}
|
||||
void AdminServiceUtils::get_md_entitlement_report(const AdminData& admin_data,
|
||||
std::vector<MDEntitlementReportUnit>& entitlements){
|
||||
for (const auto& user : admin_data.users()){
|
||||
const CMEUserData* cme_data=AdminServiceUtils::get_user_cme_data(user,
|
||||
admin_data);
|
||||
if(cme_data!=nullptr){
|
||||
for (const auto& cme_mic_data : cme_data->md_permissions()){
|
||||
MDEntitlementReportUnit rv=get_cme_md_entitlement_unit(user.name(),
|
||||
cme_mic_data);
|
||||
entitlements.push_back(rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
MDEntitlementReportUnit AdminServiceUtils::get_cme_md_entitlement_unit(
|
||||
const std::string& user,
|
||||
const CMEMicData& cme_mic_data){
|
||||
MDEntitlementReportUnit rv;
|
||||
rv.set_user(user);
|
||||
rv.set_exchange("GLBX");
|
||||
switch(cme_mic_data.mic())
|
||||
{
|
||||
case api::CMEMics::CME:
|
||||
rv.set_mic("CME");
|
||||
break;
|
||||
case api::CMEMics::NYMEX:
|
||||
rv.set_mic("NYMEX");
|
||||
break;
|
||||
case api::CMEMics::CBT:
|
||||
rv.set_mic("CBT");
|
||||
break;
|
||||
case api::CMEMics::COMEX:
|
||||
rv.set_mic("COMEX");
|
||||
break;
|
||||
case api::CMEMics::MGE:
|
||||
rv.set_mic("MGE");
|
||||
break;
|
||||
case api::CMEMics::DME:
|
||||
rv.set_mic("DME");
|
||||
break;
|
||||
case api::CMEMics::NYMSW:
|
||||
rv.set_mic("NYMSW");
|
||||
break;
|
||||
case api::CMEMics::FXS:
|
||||
rv.set_mic("FXS");
|
||||
break;
|
||||
case api::CMEMics::UNSET:
|
||||
case api::CMEMics::CMEMics_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case api::CMEMics::CMEMics_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
rv.set_mic("");
|
||||
break;
|
||||
}
|
||||
rv.set_enabled(cme_mic_data.enabled());
|
||||
std::ostringstream key;
|
||||
key << rv.user() << rv.exchange() << rv.mic();
|
||||
rv.set_record_id(key.str());
|
||||
return rv;
|
||||
}
|
||||
void AdminServiceUtils::get_user_symbol_permissions(const AdminData& data,
|
||||
const BTSUser& user,
|
||||
std::vector<UserSymbolMDPermissionUnit>& rv){
|
||||
std::map<api::CMEMics, bool> mic_perm_map;
|
||||
auto exchange = api::Venue::VENUE_GLBX;
|
||||
const CMEUserData* cme_data=get_user_cme_data(user,data);
|
||||
if(cme_data!=nullptr)
|
||||
for(const auto& mic_data : cme_data->md_permissions())
|
||||
if(mic_data.enabled())
|
||||
mic_perm_map[mic_data.mic()]=true;
|
||||
const auto& cme_symb_mics = config::get<config::CmeSymbolMics>().cme_mic();
|
||||
for(auto it=cme_symb_mics.begin();it!=cme_symb_mics.end();it++){
|
||||
const std::string& symbol=it->first;
|
||||
api::CMEMics mic=it->second;
|
||||
UserSymbolMDPermissionUnit u;
|
||||
std::ostringstream key;
|
||||
key << exchange << user.name() << symbol;
|
||||
u.set_record_id(key.str());
|
||||
u.set_user(user.name());
|
||||
u.set_exchange(exchange);
|
||||
u.set_symbol(symbol);
|
||||
u.set_enabled(mic_perm_map.find(mic)!=mic_perm_map.end());
|
||||
rv.push_back(u);
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////
|
||||
// user mutators ///////////////////////////
|
||||
////////////////////////////////////////////
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
#include "lib/api/services/AdminService.server.pb.h"
|
||||
#include "lib/api/services/OrderService.server.pb.h"
|
||||
#include "lib/domain_model/Security.h"
|
||||
#include "lib/config/protos/jetfix.pb.h"
|
||||
#include "lib/config/config.h"
|
||||
|
||||
namespace bts{
|
||||
namespace admin{
|
||||
|
||||
using namespace bts::api::admin;
|
||||
using namespace bts::api::orderman;
|
||||
|
||||
class AdminServiceUtils{
|
||||
public:
|
||||
////////////////////////////////////////////
|
||||
@@ -17,233 +18,286 @@ public:
|
||||
////////////////////////////////////////////
|
||||
// finds the max id out of all the existing connections
|
||||
// (todo: deleted connections)
|
||||
static uint32_t find_max_connection_id (const bts::api::admin::AdminData& data);
|
||||
static uint32_t find_max_connection_id (const AdminData& data);
|
||||
// finds a connection by name and returns a mutable pointer to it
|
||||
static const bts::api::admin::ExchangeConnection* find_connection(const bts::api::admin::AdminData& data,
|
||||
const std::string& connection_name);
|
||||
static const ExchangeConnection* find_connection(const AdminData& data,
|
||||
const std::string& connection_name);
|
||||
// finds the presence of an exchange in a connection
|
||||
static bool has_exchange(const bts::api::admin::ExchangeConnection& conn,
|
||||
static bool has_exchange(const ExchangeConnection& conn,
|
||||
bts::api::Venue exchange);
|
||||
// finds the default connections for an exchange
|
||||
// in a given account
|
||||
static const bts::api::admin::ExchangeConnection* find_default_account_connection(const bts::api::admin::AdminData& data,
|
||||
const bts::api::admin::BTSAccount& account,
|
||||
bts::api::Venue exchange);
|
||||
static const bts::api::admin::ExchangeConnection* resolve_cme_connection(const bts::api::admin::AdminData& data,
|
||||
const bts::api::admin::BTSAccount& account,
|
||||
const bts::api::Security& sec);
|
||||
static const bts::api::admin::ExchangeConnection* resolve_sim_connection(const bts::api::admin::AdminData& data,
|
||||
const bts::api::admin::BTSAccount& account,
|
||||
const bts::api::Security& sec);
|
||||
static const bts::api::admin::ExchangeConnection* resolve_connection(const bts::api::admin::AdminData& data,
|
||||
const bts::api::admin::BTSAccount& account,
|
||||
const bts::api::Security& sec);
|
||||
static const ExchangeConnection* find_default_account_connection(
|
||||
const AdminData& data,
|
||||
const BTSAccount& account,
|
||||
bts::api::Venue exchange);
|
||||
static const ExchangeConnection* resolve_cme_connection(
|
||||
const AdminData& data,
|
||||
const BTSAccount& account,
|
||||
const api::Security& sec);
|
||||
static const ExchangeConnection* resolve_sim_connection(
|
||||
const AdminData& data,
|
||||
const BTSAccount& account,
|
||||
const api::Security& sec);
|
||||
static const ExchangeConnection* resolve_connection(
|
||||
const AdminData& data,
|
||||
const BTSAccount& account,
|
||||
const bts::api::Security& sec);
|
||||
////////////////////////////////////////////
|
||||
// connection mutators /////////////////////
|
||||
////////////////////////////////////////////
|
||||
// adds a new connection (does not check for name uniqueness)
|
||||
static bts::api::admin::ExchangeConnection* add_connection(bts::api::admin::AdminData& data,
|
||||
const bts::api::admin::ExchangeConnection& new_connection);
|
||||
static ExchangeConnection* add_connection(AdminData& data,
|
||||
const ExchangeConnection& new_connection);
|
||||
// reads the connections from config and fills in the
|
||||
// admin data (with names only)
|
||||
static void fill_connections_from_config(bts::api::admin::AdminData& admin_data);
|
||||
static void fill_connections_from_config(AdminData& admin_data);
|
||||
////////////////////////////////////////////
|
||||
// account accessors ///////////////////////
|
||||
////////////////////////////////////////////
|
||||
// finds the account from the name and returns
|
||||
// a mutable pointer to the account
|
||||
static bts::api::admin::BTSAccount* find_account (bts::api::admin::AdminData& data, const std::string& acct_name, bool include_deleted=false);
|
||||
static BTSAccount* find_account (AdminData& data,
|
||||
const std::string& acct_name,
|
||||
bool include_deleted=false);
|
||||
// same as above for const pointer
|
||||
static const bts::api::admin::BTSAccount* find_account (const bts::api::admin::AdminData& data, const std::string& acct_name, bool include_deleted=false);
|
||||
static const BTSAccount* find_account (const AdminData& data,
|
||||
const std::string& acct_name,
|
||||
bool include_deleted=false);
|
||||
// finds the account from the id and returns
|
||||
// a mutable pointer to the account
|
||||
static bts::api::admin::BTSAccount* find_account (bts::api::admin::AdminData& data, uint32_t id, bool include_deleted=false);
|
||||
static BTSAccount* find_account (AdminData& data,
|
||||
uint32_t id,
|
||||
bool include_deleted=false);
|
||||
// like above but returns a const pointer
|
||||
static const bts::api::admin::BTSAccount* find_account (const bts::api::admin::AdminData& data, uint32_t id, bool include_deleted=false);
|
||||
static const BTSAccount* find_account (const AdminData& data,
|
||||
uint32_t id,
|
||||
bool include_deleted=false);
|
||||
// this function is an indirection layer for account access
|
||||
// so deletions are dealt in a more deliberate manner
|
||||
static std::vector<const bts::api::admin::BTSAccount*> accounts (const bts::api::admin::AdminData& data, bool include_deleted);
|
||||
static std::vector<bts::api::admin::BTSAccount*> accounts_mutable (bts::api::admin::AdminData& data, bool include_deleted);
|
||||
static std::vector<const BTSAccount*> accounts (const AdminData& data,
|
||||
bool include_deleted);
|
||||
static std::vector<BTSAccount*> accounts_mutable (AdminData& data,
|
||||
bool include_deleted);
|
||||
// finds the max id amongts all the existing accounts
|
||||
static uint32_t find_max_acct_id (const bts::api::admin::AdminData& data);
|
||||
static uint32_t find_max_acct_id (const AdminData& data);
|
||||
// gets the account data for cme (and goes up the hierarchy
|
||||
// if needed)
|
||||
static const bts::api::admin::CMEAccountData* get_account_cme_data(const bts::api::admin::BTSAccount& account,
|
||||
const bts::api::admin::AdminData& data);
|
||||
static const bts::api::admin::SIMAccountData* get_account_sim_data(const bts::api::admin::BTSAccount& account,
|
||||
const bts::api::admin::AdminData& data);
|
||||
static const CMEAccountData* get_account_cme_data(const BTSAccount& account,
|
||||
const AdminData& data);
|
||||
static const SIMAccountData* get_account_sim_data(const BTSAccount& account,
|
||||
const AdminData& data);
|
||||
// returns true if an account has a connection
|
||||
bool static account_has_connection(const bts::api::admin::BTSAccount& account, const std::string& connection_name);
|
||||
bool static account_has_connection(const BTSAccount& account,
|
||||
const std::string& connection_name);
|
||||
// finds the external/clearing account associated
|
||||
// with an account
|
||||
static std::string find_account_exchange_account (const bts::api::admin::AdminData& data,
|
||||
const bts::api::admin::BTSAccount& account,
|
||||
api::Venue exchange,
|
||||
bts::api::admin::AdminServiceOperationResult& out_result);
|
||||
static std::string find_account_exchange_account (const AdminData& data,
|
||||
const BTSAccount& account,
|
||||
api::Venue exchange,
|
||||
AdminServiceOperationResult& out_result);
|
||||
// returns a map of the accounts vs their 'is_active'
|
||||
static std::map<uint32_t,bool> accounts_map(const bts::api::admin::AdminData& admin_data);
|
||||
static std::map<uint32_t,bool> accounts_map(const AdminData& admin_data);
|
||||
// validates that the update to the account is valid
|
||||
static void validate_account_update (const bts::api::admin::AdminData& admin_data,
|
||||
const bts::api::admin::BTSAccount& updated_account,
|
||||
bts::api::admin::AdminServiceOperationResult& result);
|
||||
static void validate_account_update (const AdminData& admin_data,
|
||||
const BTSAccount& updated_account,
|
||||
AdminServiceOperationResult& result);
|
||||
// validates that the account exchange changes are valid
|
||||
// (ex > 12 characters for accounts at CME)
|
||||
static void validate_account_exchange_data (const bts::api::admin::BTSAccount& account,
|
||||
bts::api::admin::AdminServiceOperationResult& out_result);
|
||||
static bts::api::orderman::RoutingRecord get_routing_record(const bts::api::admin::AdminData& data,
|
||||
const std::string& account_name,
|
||||
const std::string& user_name,
|
||||
const bts::api::Security& sec,
|
||||
bts::api::admin::AdminServiceOperationResult& out_result);
|
||||
static bts::api::orderman::RoutingRecord get_routing_record(const bts::api::admin::AdminData& data,
|
||||
uint32_t account_id,
|
||||
uint32_t user_id,
|
||||
const bts::api::Security& sec,
|
||||
bts::api::admin::AdminServiceOperationResult& out_result);
|
||||
static void validate_account_exchange_data (const BTSAccount& account,
|
||||
AdminServiceOperationResult& out_result);
|
||||
static RoutingRecord get_routing_record(
|
||||
const AdminData& data,
|
||||
const std::string& account_name,
|
||||
const std::string& user_name,
|
||||
const bts::api::Security& sec,
|
||||
AdminServiceOperationResult& out_result);
|
||||
static RoutingRecord get_routing_record(const AdminData& data,
|
||||
uint32_t account_id,
|
||||
uint32_t user_id,
|
||||
const bts::api::Security& sec,
|
||||
AdminServiceOperationResult& out_result);
|
||||
////////////////////////////////////////////
|
||||
// account mutators ////////////////////////
|
||||
////////////////////////////////////////////
|
||||
static bts::api::admin::BTSAccount* create_account(bts::api::admin::AdminData& data,
|
||||
uint32_t parent_account_id,
|
||||
const std::string& account_name,
|
||||
const std::string& description,
|
||||
bool is_active,
|
||||
bts::api::admin::AdminServiceCreateAccountResult& result);
|
||||
static BTSAccount* create_account(AdminData& data,
|
||||
uint32_t parent_account_id,
|
||||
const std::string& account_name,
|
||||
const std::string& description,
|
||||
bool is_active,
|
||||
AdminServiceCreateAccountResult& result);
|
||||
// writes over the account data completely
|
||||
static void update_account(bts::api::admin::AdminData& data,
|
||||
const bts::api::admin::BTSAccount& updated_account,
|
||||
bts::api::admin::AdminServiceOperationResult& result);
|
||||
static void delete_account (bts::api::admin::AdminData& admin_data,
|
||||
const bts::api::admin::IDAPIArgument& id,
|
||||
bts::api::admin::AdminServiceOperationResult& result);
|
||||
static void set_account_exchange_data(bts::api::admin::BTSAccount* account,
|
||||
const bts::api::admin::ExchangeAccountData& exchange_data);
|
||||
static void update_account(AdminData& data,
|
||||
const BTSAccount& updated_account,
|
||||
AdminServiceOperationResult& result);
|
||||
static void delete_account (AdminData& admin_data,
|
||||
const IDAPIArgument& id,
|
||||
AdminServiceOperationResult& result);
|
||||
static void set_account_exchange_data(BTSAccount* account,
|
||||
const ExchangeAccountData& exchange_data);
|
||||
// this is not a generally useful function but since
|
||||
// connection are in config, this cleans up the account's
|
||||
// connections and syncs it with the list in AdminData
|
||||
static void sync_account_connections(const bts::api::admin::AdminData& data,
|
||||
bts::api::admin::BTSAccount& account);
|
||||
static void sync_account_connections(const AdminData& data,
|
||||
BTSAccount& account);
|
||||
////////////////////////////////////////////
|
||||
// group accessors /////////////////////////
|
||||
////////////////////////////////////////////
|
||||
// given an id, finds the mutable pointer to a group
|
||||
static bts::api::admin::BTSUserGroup* find_group (bts::api::admin::AdminData& data, uint32_t id);
|
||||
static BTSUserGroup* find_group (AdminData& data, uint32_t id);
|
||||
// given an id, finds the const pointer to a group
|
||||
static const bts::api::admin::BTSUserGroup* const find_group (const bts::api::admin::AdminData& data, uint32_t id);
|
||||
static const BTSUserGroup* const find_group (const AdminData& data,
|
||||
uint32_t id);
|
||||
// given a name, finds the mutable pointer to a group
|
||||
static bts::api::admin::BTSUserGroup* find_group (bts::api::admin::AdminData& data, const std::string& group_name);
|
||||
static BTSUserGroup* find_group (AdminData& data,
|
||||
const std::string& group_name);
|
||||
// finds the max id out of all the groups
|
||||
static uint32_t find_max_group_id (const bts::api::admin::AdminData& data);
|
||||
static uint32_t find_max_group_id (const AdminData& data);
|
||||
// travels up the group tree until it finds a populated cme data
|
||||
static const bts::api::admin::CMEUserData* get_group_cme_data(const bts::api::admin::BTSUserGroup& group,
|
||||
const bts::api::admin::AdminData& data);
|
||||
static const bts::api::admin::SIMUserData* get_group_sim_data(const bts::api::admin::BTSUserGroup& group,
|
||||
const bts::api::admin::AdminData& data);
|
||||
static const bts::api::admin::UserAccountPermissions* const get_group_user_permissions (const bts::api::admin::AdminData& admin_data,
|
||||
uint32_t group_id);
|
||||
static const CMEUserData* get_group_cme_data(const BTSUserGroup& group,
|
||||
const AdminData& data);
|
||||
static const SIMUserData* get_group_sim_data(const BTSUserGroup& group,
|
||||
const AdminData& data);
|
||||
static const UserAccountPermissions* const get_group_user_permissions (
|
||||
const bts::api::admin::AdminData& admin_data,
|
||||
uint32_t group_id);
|
||||
////////////////////////////////////////////
|
||||
// group mutators/ /////////////////////////
|
||||
////////////////////////////////////////////
|
||||
static bts::api::admin::BTSUserGroup* create_group(bts::api::admin::AdminData& data,
|
||||
uint32_t parent_group_id,
|
||||
const std::string& group_name,
|
||||
bts::api::admin::AdminServiceOperationResult& result);
|
||||
static BTSUserGroup* create_group(AdminData& data,
|
||||
uint32_t parent_group_id,
|
||||
const std::string& group_name,
|
||||
AdminServiceOperationResult& result);
|
||||
////////////////////////////////////////////
|
||||
// user accessors //////////////////////////
|
||||
////////////////////////////////////////////
|
||||
static bts::api::admin::BTSUser* find_user (bts::api::admin::AdminData& data, const std::string& user_name, bool include_deleted=false);
|
||||
static const bts::api::admin::BTSUser* find_user (const bts::api::admin::AdminData& data, const std::string& user_name, bool include_deleted=false);
|
||||
static bts::api::admin::BTSUser* find_user (bts::api::admin::AdminData& data, uint32_t id, bool include_deleted=false);
|
||||
static const bts::api::admin::BTSUser* const find_user (const bts::api::admin::AdminData& data, uint32_t id, bool include_deleted=false);
|
||||
static std::vector<const bts::api::admin::BTSUser*> users (const bts::api::admin::AdminData& data, bool include_deleted);
|
||||
static std::vector<bts::api::admin::BTSUser*> users_mutable (bts::api::admin::AdminData& data, bool include_deleted);
|
||||
static uint32_t find_max_user_id (const bts::api::admin::AdminData& data);
|
||||
static const bts::api::admin::CMEUserData* get_user_cme_data(const bts::api::admin::BTSUser& user,
|
||||
const bts::api::admin::AdminData& data);
|
||||
static const bts::api::admin::SIMUserData* get_user_sim_data(const bts::api::admin::BTSUser& user,
|
||||
const bts::api::admin::AdminData& data);
|
||||
static BTSUser* find_user (AdminData& data,
|
||||
const std::string& user_name,
|
||||
bool include_deleted=false);
|
||||
static const BTSUser* find_user (const AdminData& data,
|
||||
const std::string& user_name,
|
||||
bool include_deleted=false);
|
||||
static BTSUser* find_user (AdminData& data,
|
||||
uint32_t id,
|
||||
bool include_deleted=false);
|
||||
static const BTSUser* const find_user (const AdminData& data,
|
||||
uint32_t id,
|
||||
bool include_deleted=false);
|
||||
static std::vector<const BTSUser*> users (const AdminData& data,
|
||||
bool include_deleted);
|
||||
static std::vector<BTSUser*> users_mutable (AdminData& data,
|
||||
bool include_deleted);
|
||||
static uint32_t find_max_user_id (const AdminData& data);
|
||||
static const CMEUserData* get_user_cme_data(const BTSUser& user,
|
||||
const AdminData& data);
|
||||
static const SIMUserData* get_user_sim_data(const BTSUser& user,
|
||||
const AdminData& data);
|
||||
// finds the "exchange user" (ex: "operator_id" at CME or "authorized_trader"
|
||||
// at ICE) for a user
|
||||
static std::string find_user_exchange_id (const bts::api::admin::AdminData& data,
|
||||
const bts::api::admin::BTSUser& user,
|
||||
api::Venue exchange,
|
||||
bts::api::admin::AdminServiceOperationResult& out_result);
|
||||
static std::pair<const bts::api::admin::BTSAccount*, const bts::api::admin::BTSUser*>
|
||||
find_user_account_matches (const bts::api::admin::AdminData& admin_data,
|
||||
const std::string& connection, const std::string& exchange_account,
|
||||
static std::string find_user_exchange_id (
|
||||
const AdminData& data,
|
||||
const BTSUser& user,
|
||||
api::Venue exchange,
|
||||
AdminServiceOperationResult& out_result);
|
||||
static std::pair<const BTSAccount*, const BTSUser*>
|
||||
find_user_account_matches (const AdminData& admin_data,
|
||||
const std::string& connection,
|
||||
const std::string& exchange_account,
|
||||
const std::string& exchange_user,
|
||||
api::Venue exchange);
|
||||
// for a given user finds the account permissions (if permissions are
|
||||
// derived from the group, it traverses the group hierarcy to find the
|
||||
// correct permissions.
|
||||
static const bts::api::admin::UserAccountPermissions* get_user_permissions (const bts::api::admin::AdminData& admin_data, uint32_t user_id);
|
||||
static const UserAccountPermissions* get_user_permissions (
|
||||
const AdminData& admin_data,
|
||||
uint32_t user_id);
|
||||
// for a given user, fills in the associated_accounts ref arg
|
||||
// with the accounts the user has permission to trade in
|
||||
static void find_user_trading_accounts (const bts::api::admin::AdminData& admin_data,
|
||||
uint32_t user_id,
|
||||
std::vector<const api::admin::BTSAccount*>& associated_accounts);
|
||||
static void find_user_trading_accounts (
|
||||
const AdminData& admin_data,
|
||||
uint32_t user_id,
|
||||
std::vector<const BTSAccount*>& associated_accounts);
|
||||
// validates that changes in user data satisfy all the
|
||||
// constraints
|
||||
static void validate_user_update (const bts::api::admin::AdminData& admin_data,
|
||||
const bts::api::admin::BTSUser& updated_user,
|
||||
bts::api::admin::AdminServiceOperationResult& result);
|
||||
static void validate_user_update (const AdminData& admin_data,
|
||||
const BTSUser& updated_user,
|
||||
AdminServiceOperationResult& result);
|
||||
// vaidates the exchange part of user data updates
|
||||
static void validate_user_exchange_data (const bts::api::admin::BTSUser& updated_user,
|
||||
bts::api::admin::AdminServiceOperationResult& out_result);
|
||||
static void validate_user_exchange_data (
|
||||
const BTSUser& updated_user,
|
||||
AdminServiceOperationResult& out_result);
|
||||
static void get_md_entitlement_report(const AdminData& admin_data,
|
||||
std::vector<MDEntitlementReportUnit>& entitlements);
|
||||
// Gets a reporting unit out of CMEMicData
|
||||
static MDEntitlementReportUnit get_cme_md_entitlement_unit(
|
||||
const std::string& user,
|
||||
const CMEMicData& cme_mic_data);
|
||||
static void get_user_symbol_permissions(
|
||||
const AdminData& data,
|
||||
const BTSUser& user,
|
||||
std::vector<UserSymbolMDPermissionUnit>& res);
|
||||
////////////////////////////////////////////
|
||||
// user mutators ///////////////////////////
|
||||
////////////////////////////////////////////
|
||||
static bts::api::admin::BTSUser* create_user (bts::api::admin::AdminData& data,
|
||||
uint32_t parent_group_id,
|
||||
const std::string& name,
|
||||
const std::string& password,
|
||||
bool is_active,
|
||||
const bts::api::admin::LicenseData& license_data,
|
||||
const bts::api::admin::LicenseEntitlements& license_entitlements,
|
||||
bts::api::admin::AdminServiceCreateEntityResult& result);
|
||||
static bts::api::admin::BTSUser* update_user(bts::api::admin::AdminData& admin_data,
|
||||
const bts::api::admin::BTSUser& updated_user,
|
||||
bts::api::admin::AdminServiceOperationResult& result);
|
||||
static void delete_user (bts::api::admin::AdminData& admin_data,
|
||||
const bts::api::admin::IDAPIArgument& id,
|
||||
bts::api::admin::AdminServiceOperationResult& result);
|
||||
static void set_user_exchange_data(bts::api::admin::BTSUser* user,
|
||||
const bts::api::admin::ExchangeUserData& exchange_user_data);
|
||||
static void set_user_md_entitlement_data(bts::api::admin::BTSUser* user,
|
||||
const bts::api::admin::ExchangeUserMarketDataEntitlementData& exchange_user_md_entitelemnt_data);
|
||||
static void clear_user_accounts (bts::api::admin::BTSUser* user);
|
||||
static void set_user_accounts (bts::api::admin::BTSUser* user,
|
||||
const bts::api::admin::UserAccountPermissions& user_account_permissions);
|
||||
static BTSUser* create_user (AdminData& data,
|
||||
uint32_t parent_group_id,
|
||||
const std::string& name,
|
||||
const std::string& password,
|
||||
bool is_active,
|
||||
const LicenseData& license_data,
|
||||
const LicenseEntitlements& license_entitlements,
|
||||
AdminServiceCreateEntityResult& result);
|
||||
static BTSUser* update_user(AdminData& admin_data,
|
||||
const BTSUser& updated_user,
|
||||
AdminServiceOperationResult& result);
|
||||
static void delete_user (AdminData& admin_data,
|
||||
const IDAPIArgument& id,
|
||||
AdminServiceOperationResult& result);
|
||||
static void set_user_exchange_data(
|
||||
BTSUser* user,
|
||||
const ExchangeUserData& exchange_user_data);
|
||||
static void set_user_md_entitlement_data(BTSUser* user,
|
||||
const ExchangeUserMarketDataEntitlementData&);
|
||||
static void clear_user_accounts (BTSUser* user);
|
||||
static void set_user_accounts (BTSUser* user,
|
||||
const UserAccountPermissions& user_account_permissions);
|
||||
////////////////////////////////////////////
|
||||
//risk limits //////////////////////////////
|
||||
////////////////////////////////////////////
|
||||
// sorting function used by sort_limits to
|
||||
// sort SecurityScope's
|
||||
static bool _sort_security_scopes (const bts::api::admin::SecurityScope& a, const bts::api::admin::SecurityScope& b);
|
||||
static bool _sort_security_scopes (const SecurityScope& a,
|
||||
const SecurityScope& b);
|
||||
// sorting function used by sort_limits to
|
||||
// sort ProductScope's
|
||||
static bool _sort_product_scopes (const bts::api::admin::ProductScope& a, const bts::api::admin::ProductScope&);
|
||||
static bool _sort_product_scopes (const ProductScope& a,
|
||||
const ProductScope&);
|
||||
// this sorts the rules such that the most
|
||||
// specific ones are at the top. this makes it
|
||||
// easier to match rules with securities/products
|
||||
static void sort_limits (bts::api::admin::BTSAccount& account);
|
||||
static void sort_limits (BTSAccount& account);
|
||||
// creates a copy of AdminData with sorted rules
|
||||
static bts::api::admin::AdminData sort_limits (const bts::api::admin::AdminData& admin_data);
|
||||
static AdminData sort_limits (const AdminData& admin_data);
|
||||
// find the clip size for a security, account
|
||||
static const uint32_t find_account_security_clip_size(const bts::api::admin::BTSAccount& account,
|
||||
const api::Security& security);
|
||||
static const uint32_t find_account_security_clip_size(
|
||||
const BTSAccount& account,
|
||||
const api::Security& security);
|
||||
// find the position limit for an account, security
|
||||
static const bts::api::admin::AccountSecurityPositionLimitUnit* find_account_security_position_limit(const bts::api::admin::BTSAccount& account,
|
||||
static const AccountSecurityPositionLimitUnit*
|
||||
find_account_security_position_limit(const BTSAccount& account,
|
||||
const api::Security& security);
|
||||
// find the position limit for an account, product
|
||||
static const bts::api::admin::AccountProductPositionLimitUnit* find_account_product_position_limit(const bts::api::admin::BTSAccount& account,
|
||||
static const AccountProductPositionLimitUnit*
|
||||
find_account_product_position_limit(const BTSAccount& account,
|
||||
const api::Product& product);
|
||||
static bool match_security_scope (const bts::api::admin::SecurityScope& scope,
|
||||
const bts::api::Security& security);
|
||||
static bool match_product_scope (const bts::api::admin::ProductScope& scope,
|
||||
const bts::api::Product& product);
|
||||
static bool match_product(const api::Security& security, const api::Product& product);
|
||||
static bool _match_limit_rule_symbol (const std::string& symbol, const std::string& limit_symbol);
|
||||
static bool match_security_scope (const SecurityScope& scope,
|
||||
const api::Security& security);
|
||||
static bool match_product_scope (const ProductScope& scope,
|
||||
const api::Product& product);
|
||||
static bool match_product(const api::Security& security,
|
||||
const api::Product& product);
|
||||
static bool _match_limit_rule_symbol (const std::string& symbol,
|
||||
const std::string& limit_symbol);
|
||||
static api::SecurityType security_type(const api::Security& security);
|
||||
////////////////////////////////////////////
|
||||
// misc//////// ////////////////////////////
|
||||
|
||||
@@ -182,6 +182,17 @@ message AccountExchangeConnections{
|
||||
/***************************Exchange Data********************************/
|
||||
/************************************************************************/
|
||||
|
||||
message CMEMicData{
|
||||
api.CMEMics mic=10;
|
||||
bool enabled=20;
|
||||
// there are other things here
|
||||
}
|
||||
|
||||
message ICEMicData{
|
||||
api.CMEMics mic=10;
|
||||
bool enabled=20;
|
||||
}
|
||||
|
||||
message ExchangeUserMarketDataEntitlementData{
|
||||
CMEUserMarketDataEntitlementData cme_data = 10;
|
||||
ICEUserMarketDataEntitlementData ice_data = 20;
|
||||
@@ -276,6 +287,8 @@ message CMEUserData{
|
||||
string smp_instruction = 70;
|
||||
string max_order_rate_per_connection = 80;
|
||||
string location = 90;
|
||||
// add suff here
|
||||
repeated CMEMicData md_permissions = 1000;
|
||||
}
|
||||
|
||||
message SIMUserData {
|
||||
@@ -331,6 +344,48 @@ message ICEUserData{
|
||||
message ICEUserMarketDataEntitlementData{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Order Auxiliary Service ////////////////////////////////
|
||||
|
||||
message OrdersSummaryUnit{
|
||||
string account = 10;
|
||||
string user = 20;
|
||||
uint32 total_orders = 30;
|
||||
uint32 total_contracts = 40;
|
||||
}
|
||||
message OrdersSummary{
|
||||
repeated OrdersSummaryUnit units = 10;
|
||||
}
|
||||
message OrderSummaryRequest{
|
||||
}
|
||||
// top level orders that have account
|
||||
// and user that are present here, will
|
||||
// be cancelled. wild cards are not
|
||||
// supported.
|
||||
message OrderCancelRequest{
|
||||
repeated string accounts = 10;
|
||||
repeated string users = 20;
|
||||
}
|
||||
///////////////////////////////////////////////////////////
|
||||
// Reporting //////////////////////////////////////////////
|
||||
message MDEntitlementReportUnit{
|
||||
string record_id = 1 [(bts.api.key)=true];
|
||||
string user = 10;
|
||||
string exchange = 20;
|
||||
string mic = 30;
|
||||
bool enabled = 40;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Misc ///////////////////////////////////////////////////
|
||||
message UserSymbolMDPermissionUnit{
|
||||
string record_id = 1 [(bts.api.key)=true];
|
||||
string user=10;
|
||||
api.Venue exchange=20;
|
||||
string symbol=30;
|
||||
bool enabled=40;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
@@ -385,4 +440,11 @@ service AdminService {
|
||||
// subscription
|
||||
rpc admin_data(bts.api.VoidMessage) returns (stream AdminData);
|
||||
rpc get_admin_data(bts.api.VoidMessage) returns (AdminData);
|
||||
// orders
|
||||
rpc get_order_summary(bts.api.VoidMessage) returns (OrdersSummary);
|
||||
rpc cancel_orders(OrderCancelRequest) returns (bts.api.VoidMessage);
|
||||
// reports
|
||||
rpc md_entitlement_data(bts.api.VoidMessage) returns (stream MDEntitlementReportUnit);
|
||||
// misc
|
||||
rpc md_permissions_data(bts.api.VoidMessage) returns (stream UserSymbolMDPermissionUnit);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
syntax="proto3";
|
||||
package bts.api.md.auxiliary;
|
||||
option csharp_namespace="bts.api.md.auxiliary";
|
||||
import "lib/api/apioptions.proto";
|
||||
import "lib/api/apicore.proto";
|
||||
|
||||
message VolumeAtPriceLevel{
|
||||
int32 record_id = 1 [(bts.api.key)=true];
|
||||
uint32 security_id = 20;
|
||||
double price = 30;
|
||||
uint32 volume = 40;
|
||||
}
|
||||
|
||||
service MarketDataAuxiliaryService{
|
||||
option (bts.api.service_description)="Provides non-core supplementary market data";
|
||||
rpc volume_at_price(bts.api.VoidMessage) returns (stream VolumeAtPriceLevel);
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import "lib/api/apioptions.proto";
|
||||
import "lib/domain_model/Security.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "lib/sparkproto/SparkProtos.proto";
|
||||
import "lib/api/apicore.proto";
|
||||
|
||||
service OrderService {
|
||||
option (bts.api.service_description)="Implements order management";
|
||||
@@ -15,9 +16,12 @@ service OrderService {
|
||||
rpc cancel_order(Cancel) returns (Response);
|
||||
rpc update_order(Update) returns (Response);
|
||||
rpc crack_order(Crack) returns (Response);
|
||||
rpc get_registered_dynamic_order_types(bts.api.VoidMessage) returns (RegisteredDynamicOrderTypes);
|
||||
|
||||
// streams
|
||||
rpc orders (OrdersSub) returns (stream OrderRecord);
|
||||
|
||||
|
||||
rpc fills (FillsSub) returns (stream Fill);
|
||||
}
|
||||
|
||||
@@ -139,8 +143,7 @@ message CoverOrderDefinition {
|
||||
}
|
||||
message DynamicOrderDefinition {
|
||||
string dynamic_order_type = 1;
|
||||
map<string,string> parameters = 2;
|
||||
CustomOrderDefinition child = 3;
|
||||
map<string, DynamicOrderParam> order_params = 2;
|
||||
}
|
||||
// End custom order definitions
|
||||
|
||||
@@ -259,7 +262,7 @@ message TopOrderState {}
|
||||
message TriggerOrderState {}
|
||||
message CoverOrderState {}
|
||||
message DynamicOrderState {
|
||||
map<string,string> state = 2;
|
||||
map<string,string> state = 1;
|
||||
}
|
||||
|
||||
enum OrderStatus {
|
||||
@@ -465,3 +468,76 @@ message TriggerExitCondition{
|
||||
uint32 timeout_seconds=20; //seconds
|
||||
bool conditional_cancel=30;
|
||||
}
|
||||
|
||||
|
||||
// Dynamic Orders
|
||||
|
||||
enum DynamicOrderPrimitiveDescriptor {
|
||||
DYNAMIC_ORDER_PRIMITIVE_INT = 0;
|
||||
DYNAMIC_ORDER_PRIMITIVE_UINT = 1;
|
||||
DYNAMIC_ORDER_PRIMITIVE_DOUBLE = 2;
|
||||
DYNAMIC_ORDER_PRIMITIVE_STRING = 3;
|
||||
DYNAMIC_ORDER_PRIMITIVE_BOOL = 4;
|
||||
DYNAMIC_ORDER_PRIMITIVE_ORDER_DEF = 5;
|
||||
}
|
||||
|
||||
message DynamicOrderTypeDescriptor {
|
||||
oneof descriptor {
|
||||
DynamicOrderPrimitiveDescriptor primitive = 2;
|
||||
DynamicOrderArrayDescriptor array = 3;
|
||||
DynamicOrderStructDescriptor structure = 4;
|
||||
DynamicOrderEnumeratedDescriptor enumerated = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message DynamicOrderArrayDescriptor {
|
||||
DynamicOrderTypeDescriptor element_type = 1;
|
||||
}
|
||||
|
||||
message DynamicOrderParamDescriptor {
|
||||
string param_name = 1;
|
||||
DynamicOrderTypeDescriptor param_type = 2;
|
||||
}
|
||||
|
||||
message DynamicOrderStructDescriptor {
|
||||
repeated DynamicOrderParamDescriptor field = 1;
|
||||
}
|
||||
|
||||
message DynamicOrderEnumeratedDescriptor {
|
||||
repeated string element = 1;
|
||||
}
|
||||
|
||||
message DynamicOrderDescriptor {
|
||||
string dynamic_order_type = 1;
|
||||
repeated DynamicOrderParamDescriptor param_desc = 3;
|
||||
}
|
||||
|
||||
message RegisteredDynamicOrderTypes {
|
||||
repeated DynamicOrderDescriptor dynamic_order_desc = 1;
|
||||
}
|
||||
|
||||
message DynamicOrderParam {
|
||||
oneof value {
|
||||
uint32 as_int32 = 1;
|
||||
uint32 as_uint32 = 2;
|
||||
double as_double = 3;
|
||||
string as_string = 4;
|
||||
bool as_bool = 5;
|
||||
CustomOrderDefinition as_order_def = 6;
|
||||
DynamicOrderArray as_array = 7;
|
||||
DynamicOrderStruct as_struct = 8;
|
||||
DynamicOrderEnumerated as_enumerated = 9;
|
||||
}
|
||||
}
|
||||
|
||||
message DynamicOrderArray {
|
||||
repeated DynamicOrderParam element = 1;
|
||||
}
|
||||
|
||||
message DynamicOrderStruct {
|
||||
map<string,DynamicOrderParam> field = 1;
|
||||
}
|
||||
|
||||
message DynamicOrderEnumerated {
|
||||
string enum_value = 1;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -2,17 +2,17 @@
|
||||
|
||||
DynamicOrderList {
|
||||
value {
|
||||
# dynamic_orders
|
||||
# {
|
||||
# type_name: 'DynamicOrder1'
|
||||
# parameter_keys: 'param1'
|
||||
# parameter_keys: 'param2'
|
||||
# }
|
||||
# dynamic_orders
|
||||
# {
|
||||
# type_name: 'DynamicOrder2'
|
||||
# parameter_keys: 'param3'
|
||||
# parameter_keys: 'param4'
|
||||
# }
|
||||
dynamic_orders
|
||||
{
|
||||
type_name: 'DynamicOrder1'
|
||||
parameter_keys: 'param1'
|
||||
parameter_keys: 'param2'
|
||||
}
|
||||
dynamic_orders
|
||||
{
|
||||
type_name: 'DynamicOrder2'
|
||||
parameter_keys: 'param3'
|
||||
parameter_keys: 'param4'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
ExpirationDisplayOffset
|
||||
{
|
||||
value
|
||||
{
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "lo"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "CL"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "ob"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "RB"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "oh"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "HO"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "wbs"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "WBS"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "so"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "SI"
|
||||
addition_count: 0
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "og"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "GC"
|
||||
addition_count: 0
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "hxe"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "HG"
|
||||
addition_count: 0
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "ozs"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "ozw"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "osd"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "ZS"
|
||||
addition_count: 0
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "ozm"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "ZM"
|
||||
addition_count: 0
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "ozl"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "ZL"
|
||||
addition_count: 0
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "ozc"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "ZC"
|
||||
addition_count: 0
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "OPTION"
|
||||
security_name: "ozn"
|
||||
addition_count: 1
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
entries
|
||||
{
|
||||
security_type: "FUTURE"
|
||||
security_name: "ZN"
|
||||
addition_count: 0
|
||||
addition_type: MonthMoveToStart
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
syntax='proto2';
|
||||
package bts.config;
|
||||
import "lib/domain_model/Security.proto";
|
||||
|
||||
message CppConfig {
|
||||
map<string, double> cpp_entry = 1;
|
||||
}
|
||||
|
||||
message CmeSymbolMics {
|
||||
map<string, bts.api.CMEMics> cme_mic = 1;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
syntax='proto2';
|
||||
package bts.config;
|
||||
|
||||
message CppConfig {
|
||||
map<string, double> cpp_entry = 1;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
syntax='proto2';
|
||||
package bts.config;
|
||||
|
||||
message ExpirationOffsetType
|
||||
{
|
||||
enum type
|
||||
{
|
||||
Month=0;
|
||||
MonthMoveToStart=1;
|
||||
}
|
||||
}
|
||||
|
||||
message ExpirationDisplayOffsetEntry
|
||||
{
|
||||
required string security_type = 1;
|
||||
required string security_name = 2;
|
||||
required int32 addition_count = 3;
|
||||
required ExpirationOffsetType.type addition_type = 4;
|
||||
}
|
||||
|
||||
message ExpirationDisplayOffset
|
||||
{
|
||||
repeated ExpirationDisplayOffsetEntry entries = 1;
|
||||
}
|
||||
@@ -26,4 +26,8 @@ message OrdersSoftCleanup{
|
||||
|
||||
message ToastNotifications {
|
||||
optional bool enabled = 1 [default = false];
|
||||
}
|
||||
|
||||
message VolumeAtPrice{
|
||||
optional bool enabled = 1 [default = true];
|
||||
}
|
||||
@@ -40,6 +40,22 @@ enum Currency {
|
||||
CURRENCY_RMB = 14;
|
||||
}
|
||||
|
||||
enum CMEMics {
|
||||
UNSET = 0;
|
||||
CME = 1;
|
||||
NYMEX = 2;
|
||||
CBT = 3;
|
||||
COMEX = 4;
|
||||
MGE = 5;
|
||||
DME = 6;
|
||||
NYMSW = 7;
|
||||
FXS = 8;
|
||||
}
|
||||
|
||||
enum ICEMics{
|
||||
ICE_FUTURES_CANADA=0;
|
||||
}
|
||||
|
||||
enum Side {
|
||||
SIDE_UNDEFINED = 0;
|
||||
SIDE_BUY = 49;
|
||||
|
||||
@@ -131,14 +131,17 @@ int SocketConnection::write(WriteVec const &vec, size_t vec_size,
|
||||
LOG(Latency, Info,
|
||||
"perf_event:tick_to_order s2s_us:{} fix_socket_r:{} md:{} "
|
||||
"md_src:{} spreader_on_book:{} spreader_modify_order:{} "
|
||||
"order_update:{} exe_gw:{} fix_socket_w:{} md_sn:{}",
|
||||
"spreader_on_child_order_update:{} "
|
||||
"order_update:{} exe_gw:{} fix_socket_w:{} md_sn:{} order_key:{}",
|
||||
s2s.microseconds(), trace_cpy.fix_socket_r.to_uint64(),
|
||||
trace_cpy.md.to_uint64(), trace_cpy.md_src.to_uint64(),
|
||||
trace_cpy.spreader_on_book.to_uint64(),
|
||||
trace_cpy.spreader_modify_order.to_uint64(),
|
||||
trace_cpy.spreader_on_child_order_update.to_uint64(),
|
||||
trace_cpy.order_update.to_uint64(),
|
||||
trace_cpy.exe_gw.to_uint64(), trace_cpy.fix_socket_w.to_uint64(),
|
||||
trace_cpy.md_sn);
|
||||
trace_cpy.md_sn,
|
||||
trace_cpy.order_key);
|
||||
_tick_to_order->observe(s2s.nanoseconds());
|
||||
}
|
||||
|
||||
@@ -147,14 +150,17 @@ int SocketConnection::write(WriteVec const &vec, size_t vec_size,
|
||||
LOG(Latency, Info,
|
||||
"perf_event:fill_to_order s2s_us:{} fix_socket_r:{} md:{} md_src:{} "
|
||||
"spreader_on_book:{} spreader_modify_order:{} "
|
||||
"order_update:{} exe_gw:{} fix_socket_w:{} md_sn:{}",
|
||||
"spreader_on_child_order_update:{} "
|
||||
"order_update:{} exe_gw:{} fix_socket_w:{} md_sn:{} order_key:{}",
|
||||
s2s.microseconds(), trace_cpy.fix_socket_r.to_uint64(),
|
||||
trace_cpy.md.to_uint64(), trace_cpy.md_src.to_uint64(),
|
||||
trace_cpy.spreader_on_book.to_uint64(),
|
||||
trace_cpy.spreader_modify_order.to_uint64(),
|
||||
trace_cpy.spreader_on_child_order_update.to_uint64(),
|
||||
trace_cpy.order_update.to_uint64(),
|
||||
trace_cpy.exe_gw.to_uint64(), trace_cpy.fix_socket_w.to_uint64(),
|
||||
trace_cpy.md_sn);
|
||||
trace_cpy.md_sn,
|
||||
trace.order_key);
|
||||
_fill_to_order->observe(s2s.nanoseconds());
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,7 @@ void configure_logging(LoggingConfig const&cfg) {_default_logger_hub.config(cfg)
|
||||
void configure_logging(bts::config::Logging const&cfg)
|
||||
{
|
||||
LoggingConfig real_cfg;
|
||||
real_cfg.deployment_type = config::get<config::DeploymentType>().type();
|
||||
real_cfg.logger_initial_queue_size = cfg.initial_queue_size();
|
||||
real_cfg.logger_max_queue_growth = cfg.max_queue_growth();
|
||||
|
||||
@@ -115,6 +116,7 @@ void configure_logging(bts::config::Logging const&cfg)
|
||||
{log::Testing,"Testing"},
|
||||
{log::Latency,"Latency"},
|
||||
{log::DataFlow,"DataFlow"},
|
||||
{log::Plugin,"Plugin"},
|
||||
};
|
||||
|
||||
real_cfg.sinks["console"] =
|
||||
@@ -123,7 +125,6 @@ void configure_logging(bts::config::Logging const&cfg)
|
||||
std::make_pair (syslog_sink(real_cfg),get_filter(real_cfg,cfg.syslog()));
|
||||
real_cfg.sinks["file"] =
|
||||
std::make_pair (file_sink(real_cfg),get_filter(real_cfg,cfg.file()));
|
||||
real_cfg.deployment_type = config::get<config::DeploymentType>().type();
|
||||
configure_logging(real_cfg);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ constexpr log::Subsystem Mercury {ExSim.ordinal+1 };
|
||||
constexpr log::Subsystem Testing {Mercury.ordinal+1 };
|
||||
constexpr log::Subsystem Latency {Testing.ordinal+1 };
|
||||
constexpr log::Subsystem DataFlow {Latency.ordinal+1 };
|
||||
constexpr log::Subsystem Plugin {DataFlow.ordinal+1 };
|
||||
|
||||
struct LoggerHandle {
|
||||
LoggerHandle(LoggerHandle const&) = delete;
|
||||
|
||||
@@ -209,10 +209,15 @@ void MDProducerHandle::mark_deleted() {
|
||||
TimeStamp ts = TimeStamp::now();
|
||||
cdata().deleted = true;
|
||||
std::array<PriceSize,COCONUT_MAX_DEPTH> blank;
|
||||
std::array<PriceSize,COCONUT_MAX_IMPLIED_DEPTH> iblank;
|
||||
for (size_t x = 0; x < blank.size(); ++x) {
|
||||
blank[x] = PriceSize::NO_MARKET;
|
||||
if (x < COCONUT_MAX_IMPLIED_DEPTH) {
|
||||
iblank[x] = PriceSize::NO_MARKET;
|
||||
}
|
||||
}
|
||||
update_book(ts, blank, blank, 0);
|
||||
update_direct(ts, blank, blank, 0);
|
||||
update_implied(ts, iblank, iblank, 0);
|
||||
}
|
||||
|
||||
}}//namespace
|
||||
|
||||
@@ -34,8 +34,8 @@ public:
|
||||
}
|
||||
void set_legs(const std::vector<security_key>& legs);
|
||||
|
||||
void update_bbo(TimeStamp time, const PriceSize bid_price, const PriceSize ask_price, uint16_t seq=0); // hot
|
||||
void update_book(TimeStamp time, std::array<PriceSize,COCONUT_MAX_DEPTH>& bids, std::array<PriceSize,COCONUT_MAX_DEPTH>& asks, uint32_t seq=0) {
|
||||
void update_bbo(TimeStamp time, const PriceSize bid_price, const PriceSize ask_price, uint16_t seq=0);
|
||||
void update_direct(TimeStamp time, std::array<PriceSize,COCONUT_MAX_DEPTH>& bids, std::array<PriceSize,COCONUT_MAX_DEPTH>& asks, uint32_t seq=0) {
|
||||
if (!has_depth()) {
|
||||
update_bbo(time, bids[0], asks[0], seq);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
hheader().direct_count += 1;
|
||||
}
|
||||
}
|
||||
void update_implied(TimeStamp time, std::array<PriceSize,COCONUT_IMPLIED_DEPTH>& bids, std::array<PriceSize,COCONUT_IMPLIED_DEPTH>& asks, uint32_t seq=0) {
|
||||
void update_implied(TimeStamp time, std::array<PriceSize,COCONUT_MAX_IMPLIED_DEPTH>& bids, std::array<PriceSize,COCONUT_MAX_IMPLIED_DEPTH>& asks, uint32_t seq=0) {
|
||||
if (has_depth()) {
|
||||
auto& book = hdepth();
|
||||
book.set_time(TimeStamp::invalid());
|
||||
|
||||
@@ -52,7 +52,7 @@ class HotEntry {
|
||||
static_assert(sizeof(HotEntry) <= CACHE_LINE, "HotEntry should be small");
|
||||
|
||||
const uint32_t COCONUT_MAX_DEPTH = 10;
|
||||
const uint32_t COCONUT_IMPLIED_DEPTH = 2;
|
||||
const uint32_t COCONUT_MAX_IMPLIED_DEPTH = 2;
|
||||
class HotDepthEntry {
|
||||
std::atomic<TimeStamp> timestamp; // 8
|
||||
public:
|
||||
@@ -68,7 +68,7 @@ class HotDepthEntry {
|
||||
security_key key; // 4 NOTE: key is at a different offset than it is in HotEntry
|
||||
uint32_t sequence; // 4
|
||||
std::array<PriceLevel, COCONUT_MAX_DEPTH> direct; // 240
|
||||
std::array<PriceLevel, COCONUT_IMPLIED_DEPTH> implied; // 48
|
||||
std::array<PriceLevel, COCONUT_MAX_IMPLIED_DEPTH> implied; // 48
|
||||
uint8_t status; // 1
|
||||
|
||||
const PriceLevel* at(uint32_t depth) const {
|
||||
|
||||
@@ -60,7 +60,7 @@ class RelayProducer : public IRelayWriter {
|
||||
bids[x] = book_at(update.book().bids(), x);
|
||||
asks[x] = book_at(update.book().asks(), x);
|
||||
}
|
||||
handle.update_book(updated, bids, asks);
|
||||
handle.update_direct(updated, bids, asks);
|
||||
}
|
||||
if (update.has_misc()) {
|
||||
auto& misc = update.misc();
|
||||
|
||||
@@ -38,7 +38,7 @@ void setup_market(MDProducerHandle producer, const vector<PS>& bids, const vecto
|
||||
std::transform(bids.begin(), bids.end(), bids_a.begin(), [](const PS& ps) { return PriceSize::from_double<7>(ps.price, ps.size); });
|
||||
std::transform(asks.begin(), asks.end(), asks_a.begin(), [](const PS& ps) { return PriceSize::from_double<7>(ps.price, ps.size); });
|
||||
|
||||
producer.update_book(ts, bids_a, asks_a);
|
||||
producer.update_direct(ts, bids_a, asks_a);
|
||||
}
|
||||
|
||||
void expect_market(const MDConsumerHandle& handle, const vector<PS> bids, const vector<PS>& asks) {
|
||||
|
||||
@@ -17,12 +17,12 @@ namespace orderman {
|
||||
|
||||
struct AsyncFactory::PImpl
|
||||
{
|
||||
PImpl() :
|
||||
PImpl(DynamicOrderRegistry const&b) :
|
||||
orders_stream(),
|
||||
fix_buffer_stream(),
|
||||
db(),
|
||||
order_router(),
|
||||
order_factory(db,order_router)
|
||||
order_factory(db,order_router,b)
|
||||
{}
|
||||
|
||||
mercury::Stream<CreateOrderReplyEvent> orders_stream;
|
||||
@@ -32,7 +32,7 @@ struct AsyncFactory::PImpl
|
||||
OrderFactory order_factory;
|
||||
};
|
||||
|
||||
AsyncFactory::AsyncFactory() : me(new PImpl()) {}
|
||||
AsyncFactory::AsyncFactory(DynamicOrderRegistry const&b) : me(new PImpl(b)) {}
|
||||
AsyncFactory::~AsyncFactory () {}
|
||||
|
||||
void AsyncFactory::init()
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
class DynamicOrderRegistry;
|
||||
|
||||
// used to asynchronously build fix buffers and orders
|
||||
class AsyncFactory : public mercury::Actor
|
||||
{
|
||||
public:
|
||||
AsyncFactory();
|
||||
AsyncFactory(DynamicOrderRegistry const&);
|
||||
~AsyncFactory();
|
||||
|
||||
void init() override;
|
||||
|
||||
@@ -43,10 +43,12 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
|
||||
_stats.publish(_loop_timer);
|
||||
|
||||
auto security_count_metric = std::make_shared<metrics::CounterMetric<int>>("spark_mdsource_security_count");
|
||||
auto synthetic_count_metric = std::make_shared<metrics::CounterMetric<int>>("spark_mdsource_synthetic_count");
|
||||
_stats.publish(security_count_metric);
|
||||
_stats.publish(synthetic_count_metric);
|
||||
|
||||
_book_update = make_stream<BookUpdateEvent>();
|
||||
subscribe<MDRequestEvent>([this,security_count_metric](auto const &update) {
|
||||
subscribe<MDRequestEvent>([this,security_count_metric,synthetic_count_metric](auto const &update) {
|
||||
if (update.events) {
|
||||
for (auto const &ev : *update.events) {
|
||||
auto k = ev.security_key.value();
|
||||
@@ -63,6 +65,9 @@ class MDSource : public mercury::Actor, public mercury::IPollableActor {
|
||||
"Starting to publish book updates for security key: {}", k);
|
||||
auto handle = _md_consumer.get_handle(k);
|
||||
_handles.push_back({utils::TimeStamp(), handle});
|
||||
if (handle.is_synthetic()) {
|
||||
synthetic_count_metric->increment();
|
||||
}
|
||||
}
|
||||
security_count_metric->set(_handles.size());
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "ServiceBridge.h"
|
||||
|
||||
#include "lib/api/public/ServiceContext.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
#include "lib/orderman/events/ActivateOrderEvent.h"
|
||||
#include "lib/orderman/events/CancelOrderEvent.h"
|
||||
#include "lib/orderman/events/CrackOrderEvent.h"
|
||||
#include "lib/orderman/events/NewAdminDataEvent.h"
|
||||
#include "lib/orderman/events/NewSecuritiesEvent.h"
|
||||
#include "lib/orderman/events/OrderManagerReadyEvent.h"
|
||||
#include "lib/orderman/events/StoredFillEvent.h"
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "lib/orderman/order_factory/OrderFactory.h"
|
||||
#include "lib/orderman/order_router/OrderRouter.h"
|
||||
#include "lib/orderman/securities/MapSecurityDB.h"
|
||||
#include "lib/orderman/events/NewAdminDataEvent.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
|
||||
#include "lib/api/services/OrderService.pb.h"
|
||||
#include "lib/orderman/orderman_utils/orderman_common.h"
|
||||
@@ -24,12 +24,13 @@ namespace orderman {
|
||||
|
||||
struct ServiceBridge::PImpl {
|
||||
PImpl(OnReady const &on_ready, OnOrders const &on_orders,
|
||||
OnFills const &on_fills)
|
||||
OnFills const &on_fills,
|
||||
DynamicOrderRegistry const &dyn_order_registry)
|
||||
: on_ready(on_ready), on_orders(on_orders), on_fills(on_fills),
|
||||
have_orders(false), have_securities(false), order_manager_ready(false),
|
||||
sec_db(), order_router(), order_factory(sec_db, order_router),
|
||||
known_orders() {
|
||||
}
|
||||
sec_db(), order_router(),
|
||||
order_factory(sec_db, order_router, dyn_order_registry),
|
||||
known_orders() {}
|
||||
|
||||
OnReady on_ready;
|
||||
OnOrders on_orders;
|
||||
@@ -47,20 +48,18 @@ struct ServiceBridge::PImpl {
|
||||
mercury::Stream<NewAdminDataEvent> new_admin_data_pub;
|
||||
std::unordered_set<OrderKey> known_orders;
|
||||
std::vector<std::shared_ptr<const api::admin::AdminData>> admin_data_updates;
|
||||
|
||||
|
||||
std::promise<void> ready;
|
||||
};
|
||||
|
||||
ServiceBridge::ServiceBridge(OnReady const &on_ready, OnOrders const &on_orders,
|
||||
OnFills const &on_fills)
|
||||
: me(new PImpl(on_ready, on_orders, on_fills)) {}
|
||||
OnFills const &on_fills,
|
||||
DynamicOrderRegistry const &dyn_order_registry)
|
||||
: me(new PImpl(on_ready, on_orders, on_fills, dyn_order_registry)) {}
|
||||
|
||||
ServiceBridge::~ServiceBridge() {}
|
||||
|
||||
void ServiceBridge::block_until_ready()
|
||||
{
|
||||
me->ready.get_future().wait();
|
||||
}
|
||||
void ServiceBridge::block_until_ready() { me->ready.get_future().wait(); }
|
||||
|
||||
void ServiceBridge::init() {
|
||||
subscribe<NewAdminDataEvent>([this](auto const &u) { this->on(u); });
|
||||
@@ -125,8 +124,8 @@ void ServiceBridge::on(mercury::Update<OrderManagerReadyEvent> const &update) {
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceBridge::on(mercury::Update<NewAdminDataEvent> const&update) {
|
||||
if (update.events)
|
||||
void ServiceBridge::on(mercury::Update<NewAdminDataEvent> const &update) {
|
||||
if (update.events)
|
||||
for (auto ev : *(update.events))
|
||||
me->order_router.update(*ev.admin_data);
|
||||
}
|
||||
@@ -233,12 +232,12 @@ ServiceBridge::crack_order(api::orderman::Crack const &c) {
|
||||
return f.get();
|
||||
}
|
||||
|
||||
void ServiceBridge::update_admin_data(std::shared_ptr<const api::admin::AdminData> const&admin)
|
||||
{
|
||||
void ServiceBridge::update_admin_data(
|
||||
std::shared_ptr<const api::admin::AdminData> const &admin) {
|
||||
post_action([this, admin]() {
|
||||
me->admin_data_updates.push_back (admin);
|
||||
publish(me->new_admin_data_pub,*admin);
|
||||
});
|
||||
me->admin_data_updates.push_back(admin);
|
||||
publish(me->new_admin_data_pub, *admin);
|
||||
});
|
||||
}
|
||||
|
||||
bool ServiceBridge::is_ready() const {
|
||||
@@ -249,5 +248,5 @@ void ServiceBridge::maybe_signal_ready(bool old_ready) {
|
||||
if (!old_ready && is_ready())
|
||||
me->on_ready();
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -1,14 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "lib/mercury/actors/Actor.h"
|
||||
#include "lib/config/protos/jetfix.pb.h"
|
||||
#include "lib/mercury/actors/Actor.h"
|
||||
#include <memory>
|
||||
|
||||
// fwds
|
||||
namespace bts {
|
||||
namespace api {
|
||||
class ServiceContext;
|
||||
namespace admin { class AdminData;}
|
||||
namespace admin {
|
||||
class AdminData;
|
||||
}
|
||||
namespace orderman {
|
||||
class OrderRecord;
|
||||
class Fill;
|
||||
@@ -17,32 +19,36 @@ class Create;
|
||||
class Update;
|
||||
class Cancel;
|
||||
class Crack;
|
||||
}}
|
||||
} // namespace orderman
|
||||
} // namespace api
|
||||
namespace orderman {
|
||||
class StoredFillEvent;
|
||||
class StoredOrderEvent;
|
||||
class NewSecuritiesEvent;
|
||||
class OrderManagerReadyEvent;
|
||||
class NewAdminDataEvent;
|
||||
}}
|
||||
class DynamicOrderRegistry;
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
// end fwds
|
||||
|
||||
|
||||
// Provides a threading bridge between the quickbux/service world and
|
||||
// the mercury event broker.
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class ServiceBridge : public mercury::Actor
|
||||
{
|
||||
public:
|
||||
template <class EV> using OnEv = std::function<void(EV const&)>;
|
||||
class ServiceBridge : public mercury::Actor {
|
||||
public:
|
||||
template <class EV> using OnEv = std::function<void(EV const &)>;
|
||||
|
||||
using OnReady = std::function<void()>;
|
||||
using OnOrders = std::function<void (std::vector<api::orderman::OrderRecord> const& )>;
|
||||
using OnFills = std::function<void (std::vector<api::orderman::Fill> const&)>;
|
||||
|
||||
ServiceBridge(OnReady const&, OnOrders const&, OnFills const&);
|
||||
using OnOrders =
|
||||
std::function<void(std::vector<api::orderman::OrderRecord> const &)>;
|
||||
using OnFills =
|
||||
std::function<void(std::vector<api::orderman::Fill> const &)>;
|
||||
|
||||
ServiceBridge(OnReady const &, OnOrders const &, OnFills const &,
|
||||
DynamicOrderRegistry const &);
|
||||
void init() override;
|
||||
~ServiceBridge();
|
||||
|
||||
@@ -50,23 +56,25 @@ public:
|
||||
void block_until_ready();
|
||||
|
||||
// these can be called from any thread, after block_until_ready() returns
|
||||
api::orderman::Response create_order(api::orderman::Create const&c);
|
||||
api::orderman::Response update_order(api::orderman::Update const&c);
|
||||
api::orderman::Response cancel_order(api::orderman::Cancel const&c);
|
||||
api::orderman::Response crack_order(api::orderman::Crack const&c);
|
||||
void update_admin_data(std::shared_ptr<api::admin::AdminData const> const &admin);
|
||||
|
||||
private:
|
||||
api::orderman::Response create_order(api::orderman::Create const &c);
|
||||
api::orderman::Response update_order(api::orderman::Update const &c);
|
||||
api::orderman::Response cancel_order(api::orderman::Cancel const &c);
|
||||
api::orderman::Response crack_order(api::orderman::Crack const &c);
|
||||
void
|
||||
update_admin_data(std::shared_ptr<api::admin::AdminData const> const &admin);
|
||||
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
bool is_ready () const;
|
||||
bool is_ready() const;
|
||||
void maybe_signal_ready(bool old_ready);
|
||||
|
||||
void on(mercury::Update<StoredFillEvent> const&);
|
||||
void on(mercury::Update<StoredOrderEvent> const&);
|
||||
void on(mercury::Update<NewSecuritiesEvent> const&);
|
||||
void on(mercury::Update<OrderManagerReadyEvent> const&);
|
||||
void on(mercury::Update<NewAdminDataEvent> const&);
|
||||
|
||||
void on(mercury::Update<StoredFillEvent> const &);
|
||||
void on(mercury::Update<StoredOrderEvent> const &);
|
||||
void on(mercury::Update<NewSecuritiesEvent> const &);
|
||||
void on(mercury::Update<OrderManagerReadyEvent> const &);
|
||||
void on(mercury::Update<NewAdminDataEvent> const &);
|
||||
};
|
||||
|
||||
}}
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -40,7 +40,8 @@ struct OrderManager::OrderInfo {
|
||||
};
|
||||
|
||||
struct OrderManager::PImpl {
|
||||
PImpl(Actor &owner) : state(State::WAIT_ADMIN), services_data(owner) {}
|
||||
PImpl(Actor &owner, DynamicOrderRegistry const &b)
|
||||
: state(State::WAIT_ADMIN), services_data(owner, b) {}
|
||||
|
||||
State state;
|
||||
std::unordered_map<OrderKey, OrderInfo> orders;
|
||||
@@ -50,7 +51,7 @@ struct OrderManager::PImpl {
|
||||
mercury::Stream<OrderManagerReadyEvent> pub_ready;
|
||||
};
|
||||
|
||||
OrderManager::OrderManager() : me(new PImpl(*this)) {}
|
||||
OrderManager::OrderManager(DynamicOrderRegistry const&b) : me(new PImpl(*this,b)) {}
|
||||
OrderManager::~OrderManager() {}
|
||||
|
||||
void OrderManager::init() {
|
||||
@@ -202,8 +203,7 @@ void OrderManager::on_activate_order(
|
||||
OrderInfo oi{*order, me->services_data};
|
||||
auto serv_ptr = oi.order_services.get();
|
||||
me->orders[k] = std::move(oi);
|
||||
order->on_activate(ev.price, ev.quantity, *serv_ptr,
|
||||
ev.trace);
|
||||
order->on_activate(ev.price, ev.quantity, *serv_ptr, ev.trace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,8 +213,7 @@ void OrderManager::on_update_order(const mercury::Update<UpdateOrderEvent> &m) {
|
||||
auto k = ev.key();
|
||||
auto it = me->orders.find(k);
|
||||
if (it != me->orders.end())
|
||||
it->second.order->on_update(ev.price, ev.quantity,
|
||||
ev.trace);
|
||||
it->second.order->on_update(ev.price, ev.quantity, ev.trace);
|
||||
else {
|
||||
LOG(OrderMan, Error,
|
||||
"Received an update request for an unknown order {}. "
|
||||
|
||||
@@ -22,6 +22,7 @@ class StoredFillEvent;
|
||||
class CreateFIXBufferReplyEvent;
|
||||
class GatewayStatusChangeEvent;
|
||||
class NewAdminDataEvent;
|
||||
class DynamicOrderRegistry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +52,7 @@ namespace orderman {
|
||||
|
||||
class OrderManager : public mercury::Actor {
|
||||
public:
|
||||
OrderManager();
|
||||
OrderManager(DynamicOrderRegistry const&dyn_order_builder);
|
||||
~OrderManager();
|
||||
void init() override;
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
OrderServicesData::OrderServicesData(mercury::Actor &owner)
|
||||
: owner(owner), order_router(), order_factory(sec_db, order_router),
|
||||
OrderServicesData::OrderServicesData(mercury::Actor &owner,DynamicOrderRegistry const&b)
|
||||
: owner(owner), order_router(), order_factory(sec_db, order_router,b),
|
||||
last_timer_ev(
|
||||
Timer::now(),
|
||||
to<mercury::TimeStampStr>(datetime::FIX_timestamp(datetime::now()))) {
|
||||
|
||||
@@ -67,13 +67,14 @@ struct SessionServicesData {
|
||||
|
||||
class OrderServicesData {
|
||||
public:
|
||||
OrderServicesData(mercury::Actor &owner);
|
||||
OrderServicesData(mercury::Actor &owner,DynamicOrderRegistry const&b);
|
||||
|
||||
mercury::Actor &owner;
|
||||
securities::MapSecurityDB sec_db;
|
||||
OrderRouter order_router;
|
||||
Limiter limiter;
|
||||
OrderFactory order_factory;
|
||||
|
||||
|
||||
std::unique_ptr<mercury::ContentSubscription<BookUpdateEvent>> md_subs;
|
||||
std::unique_ptr<
|
||||
mercury::ContentSubscription<OrderStateUpdateEvent, ParentKey>>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class DynamicOrder;
|
||||
|
||||
using DynamicOrderBuilder = std::function<std::unique_ptr<DynamicOrder>()>;
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "DynamicOrderRegistry.h"
|
||||
#include "lib/orderman/orders/DynamicOrder.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
struct DynamicOrderRegistry::PImpl {
|
||||
std::unordered_map<
|
||||
std::string,
|
||||
std::pair<DynamicOrderBuilder, api::orderman::DynamicOrderDescriptor>>
|
||||
dyn_orders;
|
||||
};
|
||||
|
||||
DynamicOrderRegistry::DynamicOrderRegistry() : me(new PImpl()) {}
|
||||
DynamicOrderRegistry::~DynamicOrderRegistry() {}
|
||||
|
||||
void DynamicOrderRegistry::register_dynamic_order(
|
||||
api::orderman::DynamicOrderDescriptor const &desc,
|
||||
DynamicOrderBuilder const &b) {
|
||||
me->dyn_orders[desc.dynamic_order_type()] = std::make_pair(b, desc);
|
||||
}
|
||||
|
||||
std::unique_ptr<DynamicOrder>
|
||||
DynamicOrderRegistry::build(std::string const &dynamic_order_type) const {
|
||||
auto it = me->dyn_orders.find(dynamic_order_type);
|
||||
if (it != me->dyn_orders.end())
|
||||
return it->second.first();
|
||||
else
|
||||
return std::unique_ptr<DynamicOrder>();
|
||||
}
|
||||
|
||||
std::vector<api::orderman::DynamicOrderDescriptor>
|
||||
DynamicOrderRegistry::get_all_dynamic_order_types() const {
|
||||
|
||||
std::vector<api::orderman::DynamicOrderDescriptor> result;
|
||||
for (auto const &ot : me->dyn_orders)
|
||||
result.push_back(ot.second.second);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/order_factory/DynamicOrderBuilder.h"
|
||||
#include "lib/api/services/OrderService.pb.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
|
||||
class DynamicOrderRegistry {
|
||||
public:
|
||||
DynamicOrderRegistry();
|
||||
~DynamicOrderRegistry();
|
||||
|
||||
void register_dynamic_order(api::orderman::DynamicOrderDescriptor const&desc,
|
||||
DynamicOrderBuilder const&builder);
|
||||
|
||||
// can return a null if no such order type exists
|
||||
std::unique_ptr<DynamicOrder> build(std::string const&dynamic_order_type) const;
|
||||
|
||||
std::vector<api::orderman::DynamicOrderDescriptor> get_all_dynamic_order_types() const;
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr <PImpl> me;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,24 +1,25 @@
|
||||
#include "OrderFactory.h"
|
||||
#include "lib/api/services/OrderService.pb.h"
|
||||
#include "lib/logging/logging.h"
|
||||
#include "lib/orderman/orderman_utils/ExecutionReport.h"
|
||||
#include "lib/orderman/orders/PreActivationOrderServices.h"
|
||||
#include "lib/utils/Puid.h"
|
||||
#include "lib/utils/SpinLock.h"
|
||||
#include "lib/utils/bts_assert.h"
|
||||
#include "lib/orderman/orderman_utils/ExecutionReport.h"
|
||||
#include "lib/orderman/orders/PreActivationOrderServices.h"
|
||||
|
||||
// order types
|
||||
#include "lib/orderman/order_factory/DynamicOrderRegistry.h"
|
||||
#include "lib/orderman/orders/DynamicOrder.h"
|
||||
#include "lib/orderman/orders/IcebergOrder.h"
|
||||
#include "lib/orderman/orders/spreader_orders/SpreaderOrder.h"
|
||||
#include "lib/orderman/orders/NativeOrder.h"
|
||||
#include "lib/orderman/orders/TimeBoxOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/TickOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/LeanOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/JoinOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/TopOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/CoverOrder.h"
|
||||
#include "lib/orderman/orders/TriggerOrder.h"
|
||||
#include "lib/orderman/orders/DynamicOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/CoverOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/JoinOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/LeanOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/TickOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/TopOrder.h"
|
||||
#include "lib/orderman/orders/spreader_orders/SpreaderOrder.h"
|
||||
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
@@ -48,16 +49,20 @@ OrderKey gen_order_id() {
|
||||
}
|
||||
|
||||
struct OrderFactory::PImpl {
|
||||
PImpl(securities::ISecurityDB &db,OrderRouter const&router)
|
||||
: my_orders(), sec_db(db), router(router){}
|
||||
PImpl(securities::ISecurityDB &db, OrderRouter const &router,
|
||||
DynamicOrderRegistry const &dr)
|
||||
: my_orders(), sec_db(db), router(router), dynamic_order_registry(dr) {}
|
||||
|
||||
std::vector<std::unique_ptr<Order>> my_orders;
|
||||
securities::ISecurityDB &sec_db;
|
||||
OrderRouter const&router;
|
||||
OrderRouter const &router;
|
||||
DynamicOrderRegistry const &dynamic_order_registry;
|
||||
};
|
||||
|
||||
OrderFactory::OrderFactory(securities::ISecurityDB &db, OrderRouter const&router)
|
||||
: me(new PImpl(db, router)) {}
|
||||
OrderFactory::OrderFactory(securities::ISecurityDB &db,
|
||||
OrderRouter const &router,
|
||||
DynamicOrderRegistry const ®istry)
|
||||
: me(new PImpl(db, router, registry)) {}
|
||||
|
||||
OrderFactory::~OrderFactory() {}
|
||||
|
||||
@@ -66,8 +71,8 @@ Order &OrderFactory::create(OrderKey parent,
|
||||
auto k = gen_order_id();
|
||||
auto pk = parent;
|
||||
auto &order = allocate(k, pk, def);
|
||||
order.on_init_new(def,
|
||||
PreActivationOrderServices{me->sec_db, *this,me->router});
|
||||
order.on_init_new(def,
|
||||
PreActivationOrderServices{me->sec_db, *this, me->router});
|
||||
return order;
|
||||
}
|
||||
|
||||
@@ -76,7 +81,7 @@ Order &OrderFactory::recover(api::orderman::OrderRecord const &rec) {
|
||||
auto pk = OrderKey(rec.parent_key());
|
||||
auto &order = allocate(k, pk, rec.def());
|
||||
order.on_init_recovered(
|
||||
rec, PreActivationOrderServices{me->sec_db, *this,me->router});
|
||||
rec, PreActivationOrderServices{me->sec_db, *this, me->router});
|
||||
return order;
|
||||
}
|
||||
|
||||
@@ -90,7 +95,7 @@ Order &OrderFactory::recreate_from_exe_report(ExecutionReport const &r) {
|
||||
case NATIVE_ORDER_TYPE_STOP_LIMIT: {
|
||||
auto native_order = std::make_unique<NativeOrder>();
|
||||
native_order->on_init_from_exe_report(
|
||||
r, PreActivationOrderServices{me->sec_db, *this,me->router});
|
||||
r, PreActivationOrderServices{me->sec_db, *this, me->router});
|
||||
native_order->_key = r.order_key;
|
||||
native_order->_parent_key = null_order_key();
|
||||
me->my_orders.emplace_back();
|
||||
@@ -122,32 +127,40 @@ Order &OrderFactory::allocate(OrderKey k, OrderKey pk,
|
||||
order_ptr.reset(new IcebergOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kSpreader:
|
||||
order_ptr.reset (new orderman::SpreaderOrder());
|
||||
order_ptr.reset(new orderman::SpreaderOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kTimeBox:
|
||||
order_ptr.reset (new orderman::TimeBoxOrder());
|
||||
order_ptr.reset(new orderman::TimeBoxOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kTick:
|
||||
order_ptr.reset (new orderman::TickOrder());
|
||||
order_ptr.reset(new orderman::TickOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kLean:
|
||||
order_ptr.reset (new orderman::LeanOrder());
|
||||
break;
|
||||
order_ptr.reset(new orderman::LeanOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kJoin:
|
||||
order_ptr.reset (new orderman::JoinOrder());
|
||||
order_ptr.reset(new orderman::JoinOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kTop:
|
||||
order_ptr.reset (new orderman::TopOrder());
|
||||
order_ptr.reset(new orderman::TopOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kTrigger:
|
||||
order_ptr.reset (new orderman::TriggerOrder());
|
||||
order_ptr.reset(new orderman::TriggerOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kCover:
|
||||
order_ptr.reset (new orderman::CoverOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kDynamic:
|
||||
order_ptr.reset (new orderman::DynamicOrder());
|
||||
order_ptr.reset(new orderman::CoverOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kDynamic: {
|
||||
order_ptr = me->dynamic_order_registry.build(
|
||||
def.custom_def().dynamic().dynamic_order_type());
|
||||
if (!order_ptr) {
|
||||
// the default dynamic order is empty and will transition
|
||||
// immediately to an error state, so we use it when we cannot
|
||||
// resolve the requested type
|
||||
order_ptr.reset(new orderman::DynamicOrder());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CustomOrderDefinition::CUSTOM_NOT_SET:
|
||||
bts_assert(false);
|
||||
break;
|
||||
@@ -156,5 +169,5 @@ Order &OrderFactory::allocate(OrderKey k, OrderKey pk,
|
||||
order_ptr->_parent_key = pk;
|
||||
return *order_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -11,7 +11,8 @@ class ISecurityDB;
|
||||
}
|
||||
namespace orderman {
|
||||
class Order;
|
||||
}
|
||||
class DynamicOrderRegistry;
|
||||
} // namespace orderman
|
||||
namespace orderman {
|
||||
class OrderRouter;
|
||||
}
|
||||
@@ -32,7 +33,8 @@ namespace orderman {
|
||||
|
||||
class OrderFactory : public IOrderFactory {
|
||||
public:
|
||||
OrderFactory(securities::ISecurityDB &db, OrderRouter const &router);
|
||||
OrderFactory(securities::ISecurityDB &db, OrderRouter const &router,
|
||||
DynamicOrderRegistry const &dynamic_order_reg);
|
||||
~OrderFactory();
|
||||
|
||||
Order &create(OrderKey parent,
|
||||
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
utils::TimeStamp exe_gw ;
|
||||
utils::TimeStamp fix_socket_w ;
|
||||
utils::TimeStamp spreader_modify_order ;
|
||||
uint32_t order_key = 0;
|
||||
uint16_t md_sn = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "lib/api/services/OrderService.pb.h"
|
||||
|
||||
namespace bts{
|
||||
namespace orderman{
|
||||
|
||||
using namespace bts::api::orderman;
|
||||
|
||||
inline bool order_in_error_state(OrderStatus order_status){
|
||||
return order_status == OrderStatus::ORDER_STATUS_ERROR ||
|
||||
order_status == OrderStatus::ORDER_STATUS_DISCONNECTED ||
|
||||
order_status == OrderStatus::ORDER_STATUS_REJECTED_BY_SPARK;
|
||||
}
|
||||
|
||||
inline bool order_in_working_state(OrderStatus order_status){
|
||||
return order_status == OrderStatus::ORDER_STATUS_WORKING ||
|
||||
order_status == OrderStatus::ORDER_STATUS_PENDING_WORKING;
|
||||
}
|
||||
|
||||
inline bool is_exchange_order(const OrderState& state){
|
||||
return state.has_market() ||
|
||||
state.has_limit() ||
|
||||
state.has_stop() ||
|
||||
state.has_stop_limit();
|
||||
}
|
||||
|
||||
inline bool is_parent_order(const OrderRecord& ord){
|
||||
return ord.parent_key()==0;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -15,7 +15,6 @@ struct DynamicOrder::PImpl {
|
||||
api::orderman::OrderState state;
|
||||
};
|
||||
|
||||
|
||||
DynamicOrder::DynamicOrder() : me(new PImpl()) {}
|
||||
|
||||
DynamicOrder::~DynamicOrder() {}
|
||||
@@ -27,13 +26,14 @@ api::orderman::OrderDefinition const &DynamicOrder::definition() const {
|
||||
void DynamicOrder::on_init_new(api::orderman::OrderDefinition const &def,
|
||||
const PreActivationOrderServices &) {
|
||||
me->def = def;
|
||||
me->state.mutable_trigger();
|
||||
me->state.mutable_dynamic();
|
||||
|
||||
auto const &dynamic_def = def.custom_def().dynamic();
|
||||
auto msg = fmt::format("Could not find implementation for dynamic order type {}",
|
||||
dynamic_def.dynamic_order_type());
|
||||
auto msg =
|
||||
fmt::format("Could not find implementation for dynamic order type {}",
|
||||
dynamic_def.dynamic_order_type());
|
||||
me->state.set_status(ORDER_STATUS_REJECTED_BY_SPARK);
|
||||
me->state.set_last_msg(msg);
|
||||
transition(ORDER_STATUS_REJECTED_BY_SPARK, msg);
|
||||
}
|
||||
|
||||
void DynamicOrder::on_init_recovered(api::orderman::OrderRecord const &rec,
|
||||
@@ -41,35 +41,21 @@ void DynamicOrder::on_init_recovered(api::orderman::OrderRecord const &rec,
|
||||
auto const &def = rec.def();
|
||||
me->def = def;
|
||||
me->state = rec.state();
|
||||
auto msg = fmt::format("Could not find implementation for dynamic order type {}",
|
||||
def.custom_def().dynamic().dynamic_order_type());
|
||||
transition(ORDER_STATUS_ERROR, msg);
|
||||
}
|
||||
|
||||
void DynamicOrder::on_activate(Price , Quantity , OrderServices &services,
|
||||
PerfTrace const&) {
|
||||
bts_assert(!me->services);
|
||||
me->services = &services;
|
||||
report_state();
|
||||
}
|
||||
|
||||
void DynamicOrder::on_update(Price , Quantity , PerfTrace const&) {}
|
||||
void DynamicOrder::on_crack(PerfTrace const&) {}
|
||||
void DynamicOrder::on_cancel(PerfTrace const&) {}
|
||||
|
||||
void DynamicOrder::transition(api::orderman::OrderStatus new_status,
|
||||
std::string const &msg) {
|
||||
auto const &from = OrderStatus_Name(me->state.status());
|
||||
auto const &to = OrderStatus_Name(new_status);
|
||||
LOG(OrderMan, Info, "Transitioning dynamic order {} from {} to {}. Msg: {}",
|
||||
key().value(), from, to, msg);
|
||||
auto msg =
|
||||
fmt::format("Could not find implementation for dynamic order type {}",
|
||||
def.custom_def().dynamic().dynamic_order_type());
|
||||
me->state.set_status(ORDER_STATUS_REJECTED_BY_SPARK);
|
||||
me->state.set_last_msg(msg);
|
||||
me->state.set_status(new_status);
|
||||
}
|
||||
|
||||
void DynamicOrder::report_state() {
|
||||
me->services->report_state(me->state);
|
||||
void DynamicOrder::on_activate(Price, Quantity, OrderServices &services,
|
||||
PerfTrace const &) {
|
||||
services.report_state(me->state);
|
||||
}
|
||||
|
||||
void DynamicOrder::on_update(Price, Quantity, PerfTrace const &) {}
|
||||
void DynamicOrder::on_crack(PerfTrace const &) {}
|
||||
void DynamicOrder::on_cancel(PerfTrace const &) {}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -25,8 +25,6 @@ public:
|
||||
void on_cancel(PerfTrace const&) override ;
|
||||
|
||||
private:
|
||||
void report_state();
|
||||
void transition(api::orderman::OrderStatus new_state,std::string const&msg);
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
};
|
||||
|
||||
@@ -271,7 +271,10 @@ NativeOrder::~NativeOrder() {}
|
||||
|
||||
void NativeOrder::on_activate(Price p, Quantity q,
|
||||
bts::orderman::OrderServices &services,
|
||||
PerfTrace const&trace) {
|
||||
PerfTrace const&t) {
|
||||
auto trace = t;
|
||||
trace.order_key = key().value();
|
||||
|
||||
tracepoint(bts_trace, trace_order, (char *)"on_activate", 0, trace.md_sn, 0);
|
||||
bts_assert(!me->services);
|
||||
me->services = &services;
|
||||
@@ -454,6 +457,7 @@ void NativeOrder::on_activate(Price p, Quantity q,
|
||||
void NativeOrder::on_update(Price p, Quantity q, PerfTrace const &t) {
|
||||
auto trace = t;
|
||||
trace.order_update = utils::TimeStamp::now();
|
||||
trace.order_key = key().value();
|
||||
tracepoint(bts_trace, trace_order, (char *)"on_update", 0, trace.md_sn, 0);
|
||||
|
||||
switch (me->state.status()) {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
.separator ","
|
||||
create table trace (md integer,event_type text,md_src integer,event_id integer,order_update integer,fix_socket_r integer,spreader integer,md_sn integer,s2s_us integer,fix_socket_w integer,exe_gw integer);
|
||||
.import trace.csv trace
|
||||
create view summary as select (fix_socket_w - md) / 1000 total, (md_src-md)/1000 md_to_md_src, (spreader-md_src)/1000 md_src_to_spreader, (exe_gw - spreader)/1000 spreader_to_gw, (fix_socket_w - exe_gw)/1000 gw_to_socket from trace where md<>0 and total < 3000
|
||||
@@ -1,152 +0,0 @@
|
||||
28196590053886,'tick_to_order',28197102957058,28197103124480,0,0,28197102965440,0,513025,28197103079756,28197103059842
|
||||
28196697483499,'tick_to_order',28197102959931,28197103141481,0,0,28197102977491,0,405644,28197103127966,28197103069284
|
||||
28201969547888,'tick_to_order',28202833807433,28202833937515,0,0,28202833816030,0,864350,28202833898377,28202833881042
|
||||
28202088397252,'tick_to_order',28202833808697,28202833958080,0,0,28202833820739,0,745545,28202833942340,28202833889176
|
||||
28208616597481,'tick_to_order',28208827513088,28208827642654,0,0,28208827522022,0,211009,28208827607194,28208827592933
|
||||
28206481082894,'tick_to_order',28208827514190,28208827656336,0,0,28208827526464,0,2346563,28208827646293,28208827600491
|
||||
0,'fill_to_order',0,28208839081032,0,28208838837781,28208838868980,0,217,28208839055537,28208839019346
|
||||
28208839129931,'tick_to_order',28208839131496,28208839264318,28208839145688,0,28208839136228,0,117,28208839247030,28208839179115
|
||||
28208839129931,'tick_to_order',28208839131496,28208839289002,28208839159470,0,28208839140083,0,137,28208839267546,28208839198889
|
||||
28208839129931,'tick_to_order',28208839131496,28208839308230,28208839168905,0,28208839142093,0,162,28208839291985,28208839226400
|
||||
28208840433680,'tick_to_order',28208840435375,28208840547408,28208840447508,0,28208840439959,0,82,28208840516447,28208840472378
|
||||
28208840433680,'tick_to_order',28208840435375,28208840564743,28208840461566,0,28208840443149,0,116,28208840550591,28208840491019
|
||||
0,'fill_to_order',0,28208840879082,0,28208840576867,28208840672109,0,279,28208840855927,28208840823128
|
||||
28208843503746,'tick_to_order',28208843504814,28208843593574,28208843515483,0,28208843508641,0,59,28208843563706,28208843538005
|
||||
28208843503746,'tick_to_order',28208843504814,28208843610982,28208843528636,0,28208843511561,0,93,28208843596950,28208843551505
|
||||
0,'fill_to_order',0,28208944130393,0,28208943887617,28208943948194,0,222,28208944109810,28208944074684
|
||||
0,'fill_to_order',0,28209370139941,0,28209369888113,28209369952751,0,229,28209370117992,28209370079701
|
||||
0,'fill_to_order',0,28209484101320,0,28209483868990,28209483924268,0,212,28209484081653,28209484047486
|
||||
0,'fill_to_order',0,28209620409858,0,28209620162751,28209620228530,0,226,28209620388905,28209620355079
|
||||
0,'fill_to_order',0,28209739007884,0,28209738787668,28209738842302,0,199,28209738987526,28209738956093
|
||||
0,'fill_to_order',0,28210065047881,0,28210064800913,28210064864573,0,222,28210065023655,28210064978085
|
||||
0,'fill_to_order',0,28210065233727,0,28210064898370,28210065084780,0,323,28210065221391,28210065180960
|
||||
0,'fill_to_order',0,28210065333238,0,28210064996958,28210065263677,0,318,28210065315113,28210065306971
|
||||
0,'fill_to_order',0,28210065415952,0,28210065129134,28210065363289,0,273,28210065402209,28210065394553
|
||||
28215444390938,'tick_to_order',28215444393078,28215444529603,28215444414071,0,28215444400232,0,112,28215444503281,28215444457072
|
||||
28215444390938,'tick_to_order',28215444393078,28215444554080,28215444447525,0,28215444407818,0,142,28215444533183,28215444489016
|
||||
28215701976039,'tick_to_order',28215701977746,28215702098032,28215701997311,0,28215701984151,0,96,28215702072244,28215702038741
|
||||
28215701976039,'tick_to_order',28215701977746,28215702117853,28215702025791,0,28215701991346,0,125,28215702101709,28215702058942
|
||||
28220019865624,'tick_to_order',28220019867840,28220020026255,28220019895427,0,28220019878734,0,121,28220019986960,28220019950863
|
||||
28220019865624,'tick_to_order',28220019867840,28220020048864,28220019925593,0,28220019887884,0,164,28220020030569,28220019973048
|
||||
28220718678139,'tick_to_order',28220718680250,28220718831012,28220718700578,0,28220718686869,0,117,28220718795381,28220718739230
|
||||
28220718678139,'tick_to_order',28220718680250,28220718843749,28220718729541,0,28220718694405,0,156,28220718834720,28220718758232
|
||||
0,'fill_to_order',0,28220848918980,0,28220848687143,28220848747379,0,215,28220848902908,28220848871434
|
||||
0,'fill_to_order',0,28220849030568,0,28220848810372,28220848942605,0,208,28220849018851,28220848995256
|
||||
28220979169929,'tick_to_order',28220979172020,28220979305300,28220979192771,0,28220979179092,0,91,28220979261054,28220979229515
|
||||
28220979169929,'tick_to_order',28220979172020,28220979318464,28220979220293,0,28220979186577,0,139,28220979309388,28220979248193
|
||||
0,'fill_to_order',0,28220979513307,0,28220979350005,28220979419822,0,143,28220979493077,28220979481893
|
||||
28221070673726,'tick_to_order',28221070675735,28221070736601,28221070686482,0,28221070679562,0,38,28221070712616,28221070696306
|
||||
0,'fill_to_order',0,28222155872739,0,28222155643549,28222155706574,0,212,28222155855965,28222155816114
|
||||
0,'fill_to_order',0,28223133846563,0,28223133590522,28223133654830,0,239,28223133830454,28223133794944
|
||||
0,'fill_to_order',0,28223133964453,0,28223133694947,28223133883747,0,257,28223133952496,28223133928563
|
||||
0,'fill_to_order',0,28223581969280,0,28223581343526,28223581815686,0,609,28223581953459,28223581912188
|
||||
0,'fill_to_order',0,28223704304248,0,28223704088620,28223704171518,0,198,28223704286939,28223704256133
|
||||
0,'fill_to_order',0,28223810423519,0,28223810245448,28223810273233,0,160,28223810406444,28223810375144
|
||||
0,'fill_to_order',0,28224157832610,0,28224157585281,28224157653252,0,228,28224157813464,28224157774003
|
||||
28225529919208,'tick_to_order',28225529920711,28225530042405,28225529934691,0,28225529924851,0,80,28225529999639,28225529967993
|
||||
28226405462919,'tick_to_order',28226405465191,28226405619988,28226405485773,0,28226405472394,0,109,28226405572077,28226405529637
|
||||
28226405462919,'tick_to_order',28226405465191,28226405643951,28226405515803,0,28226405479758,0,161,28226405624112,28226405552798
|
||||
0,'fill_to_order',0,28226639771067,0,28226639589379,28226639651419,0,160,28226639750285,28226639740882
|
||||
0,'fill_to_order',0,28226639868980,0,28226639697224,28226639800947,0,156,28226639853935,28226639847230
|
||||
0,'fill_to_order',0,28227470569733,0,28227470374132,28227470440886,0,173,28227470547685,28227470529896
|
||||
0,'fill_to_order',0,28227924680234,0,28227924466565,28227924537639,0,191,28227924657821,28227924642595
|
||||
0,'fill_to_order',0,28228583926424,0,28228583705807,28228583773256,0,196,28228583902203,28228583885542
|
||||
0,'fill_to_order',0,28229533144966,0,28229532943412,28229533016549,0,179,28229533123032,28229533107434
|
||||
28229639851202,'tick_to_order',28229639852863,28229639980592,28229639870969,0,28229639858965,0,101,28229639952655,28229639907287
|
||||
28229639851202,'tick_to_order',28229639852863,28229640022874,28229639895237,0,28229639865959,0,137,28229639988700,28229639933822
|
||||
28229758761828,'tick_to_order',28229758763548,28229758882763,28229758783209,0,28229758770464,0,87,28229758849709,28229758814253
|
||||
28230101180913,'tick_to_order',28230101182993,28230101321254,28230101203074,0,28230101189865,0,93,28230101274549,28230101238130
|
||||
0,'fill_to_order',0,28230213923877,0,28230213648930,28230213710049,0,247,28230213896822,28230213856225
|
||||
0,'fill_to_order',0,28230322952329,0,28230322741821,28230322777654,0,195,28230322937621,28230322902984
|
||||
28230322898664,'tick_to_order',28230322908948,28230323024151,28230322965669,0,28230322958901,0,112,28230323011412,28230322986116
|
||||
28230322898664,'tick_to_order',28230322908948,28230323038883,28230322977834,0,28230322962821,0,128,28230323027132,28230322999842
|
||||
28230440123991,'tick_to_order',28230440126171,28230440213062,28230440147361,0,28230440132325,0,64,28230440188943,28230440169401
|
||||
0,'fill_to_order',0,28230662058747,0,28230661808794,28230661873095,0,228,28230662036818,28230661997869
|
||||
28230661973920,'tick_to_order',28230662004972,28230662136598,28230662078575,0,28230662071011,0,145,28230662119451,28230662092610
|
||||
28232123015042,'tick_to_order',28232123016868,28232123163592,28232123038403,0,28232123025185,0,98,28232123113494,28232123079664
|
||||
28232246918717,'tick_to_order',28232246920939,28232247064104,28232246940909,0,28232246927439,0,103,28232247021756,28232246981847
|
||||
28232246918717,'tick_to_order',28232246920939,28232247092688,28232246970727,0,28232246934998,0,149,28232247068479,28232247006870
|
||||
0,'fill_to_order',0,28232368953013,0,28232368700267,28232368775616,0,231,28232368931852,28232368894466
|
||||
28233036777229,'tick_to_order',28233036779530,28233036901259,28233036799515,0,28233036787312,0,85,28233036862284,28233036832720
|
||||
28233143137874,'tick_to_order',28233143139325,28233143260634,28233143160138,0,28233143147888,0,80,28233143218446,28233143191543
|
||||
28233699628365,'tick_to_order',28233699630159,28233699764620,28233699650528,0,28233699637850,0,84,28233699713280,28233699683814
|
||||
28234022689932,'tick_to_order',28234022691802,28234022828558,28234022711256,0,28234022699631,0,88,28234022778733,28234022747663
|
||||
28234704667015,'tick_to_order',28234704668729,28234704800087,28234704690713,0,28234704677354,0,86,28234704753635,28234704723237
|
||||
28234821194623,'tick_to_order',28234821196392,28234821314094,28234821215371,0,28234821204189,0,85,28234821280172,28234821249340
|
||||
28236352247871,'tick_to_order',28236352249625,28236352418387,28236352276252,0,28236352259617,0,116,28236352364376,28236352321875
|
||||
28236352247871,'tick_to_order',28236352249625,28236352441756,28236352308395,0,28236352268768,0,174,28236352422196,28236352346336
|
||||
28237224563641,'tick_to_order',28237224565693,28237224718121,28237224586812,0,28237224573410,0,111,28237224675179,28237224629165
|
||||
28237224563641,'tick_to_order',28237224565693,28237224741455,28237224617616,0,28237224580796,0,158,28237224721866,28237224660120
|
||||
28237332437212,'tick_to_order',28237332439266,28237332577973,28237332458507,0,28237332446944,0,103,28237332540626,28237332500617
|
||||
28237332437212,'tick_to_order',28237332439266,28237332599881,28237332488379,0,28237332453920,0,143,28237332580885,28237332523852
|
||||
28237549841429,'tick_to_order',28237549843628,28237549965700,28237549863870,0,28237549851244,0,85,28237549926606,28237549894491
|
||||
28238228061596,'tick_to_order',28238228063700,28238228177547,28238228084533,0,28238228077227,0,87,28238228149300,28238228118553
|
||||
28240113746524,'tick_to_order',28240113749923,28240113863959,28240113772664,0,28240113765041,0,93,28240113840462,28240113806744
|
||||
28240330403263,'tick_to_order',28240330405652,28240330535145,28240330434929,0,28240330420233,0,97,28240330500436,28240330470432
|
||||
28240853135285,'tick_to_order',28240853137341,28240853262896,28240853159118,0,28240853146534,0,86,28240853221294,28240853191691
|
||||
28240977598825,'tick_to_order',28240977600650,28240977717730,28240977622582,0,28240977609659,0,86,28240977685679,28240977656167
|
||||
0,'fill_to_order',0,28240978153216,0,28240977958658,28240978007053,0,180,28240978138810,28240978114020
|
||||
28240991592589,'tick_to_order',28240991593244,28240991653539,28240991597776,0,28240991594417,0,30,28240991623111,28240991609356
|
||||
28241670792957,'tick_to_order',28241670795036,28241670914874,28241670817757,0,28241670802941,0,88,28241670881569,28241670848033
|
||||
0,'fill_to_order',0,28241794767341,0,28241794513571,28241794577505,0,236,28241794750100,28241794703433
|
||||
28241823290439,'tick_to_order',28241823292469,28241823402171,28241823319217,0,28241823308663,0,82,28241823372733,28241823346560
|
||||
0,'fill_to_order',0,28242287683143,0,28242287436494,28242287498636,0,230,28242287667458,28242287624940
|
||||
28242298774730,'tick_to_order',28242298775728,28242298835466,28242298785181,0,28242298781321,0,34,28242298809643,28242298796811
|
||||
28242403521235,'tick_to_order',28242403521791,28242403623300,28242403529069,0,28242403523540,0,72,28242403593658,28242403559881
|
||||
0,'fill_to_order',0,28243061262066,0,28243061022436,28243061084315,0,224,28243061246455,28243061200891
|
||||
28243068384448,'tick_to_order',28243068384965,28243068443520,28243068390651,0,28243068386258,0,35,28243068420176,28243068403580
|
||||
28245948431958,'tick_to_order',28245948434240,28245948538937,28245948452612,0,28245948440859,0,82,28245948514737,28245948482316
|
||||
28247374525300,'tick_to_order',28247374526964,28247374651012,28247374547402,0,28247374535057,0,90,28247374615901,28247374579848
|
||||
28248234779582,'tick_to_order',28248234781348,28248234894161,28248234800599,0,28248234788742,0,86,28248234866284,28248234833094
|
||||
28252865029092,'tick_to_order',28252865030782,28252865145166,28252865048926,0,28252865037341,0,92,28252865121187,28252865083003
|
||||
28256547630478,'tick_to_order',28256547632063,28256547752066,28256547651901,0,28256547640012,0,86,28256547717211,28256547686110
|
||||
28279272348557,'tick_to_order',28279272349076,28279272467980,28279272355844,0,28279272350444,0,73,28279272422135,28279272389172
|
||||
28279501250366,'tick_to_order',28279501251899,28279501365341,28279501269773,0,28279501258390,0,86,28279501336734,28279501303261
|
||||
28280187509181,'tick_to_order',28280187511273,28280187630391,28280187528341,0,28280187517136,0,83,28280187592503,28280187561987
|
||||
28282957934927,'tick_to_order',28282957935955,28282958035906,28282957942708,0,28282957937270,0,71,28282958006407,28282957974920
|
||||
28289227944564,'tick_to_order',28289227946847,28289228127778,28289227964979,0,28289227953145,0,132,28289228076736,28289227998830
|
||||
28289718961779,'tick_to_order',28289718962450,28289719097342,28289718971611,0,28289718964883,0,78,28289719040495,28289719006734
|
||||
28289840450006,'tick_to_order',28289840451831,28289840568368,28289840471697,0,28289840459824,0,89,28289840539343,28289840506386
|
||||
28289951908418,'tick_to_order',28289951909247,28289952025470,28289951916324,0,28289951910651,0,77,28289951986204,28289951950742
|
||||
28290430936960,'tick_to_order',28290430937796,28290431040042,28290430945067,0,28290430939356,0,76,28290431013304,28290430979156
|
||||
28291466291399,'tick_to_order',28291466292396,28291466391677,28291466299142,0,28291466293741,0,73,28291466364828,28291466331580
|
||||
28291586496848,'tick_to_order',28291586499297,28291586630493,28291586518549,0,28291586506523,0,89,28291586586748,28291586552740
|
||||
28292751384837,'tick_to_order',28292751386806,28292751515067,28292751402678,0,28292751392069,0,83,28292751468056,28292751435430
|
||||
28293907933522,'tick_to_order',28293907934184,28293908066450,28293907941496,0,28293907935646,0,82,28293908016305,28293907974890
|
||||
28295067740412,'tick_to_order',28295067741030,28295067853412,28295067747989,0,28295067742670,0,74,28295067814671,28295067780682
|
||||
28295196992579,'tick_to_order',28295196993281,28295197144280,28295197000321,0,28295196995181,0,66,28295197059418,28295197030200
|
||||
28295451473434,'tick_to_order',28295451475533,28295451601789,28295451493675,0,28295451482374,0,86,28295451560177,28295451527873
|
||||
28295571761366,'tick_to_order',28295571763034,28295571881990,28295571773921,0,28295571766554,0,87,28295571848682,28295571810898
|
||||
28295799249116,'tick_to_order',28295799249915,28295799381637,28295799259696,0,28295799252812,0,85,28295799334429,28295799296519
|
||||
28297239376580,'tick_to_order',28297239377240,28297239498181,28297239384700,0,28297239378885,0,73,28297239449922,28297239418885
|
||||
0,'fill_to_order',0,28298760385155,0,28298760203371,28298760266335,0,159,28298760363345,28298760352002
|
||||
28298760374945,'tick_to_order',28298760391800,28298760451225,28298760405116,0,28298760398804,0,55,28298760430902,28298760417038
|
||||
0,'fill_to_order',0,28299876959405,0,28299876766737,28299876827336,0,167,28299876934037,28299876920197
|
||||
0,'fill_to_order',0,28299989659260,0,28299989480132,28299989530309,0,157,28299989637655,28299989625573
|
||||
28299989581876,'tick_to_order',28299989633042,28299989717824,28299989671330,0,28299989665389,0,115,28299989697691,28299989684427
|
||||
0,'fill_to_order',0,28300122561435,0,28300122382620,28300122417354,0,163,28300122545783,28300122511174
|
||||
0,'fill_to_order',0,28300483509579,0,28300483262045,28300483323303,0,228,28300483490414,28300483452480
|
||||
0,'fill_to_order',0,28300841665450,0,28300841442269,28300841506011,0,206,28300841649125,28300841613194
|
||||
0,'fill_to_order',0,28301189220778,0,28301188990707,28301189050284,0,213,28301189204011,28301189165953
|
||||
0,'fill_to_order',0,28301653689006,0,28301653480269,28301653538862,0,200,28301653680352,28301653645610
|
||||
0,'fill_to_order',0,28301653834317,0,28301653598088,28301653712709,0,228,28301653826941,28301653795605
|
||||
0,'fill_to_order',0,28301653955025,0,28301653702923,28301653857384,0,245,28301653948024,28301653918401
|
||||
28302449240285,'tick_to_order',28302449240876,28302449335838,28302449247510,0,28302449242166,0,70,28302449310609,28302449282305
|
||||
0,'fill_to_order',0,28302686107925,0,28302685894905,28302685956385,0,197,28302686092000,28302686056337
|
||||
0,'fill_to_order',0,28303035556183,0,28303035327940,28303035392496,0,208,28303035536455,28303035500778
|
||||
0,'fill_to_order',0,28304618318730,0,28304618096174,28304618159048,0,206,28304618302477,28304618266601
|
||||
28306678855488,'tick_to_order',28306678857539,28306678970537,28306678878136,0,28306678865289,0,86,28306678941575,28306678909824
|
||||
0,'fill_to_order',0,28306679437306,0,28306679263763,28306679309431,0,159,28306679423428,28306679399469
|
||||
0,'fill_to_order',0,28306679584663,0,28306679309460,28306679462045,0,264,28306679573483,28306679540241
|
||||
28306709072481,'tick_to_order',28306709073029,28306709138909,28306709077851,0,28306709074198,0,39,28306709111506,28306709097190
|
||||
0,'fill_to_order',0,28306818077071,0,28306817801256,28306817871966,0,253,28306818054507,28306818012078
|
||||
0,'fill_to_order',0,28306818303482,0,28306817895245,28306818119406,0,388,28306818283918,28306818253059
|
||||
28307181183628,'tick_to_order',28307181186016,28307181304136,28307181209067,0,28307181193730,0,93,28307181277531,28307181244198
|
||||
0,'fill_to_order',0,28309145604025,0,28309145374760,28309145437019,0,212,28309145587475,28309145548980
|
||||
0,'fill_to_order',0,28309284279140,0,28309284059642,28309284117538,0,202,28309284262556,28309284227472
|
||||
0,'fill_to_order',0,28309449537547,0,28309449314305,28309449372163,0,203,28309449517790,28309449480468
|
||||
0,'fill_to_order',0,28309449660123,0,28309449443555,28309449562971,0,204,28309449648393,28309449624212
|
||||
0,'fill_to_order',0,28310100956899,0,28310100701043,28310100768437,0,232,28310100933398,28310100893978
|
||||
0,'fill_to_order',0,28310247666234,0,28310247418609,28310247492259,0,230,28310247649244,28310247612730
|
||||
0,'fill_to_order',0,28310247794724,0,28310247528988,28310247699695,0,253,28310247782849,28310247759510
|
||||
0,'fill_to_order',0,28310884035988,0,28310883781857,28310883843745,0,204,28310883986697,28310883951864
|
||||
|
Binary file not shown.
@@ -3,5 +3,5 @@ mkdir -p latency_data
|
||||
rm latency_data/*
|
||||
grep Latency $1 | python parse_helper.py import trace.csv> latency_data/import.sql
|
||||
rm -f latency_data/latency.sqlite
|
||||
grep Latency ~/sparkdata/data/logging/log | python parse_helper.py load > latency_data/trace.csv
|
||||
grep Latency $1 | python parse_helper.py load > latency_data/trace.csv
|
||||
(cd latency_data && sqlite3 trace.sqlite < import.sql)
|
||||
@@ -10,7 +10,31 @@ def gen_create_table(d,t):
|
||||
fields = [ "%s integer" % k if isinstance (v,int) else "%s text" % k for (k,v) in d.iteritems()]
|
||||
print ".separator \",\"\ncreate table trace (%s);" % ",".join(fields)
|
||||
print ".import %s trace" % t
|
||||
print "create view summary as select (fix_socket_w - md) / 1000 total, (md_src-md)/1000 md_to_md_src, (spreader_on_book-md_src)/1000 md_src_to_spreader, (spreader_on_child_order_update-spreader_on_book)/1000 on_book_to_order_update, (exe_gw - spreader_on_child_order_update)/1000 child_order_update_to_gw, (fix_socket_w - exe_gw)/1000 gw_to_socket from trace where md<>0 and total < 3000";
|
||||
print '''
|
||||
create view tick_to_order as select
|
||||
event_id,
|
||||
order_key,
|
||||
(fix_socket_w - md) / 1000 total,
|
||||
(md_src-md)/1000 md_to_md_src,
|
||||
(spreader_on_book-md_src)/1000 md_src_to_spreader,
|
||||
(spreader_modify_order-spreader_on_book)/1000 spreader_on_book_to_modify_order,
|
||||
(order_update-spreader_modify_order)/1000 spreader_modify_order_to_native_order,
|
||||
(exe_gw-order_update)/1000 native_order_to_gw,
|
||||
(fix_socket_w - exe_gw)/1000 gw_to_socket
|
||||
from trace where md<>0 and total < 3000 and spreader_modify_order<>0;
|
||||
|
||||
create view tick_to_order_perc as select
|
||||
event_id,
|
||||
total,
|
||||
round(100.0*md_to_md_src/total) md_to_md_src ,
|
||||
round(100.0*md_src_to_spreader/total) md_src_to_spreader ,
|
||||
round(100.0*spreader_on_book_to_modify_order/total) spreader_on_book_to_modify_order ,
|
||||
round(100.0*spreader_modify_order_to_native_order/total) spreader_modify_order_to_native_order ,
|
||||
round(100.0*native_order_to_gw/total) native_order_to_gw ,
|
||||
round(100.0*gw_to_socket/total) gw_to_socket
|
||||
from tick_to_order;
|
||||
|
||||
'''
|
||||
|
||||
def gen_insert(d):
|
||||
values = [ "%s" % v if isinstance (v,int) else "'%s'" % v for v in d.values()]
|
||||
|
||||
Loaded 100 of 138 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user