Compare commits

...
85 Commits
Author SHA1 Message Date
Jake Norbut f415cddf0b Merged in SP-208 (pull request #330)
SP-208 - no nullref when clearing empty discrete filter

Approved-by: Kevin Darby <kevin.darby@bluetradesys.com>
2019-08-28 15:52:57 +00:00
Jake Norbut 8c36b498a4 proposed release notes 2019-08-28 10:45:45 -05:00
Jake Norbut 94baf15d01 Per John, adding this line back to repopulate items once again 2019-08-28 10:02:37 -05:00
Jake Norbut 14aad6ece8 SP-208 - no nullref when clearing empty discrete filter 2019-08-28 08:48:34 -05:00
Pedro Pinto fa55a61ef3 Merge branch 'prod' of bitbucket.org:bluetradesys/spark into prod 2019-08-22 11:43:08 -04:00
Pedro Pinto e832252669 Merge branch 'master' of bitbucket.org:bluetradesys/spark 2019-08-22 11:41:30 -04:00
Pedro Pinto 31980f7c14 Updated release notes. 2019-08-22 11:41:14 -04:00
Pedro Pinto d63ee80f94 Fixed up internal tool only pp uses. 2019-08-22 11:40:53 -04:00
Jake Norbut ca69e11fff Merged in SP-190 (pull request #325)
use Spreader AlgoFormat when security is synthetic

Approved-by: John Colvin <john.colvin@bluetradesys.com>
2019-08-22 15:38:17 +00:00
Eric Harding 9d202906f0 Merged in SP-184-add-display-factor-mapping (pull request #326)
SP-184 add display factor mapping

Approved-by: Pedro Pinto <pedro.pinto+atlassian@bluetradesys.com>
2019-08-22 15:27:04 +00:00
Pedro Pinto 968dd5a4d3 Merge branch 'prod' 2019-08-22 11:03:09 -04:00
Pedro Pinto 30cb1fd800 Updated externals subrepo pointer 2019-08-22 11:02:35 -04:00
Pedro Pinto 38eb122bbc Updated docker subrepo pointer 2019-08-22 11:01:51 -04:00
Eric Harding e2e31d310f SP-184 Update SOM price mult 2019-08-22 10:55:02 -04:00
Eric Harding 6890a61b26 Add SOM display factor to defaults 2019-08-22 08:51:29 -04:00
Eric Harding 36828a979f Add std::optional stand-in for _WIN32 2019-08-21 18:40:26 -04:00
Eric Harding 57bf60e6df Extract parse_enum<T> for parsing protobuf enum to optional<T> 2019-08-21 18:40:26 -04:00
Eric Harding 8e3a83d314 SP-184 Revenge of Mapping Part IV 2019-08-21 18:40:26 -04:00
Jake Norbut dc43d25c53 use Spreader AlgoFormat when security is synthetic 2019-08-21 15:54:23 -05:00
Jake Norbut 845fa99bd0 swapping these statements so no NullRef 2019-08-21 10:48:48 -05:00
John Colvin 2b5403bbd5 Merged in sorted-wrapper-crash (pull request #324)
SP-188 DiscreteValuesFilterVM SortedWrapper crash
2019-08-21 15:34:50 +00:00
John Colvin c9ff3e1bb3 SP-188 DiscreteValuesFilterVM SortedWrapper crash 2019-08-21 10:21:18 -05:00
Kevin Darby 632a86f670 Merge branch 'prod' of bitbucket.org:bluetradesys/spark 2019-08-15 09:35:33 -04:00
Taha Afzal cdbda8250f 'Fixing' the test (the test is broken, fill really fix it in the subsequent push) 2019-08-14 22:14:54 -04:00
John Colvin 43fd07dcfa Merged in SOM-ticks (pull request #320)
SPARK-1715 Handle fractional numerator tick sizes

Approved-by: Kevin Darby <kevin.darby@bluetradesys.com>
2019-08-14 20:43:00 +00:00
John Colvin efcb4f471c fix config toggle for som ticks 2019-08-14 15:40:23 -05:00
John Colvin d2f2e03e64 [SPARK-1715] config toggle for som ticks fix 2019-08-14 15:31:30 -05:00
John Colvin cfeba74900 SPARK-1715 Handle fractional numerator tick sizes 2019-08-14 14:50:42 -05:00
Jake Norbut 41bc4f7950 re-generated conf with SOM and latest from CME ftp 2019-08-14 11:51:07 -05:00
Jake Norbut 963bd15b35 adding SOM manual list; CME does not publish SOM data in their ftp 2019-08-14 11:50:24 -05:00
Kevin Darby b080d4a9c4 Merged in master (pull request #318)
Spark 2.8

Approved-by: Kevin Darby <kevin.darby@bluetradesys.com>
2019-08-13 19:19:47 +00:00
pfisher 282e10cba3 fixed update.txt test 2019-08-13 12:04:11 -04:00
Kevin Darby fa1b436fb3 added sticky button release notes 2019-08-09 10:53:02 -04:00
Kevin Darby 191518d8bc Merged in fix_algo_docs (pull request #316)
removing duplicate mark down describing algos

Approved-by: Michael Harding <michael.harding@bluetradesys.com>
2019-08-08 20:26:11 +00:00
Kevin Darby 50768750d6 removing duplicate mark down describing algos 2019-08-08 16:14:49 -04:00
Jake Norbut 450ef7dd56 Merged in SP-128 (pull request #312)
SP-128 - Allow for configurable stickyness on Algo Favorites

Approved-by: Kevin Darby <kevin.darby@bluetradesys.com>
2019-08-08 19:26:03 +00:00
Jake Norbut 89a4f9264a LadderSaveState now at version 2; implementing upgrade mechanism for migrating existing favorite algos to stickied algos 2019-08-08 13:03:26 -05:00
Jake Norbut 55ade15574 provide upgrade mechanism when loading IShellWindow 2019-08-08 13:01:19 -05:00
Kevin Darby 36b8b35e47 Merged in fix_tooltips2 (pull request #315)
fix non-dynamic and non-generic tooltips

Approved-by: Jake Norbut <jake.norbut@bluetradesys.com>
2019-08-08 16:18:29 +00:00
Kevin Darby 23bb872052 fix non-dynamic and non-generic tooltips 2019-08-08 12:09:48 -04:00
Kevin Darby 5a36af1ed8 more 2.8 release notes 2019-08-08 10:54:57 -04:00
Jake Norbut bc12a3bd42 Merged in SP-172 (pull request #313)
making login view a little wider and shorter so that error state doesn't look as bad

Approved-by: Kevin Darby <kevin.darby@bluetradesys.com>
2019-08-08 14:48:31 +00:00
Kevin Darby 4e831b5f89 Merged in spreader_nlegs_hedging (pull request #314)
RTM Spreader nlegs hedging - for Taha

Approved-by: Kevin Darby <kevin.darby@bluetradesys.com>
2019-08-08 14:33:18 +00:00
Kevin Darby d886327c1a Merge branch 'master' of bitbucket.org:bluetradesys/spark into spreader_nlegs_hedging 2019-08-08 09:59:46 -04:00
Kevin Darby 533ff8acf7 Merged in server_sdk_docs (pull request #310)
RTM SP-138, SP-139, SP-140 server sdk docs

Approved-by: Pedro Pinto <pedro.pinto+atlassian@bluetradesys.com>
2019-08-07 21:30:35 +00:00
Kevin Darby e64eaec240 lumping client doc changes in with server 2019-08-07 17:27:16 -04:00
Taha Afzal 02a30142b7 Fixing the tests 2019-08-07 11:24:22 -04:00
Taha Afzal 3937939c0a Bug in sells fixed (the LegPropertyData::trading_side() is already adjusted for the spreader side 2019-08-06 18:57:49 -04:00
Taha Afzal be4bfb6152 Hooked up the hedging price calculation to the UI 2019-08-06 17:27:16 -04:00
Jake Norbut 4ff1be11e2 making login view a little wider and shorter so that error state doesn't look as bad 2019-08-06 14:32:32 -05:00
John Colvin dad4c1bf9b ExecutionStrategyEditor uses VisualStates to disable name, ticks, and pricing controls after creation 2019-08-06 13:07:03 -05:00
John Colvin 40aa6c518a added hedge pricing controls to synth editor 2019-08-06 12:58:58 -05:00
Jake Norbut bf8df1d396 always push Limit onto the algo stack; henceforth known as the anchor 2019-08-06 10:24:59 -05:00
Taha Afzal 9f575fcdec Added spreader params for this functionality(recalc) 2019-08-06 10:37:44 -04:00
Taha Afzal a807a09bea Merge branch 'master' into spreader_nlegs_hedging 2019-08-05 22:50:39 -04:00
John Colvin d064af817c remove unreferenced '_sticky_algos' field 2019-08-05 15:51:21 -05:00
John Colvin 7b3c4b76bc LadderVM/OrderPropertiesEditorVM sticky/stack behavior 2019-08-05 15:36:57 -05:00
John Colvin 5de431f279 make LadderVM.send_order_command an IAsyncCommand 2019-08-05 15:36:57 -05:00
John Colvin 7b63d951f0 ShellSettingsDialogVM profilevm resets 'is_dirty' whenever the internal vm's resultant value equals the target value 2019-08-05 15:36:57 -05:00
John Colvin 018887980b LadderSettingsVM 'sticky buttons' impl reacts to FavoriteAlgoItem's value (algo) changes 2019-08-05 15:06:39 -05:00
John Colvin 8b4d649bd4 ExecuteAsync should return the Task directly (no need to await internally) 2019-08-05 15:06:39 -05:00
Jake Norbut 441d3c886b fixing improper use of is 2019-08-05 15:06:39 -05:00
Jake Norbut 472e32f558 removing empty new lines; leftovers from Dispatcher debugging 2019-08-05 15:06:39 -05:00
Jake Norbut 472c9252f9 adding Stay Enabled (sticky) checkbox to Favorites UI 2019-08-05 15:06:39 -05:00
Jake Norbut 98a9ad3ef2 reset order type after non-sticky order entry 2019-08-05 15:06:39 -05:00
Jake Norbut 7b237fedea adding sticky-related bits 2019-08-05 15:06:39 -05:00
Jake Norbut 7281aa8ff1 adding is_sticky property 2019-08-05 15:06:39 -05:00
Jake Norbut d915e2f064 setting algo_def_vm.is_sticky via CollectionChanged event (hmm) 2019-08-05 15:06:39 -05:00
Jake Norbut beb5d855b1 Dispatcher debuggering with John; think does not appear to work since the if condition is never met, but commiting this part of the pair-debugging experience 2019-08-05 15:06:39 -05:00
Jake Norbut 120b86aaae popuplating stickied algo keys for persistence/restoration state 2019-08-05 15:06:39 -05:00
Jake Norbut 44eeff98e7 adding is_sticky member to which the view will Databind 2019-08-05 15:06:39 -05:00
Jake Norbut dc420a097a adding stickied_algos ProtoMember for persistence 2019-08-05 15:06:39 -05:00
Jake Norbut 69ee85dea9 misc - adding OnDispatcher after discussing with John 2019-08-05 15:06:39 -05:00
Kevin Darby bd451f6f65 SP-138, SP-139, SP-140 server sdk docs 2019-08-05 14:29:13 -04:00
Taha Afzal dc922a0299 Fixed the test that was failing when Spreader:n_legs_recomp_hedges_on_fill: true 2019-07-08 14:01:24 -04:00
Taha Afzal 729acc4ad5 deleted default constructors and assignment operators on NLegsHedgeRecompData plus tightened a condition for application of recompute redhedging 2019-07-07 20:52:42 -04:00
Taha Afzal 4d559b8ec1 Reorganized the data for NLeg Hedge Recomp better 2019-07-05 11:16:24 -04:00
Taha Afzal 2561cb3960 Better comments 2019-07-04 19:59:21 -04:00
Taha Afzal c4ba25bdae Merge branch 'master' into spreader_nlegs_hedging 2019-07-04 11:18:51 -04:00
Taha Afzal 7563eb7afe Merge branch 'master' into spreader_nlegs_hedging 2019-06-10 08:30:58 -04:00
Taha Afzal 1b4275db4c Merge branch 'master' into spreader_nlegs_hedging 2019-05-23 16:42:28 -04:00
Taha Afzal 592ad39a32 tests pass 2019-05-23 12:37:30 -04:00
Taha Afzal 1fd66a17ca better tests 2019-05-20 19:57:18 -04:00
Taha Afzal 3ec896d609 code complete, testing remains 2019-05-17 19:51:37 -04:00
Taha Afzal 8f1eab57b7 Basic functions in, need to be hooked 2019-05-17 18:22:36 -04:00
61 changed files with 1278 additions and 374 deletions

No files matched your search

+2 -2
View File
@@ -135,13 +135,13 @@
"name": "Spreader Tests",
"type": "cppdbg",
"request": "launch",
"program": "/home/bts/spark/build/ninja_debug/src/server/sparkd/sparkd",
"program": "/home/bts/spark/build/ninja_debug/server/sparkd",
"args": [
"test",
"[spreader]"
],
"stopAtEntry": false,
"cwd": "/home/bts/spark/build/ninja_debug/src/server/sparkd/",
"cwd": "/home/bts/spark/build/ninja_debug/server/",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
+1 -1
View File
@@ -1 +1 @@
set(sources /home/ppinto/Dropbox/bts/spark/doc/user/build.sh;content/_index.md;content/bts_spark/Algos/_index.md;content/bts_spark/Glossary/index.md;content/bts_spark/Help/about_spark.png;content/bts_spark/Help/image39.png;content/bts_spark/Help/image58.png;content/bts_spark/Help/index.md;content/bts_spark/Launcher/image38.png;content/bts_spark/Launcher/image68.png;content/bts_spark/Launcher/index.md;content/bts_spark/Logging-In-to-the-System/image3.png;content/bts_spark/Logging-In-to-the-System/image64.png;content/bts_spark/Logging-In-to-the-System/index.md;content/bts_spark/Market/change_securities.png;content/bts_spark/Market/image11.png;content/bts_spark/Market/image14.png;content/bts_spark/Market/image20.png;content/bts_spark/Market/image21.png;content/bts_spark/Market/image23.png;content/bts_spark/Market/image24.png;content/bts_spark/Market/image34.png;content/bts_spark/Market/image49.png;content/bts_spark/Market/image53.png;content/bts_spark/Market/image66.png;content/bts_spark/Market/image69.png;content/bts_spark/Market/index.md;content/bts_spark/Market/market_view.png;content/bts_spark/Market/settings_icon.png;content/bts_spark/Market/time_and_sales.png;content/bts_spark/My-Windows/image15.png;content/bts_spark/My-Windows/image16.png;content/bts_spark/My-Windows/image37.png;content/bts_spark/My-Windows/index.md;content/bts_spark/Settings/image51.png;content/bts_spark/Settings/image9.png;content/bts_spark/Settings/index.md;content/bts_spark/Spreader/image10.png;content/bts_spark/Spreader/image13.png;content/bts_spark/Spreader/image18.png;content/bts_spark/Spreader/image19.png;content/bts_spark/Spreader/image28.png;content/bts_spark/Spreader/image29.png;content/bts_spark/Spreader/image31.png;content/bts_spark/Spreader/image35.png;content/bts_spark/Spreader/image40.png;content/bts_spark/Spreader/image43.png;content/bts_spark/Spreader/image54.png;content/bts_spark/Spreader/image55.png;content/bts_spark/Spreader/image56.png;content/bts_spark/Spreader/image6.png;content/bts_spark/Spreader/image7.png;content/bts_spark/Spreader/image70.png;content/bts_spark/Spreader/image72.png;content/bts_spark/Spreader/image8.png;content/bts_spark/Spreader/index.md;content/bts_spark/Trading/algo_studio.png;content/bts_spark/Trading/collapse_all_icon.png;content/bts_spark/Trading/cover_algo_control.png;content/bts_spark/Trading/expand_all_icon.png;content/bts_spark/Trading/image1.png;content/bts_spark/Trading/image17.png;content/bts_spark/Trading/image2.png;content/bts_spark/Trading/image25.png;content/bts_spark/Trading/image27.png;content/bts_spark/Trading/image33.png;content/bts_spark/Trading/image42.png;content/bts_spark/Trading/image44.png;content/bts_spark/Trading/image47.png;content/bts_spark/Trading/image48.png;content/bts_spark/Trading/image5.png;content/bts_spark/Trading/image50.png;content/bts_spark/Trading/image52.png;content/bts_spark/Trading/image57.png;content/bts_spark/Trading/image59.png;content/bts_spark/Trading/image60.png;content/bts_spark/Trading/image61.png;content/bts_spark/Trading/image62.png;content/bts_spark/Trading/image73.png;content/bts_spark/Trading/image74.png;content/bts_spark/Trading/index.md;content/bts_spark/Trading/join_algo_control.png;content/bts_spark/Trading/ladder.png;content/bts_spark/Trading/ladder_badges.png;content/bts_spark/Trading/ladder_main_part.png;content/bts_spark/Trading/lean_algo_control.png;content/bts_spark/Trading/mini_orderbook.png;content/bts_spark/Trading/oco_algo_control.png;content/bts_spark/Trading/offset_algo_control.png;content/bts_spark/Trading/pnl_calculation.png;content/bts_spark/Trading/pnl_window.png;content/bts_spark/Trading/recreate_icon.png;content/bts_spark/Trading/settings_icon.png;content/bts_spark/Trading/spark_menu_order_book.png;content/bts_spark/Trading/top_algo_control.png;content/bts_spark/Trading/trigger_algo_control.png;content/bts_spark/_index.md;content/release_notes/_index.md;content/system_requirements/_index.md;static/book.js;static/favicon.ico;static/image.js;templates/index.html;templates/page.html;templates/section.html;templates/shortcodes/back_button.html)
set(sources /home/ppinto/Dropbox/bts/spark/doc/user/build.sh;content/_index.md;content/bts_spark/Glossary/_index.md;content/bts_spark/Help/_index.md;content/bts_spark/Help/about_spark.png;content/bts_spark/Help/image39.png;content/bts_spark/Help/image58.png;content/bts_spark/Launcher/_index.md;content/bts_spark/Launcher/image38.png;content/bts_spark/Launcher/image68.png;content/bts_spark/Logging-In-to-the-System/_index.md;content/bts_spark/Logging-In-to-the-System/image3.png;content/bts_spark/Logging-In-to-the-System/image64.png;content/bts_spark/Market/_index.md;content/bts_spark/Market/change_securities.png;content/bts_spark/Market/image11.png;content/bts_spark/Market/image14.png;content/bts_spark/Market/image20.png;content/bts_spark/Market/image21.png;content/bts_spark/Market/image23.png;content/bts_spark/Market/image24.png;content/bts_spark/Market/image34.png;content/bts_spark/Market/image49.png;content/bts_spark/Market/image53.png;content/bts_spark/Market/image66.png;content/bts_spark/Market/image69.png;content/bts_spark/Market/market_view.png;content/bts_spark/Market/settings_icon.png;content/bts_spark/Market/time_and_sales.png;content/bts_spark/My-Windows/_index.md;content/bts_spark/My-Windows/image15.png;content/bts_spark/My-Windows/image16.png;content/bts_spark/My-Windows/image37.png;content/bts_spark/Settings/_index.md;content/bts_spark/Settings/image51.png;content/bts_spark/Settings/image9.png;content/bts_spark/Spreader/_index.md;content/bts_spark/Spreader/image10.png;content/bts_spark/Spreader/image13.png;content/bts_spark/Spreader/image18.png;content/bts_spark/Spreader/image19.png;content/bts_spark/Spreader/image28.png;content/bts_spark/Spreader/image29.png;content/bts_spark/Spreader/image31.png;content/bts_spark/Spreader/image35.png;content/bts_spark/Spreader/image40.png;content/bts_spark/Spreader/image43.png;content/bts_spark/Spreader/image54.png;content/bts_spark/Spreader/image55.png;content/bts_spark/Spreader/image56.png;content/bts_spark/Spreader/image6.png;content/bts_spark/Spreader/image7.png;content/bts_spark/Spreader/image70.png;content/bts_spark/Spreader/image72.png;content/bts_spark/Spreader/image8.png;content/bts_spark/Trading/OrderTypes/index.md;content/bts_spark/Trading/_index.md;content/bts_spark/Trading/algo_studio.png;content/bts_spark/Trading/collapse_all_icon.png;content/bts_spark/Trading/cover_algo_control.png;content/bts_spark/Trading/expand_all_icon.png;content/bts_spark/Trading/image1.png;content/bts_spark/Trading/image17.png;content/bts_spark/Trading/image2.png;content/bts_spark/Trading/image25.png;content/bts_spark/Trading/image27.png;content/bts_spark/Trading/image33.png;content/bts_spark/Trading/image42.png;content/bts_spark/Trading/image44.png;content/bts_spark/Trading/image47.png;content/bts_spark/Trading/image48.png;content/bts_spark/Trading/image5.png;content/bts_spark/Trading/image50.png;content/bts_spark/Trading/image52.png;content/bts_spark/Trading/image57.png;content/bts_spark/Trading/image59.png;content/bts_spark/Trading/image60.png;content/bts_spark/Trading/image61.png;content/bts_spark/Trading/image62.png;content/bts_spark/Trading/image73.png;content/bts_spark/Trading/image74.png;content/bts_spark/Trading/join_algo_control.png;content/bts_spark/Trading/ladder.png;content/bts_spark/Trading/ladder_badges.png;content/bts_spark/Trading/ladder_main_part.png;content/bts_spark/Trading/lean_algo_control.png;content/bts_spark/Trading/mini_orderbook.png;content/bts_spark/Trading/oco_algo_control.png;content/bts_spark/Trading/offset_algo_control.png;content/bts_spark/Trading/pnl_calculation.png;content/bts_spark/Trading/pnl_window.png;content/bts_spark/Trading/recreate_icon.png;content/bts_spark/Trading/settings_icon.png;content/bts_spark/Trading/spark_menu_order_book.png;content/bts_spark/Trading/top_algo_control.png;content/bts_spark/Trading/trigger_algo_control.png;content/bts_spark/_index.md;content/release_notes/_index.md;content/system_requirements/_index.md;static/book.js;static/favicon.ico;static/image.js;templates/index.html;templates/page.html;templates/section.html;templates/shortcodes/back_button.html)
+16 -1
View File
@@ -4,6 +4,17 @@ weight = 3
sort_by = "weight"
insert_anchor_links = "right"
+++
## 2.8.3
### Bug Fixes
- Fixed a bug that could cause an OrderBook's Security column filter to be blank
- Fixed a bug that could cause a UI failure when clearing a filter selection on a filtering widget
## 2.8.2
### Bug Fixes
- Added proper display factors for SOM spreads
- Fixed a bug that could cause a UI failure when trying to change settings in a synthetic ladder
## 2.8.1
### Bug fixes
- Fixed an error in the UI grids filtering widget
## 2.8.0
### User Visible Changes
- Added ProRata and Scratch algos
@@ -14,6 +25,9 @@ insert_anchor_links = "right"
- Fixed a bug that cause cause a failure on startup if the user
loaded a workspace with a Ladder that had a dynamic order type
selected by default
- Increased width of login panel to better show login error messages
- Added optional 'Maker/Taker' pricing to Spreader algo
- Algo buttons in ladder can now be made to deactivate after launching an algo or remain 'sticky'
### Internal changes
- Made it easier to generate simple UI's for new order types
### API Changes
@@ -362,7 +376,8 @@ insert_anchor_links = "right"
- The zoom slider can be enabled from Ladder Form -> Settings button -> Left Pane tab -> check Zoom Slider checkbox
- The zoom functionality can also be performed via hotkey and mouse wheel combinations
- Zoom In = CTRL + Mouse wheel up
- Zoom Out = CTRL + Mouse wheel down␍
- Zoom Out = CTRL + Mouse wheel down
- Reset zoom = CTRL + Mouse wheel click or double click on the zoom slider
### Exchange simulator
- Improved the exchange simulator to track real market data more closely
@@ -374,6 +374,72 @@
Height="{TemplateBinding Height}"
Padding="{TemplateBinding Padding}"
>
<Border.Resources>
<!--Leg Count States-->
<sys:String x:Key="LegCountStates">LegCountStates</sys:String>
<sys:String x:Key="LegCountStates.TwoOrFewer">TwoOrFewerLegsState</sys:String>
<sys:String x:Key="LegCountStates.ThreeOrMore">ThreeOrMoreLegsState</sys:String>
<cv:ValueConverterPipe x:Key="LegCountStateConverter">
<cv:IntGreaterThanConverter Value="2"/>
<cv:BooleanToObjectConverter ValueForFalse="{StaticResource LegCountStates.TwoOrFewer}" ValueForTrue="{StaticResource LegCountStates.ThreeOrMore}"/>
</cv:ValueConverterPipe>
<!--Persistance States-->
<sys:String x:Key="PersistanceStates">PersistanceStates</sys:String>
<sys:String x:Key="PersistanceStates.Unpersisted">UnpersistedState</sys:String>
<sys:String x:Key="PersistanceStates.Persisted">PersistedState</sys:String>
<cv:BooleanToObjectConverter x:Key="PersistanceStateConverter" ValueForFalse="{StaticResource PersistanceStates.Persisted}" ValueForTrue="{StaticResource PersistanceStates.Unpersisted}"/>
</Border.Resources>
<u:StateManager.Groups>
<u:StateGroupsManager AttachToMembers="True">
<u:StateDefinitionCollection>
<u:StateDefinition State="{Binding Group.Target.TemplatedParent.LegTuples.Count, RelativeSource={RelativeSource Self}, Converter={StaticResource LegCountStateConverter}}"/>
<u:StateDefinition State="{Binding Group.Target.TemplatedParent.IsNew, RelativeSource={RelativeSource Self}, Converter={StaticResource PersistanceStateConverter}}"/>
</u:StateDefinitionCollection>
</u:StateGroupsManager>
</u:StateManager.Groups>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="{StaticResource LegCountStates}">
<VisualState Name="{StaticResource LegCountStates.TwoOrFewer}"/>
<VisualState Name="{StaticResource LegCountStates.ThreeOrMore}">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_HedgePricing_Label" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_HedgePricing_DropDown" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup Name="{StaticResource PersistanceStates}">
<VisualState Name="{StaticResource PersistanceStates.Unpersisted}"/>
<VisualState Name="{StaticResource PersistanceStates.Persisted}">
<Storyboard>
<!--Name-->
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PART_Name_Label" Storyboard.TargetProperty="(UIElement.IsEnabled)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PART_Name_TextBox" Storyboard.TargetProperty="(UIElement.IsEnabled)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
<!--Tick Factors-->
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PART_TickFactors_Label" Storyboard.TargetProperty="(UIElement.IsEnabled)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PART_TickFactors_Picker" Storyboard.TargetProperty="(UIElement.IsEnabled)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
<!--Pricing-->
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PART_Pricing_Label" Storyboard.TargetProperty="(UIElement.IsEnabled)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="PART_Pricing_DropDown" Storyboard.TargetProperty="(UIElement.IsEnabled)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
@@ -388,8 +454,9 @@
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" IsEnabled="{TemplateBinding IsNew}">Name</TextBlock>
<TextBlock x:Name="PART_Name_Label" VerticalAlignment="Center" IsEnabled="{TemplateBinding IsNew}">Name</TextBlock>
<TextBox
x:Name="PART_Name_TextBox"
Grid.Column="1"
@@ -408,20 +475,37 @@
</u:Behavior.BindingUpdateGroups>
</TextBox>
<TextBlock
Grid.Column="2" VerticalAlignment="Center" Margin="{StaticResource Margin.LHeaderPanelItem}" Text="Ticks" IsEnabled="{TemplateBinding IsNew}"
x:Name="PART_TickFactors_Label"
Grid.Column="2"
VerticalAlignment="Center"
Margin="{StaticResource Margin.LHeaderPanelItem}"
Text="Ticks"
IsEnabled="True"
Visibility="{Binding LegTuples.Count, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource IntNotZeroVisibilityConverter}}"
/>
<c:TickFactorsPicker
x:Name="PART_TickFactorsPicker" Grid.Column="3" Margin="{StaticResource Margin.LHeaderPanelItem}" IsEnabled="{TemplateBinding IsNew}" HorizontalAlignment="Stretch"
x:Name="PART_TickFactors_Picker"
Grid.Column="3"
Margin="{StaticResource Margin.LHeaderPanelItem}"
HorizontalAlignment="Stretch"
IsEnabled="True"
SelectedTickFactors="{Binding TickFactors, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Visibility="{Binding LegTuples.Count, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource IntNotZeroVisibilityConverter}}"
/>
<TextBlock Grid.Column="4" VerticalAlignment="Center" Margin="{StaticResource Margin.LHeaderPanelItem}" IsEnabled="{TemplateBinding IsNew}" >Pricing</TextBlock>
<TextBlock
x:Name="PART_Pricing_Label"
Grid.Column="4"
VerticalAlignment="Center"
Margin="{StaticResource Margin.LHeaderPanelItem}"
IsEnabled="True"
Text="Pricing"
/>
<ComboBox
x:Name="PART_Pricing_DropDown"
Grid.Column="5"
Margin="{StaticResource Margin.LHeaderPanelItem}"
Width="90"
IsEnabled="{TemplateBinding IsNew}"
IsEnabled="True"
ItemsSource="{x:Static usp:ExecutionStrategyEditor.PriceCalcItems}"
SelectedItem="{Binding price_calc}"
>
@@ -431,6 +515,24 @@
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock
Grid.Column="6"
x:Name="PART_HedgePricing_Label"
VerticalAlignment="Center"
Margin="{StaticResource Margin.LHeaderPanelItem}"
Text="Hedge"
Visibility="Collapsed"
/>
<ComboBox
x:Name="PART_HedgePricing_DropDown"
Grid.Column="7"
HorizontalAlignment="Stretch"
Margin="{StaticResource Margin.LHeaderPanelItem}"
ItemsSource="{TemplateBinding HedgePricingItemsSource}"
ItemTemplate="{StaticResource EnumDescriptionTemplate}"
SelectedItem="{Binding HedgePricing, RelativeSource={RelativeSource TemplatedParent}}"
Visibility="Collapsed"
/>
</Grid>
<c:DataGridEx
x:Name="PART_DataGrid"
@@ -8,6 +8,7 @@ using mbts.ui.utility;
using mbts.user.settings;
using mbts.utils;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
@@ -183,6 +184,29 @@ namespace mbts.ui.spark {
public mbts.spark.ContractPickerModel ContractPickerModel { get => GetValue(ContractPickerModelProperty) as mbts.spark.ContractPickerModel; set => SetValue(ContractPickerModelProperty, value); }
#endregion
#region HedgePricingItemsSource
public static readonly DependencyProperty HedgePricingItemsSourceProperty =
WPFHelper.create_dp<IEnumerable, ExecutionStrategyEditor>(
nameof(HedgePricingItemsSource));
public IEnumerable HedgePricingItemsSource {
get => GetValue(HedgePricingItemsSourceProperty) as IEnumerable;
set => SetValue(HedgePricingItemsSourceProperty, value);
}
#endregion
#region HedgePricing
public static readonly DependencyProperty HedgePricingProperty =
WPFHelper.create_dp<object, ExecutionStrategyEditor>(
nameof(HedgePricing),
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault);
public object HedgePricing {
get => GetValue(HedgePricingProperty);
set => SetValue(HedgePricingProperty, value);
}
#endregion
public override void OnApplyTemplate() =>
_connect_leg_tuples();
@@ -251,7 +275,7 @@ namespace mbts.ui.spark {
public ExecutionStrategyErrorAdorner(ExecutionStrategyEditor editor) : base(editor) {
_name_text_box = child_property<TextBox>("PART_Name_TextBox");
_tick_factors_picker = child_property<TickFactorsPicker>("PART_TickFactorsPicker");
_tick_factors_picker = child_property<TickFactorsPicker>("PART_TickFactors_Picker");
}
protected override void OnRender(DrawingContext drawing_context) {
@@ -34,6 +34,8 @@
LegTuples="{Binding leg_tuples}"
RemoveLegCommand="{Binding remove_leg}"
ContractPickerModel="{Binding contract_picker_model}"
HedgePricing="{Binding hedge_pricing}"
HedgePricingItemsSource="{Binding hedge_pricing_options}"
/>
<c:DialogSkirtOKCancel Grid.Row="1" OKCommand="{Binding commit}" CloseOnOK="False"/>
</Grid>
@@ -17,6 +17,7 @@ using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media;
using HedgePricing = bts.spark.ExecutionStrategy.Types.HedgePricing;
namespace mbts.spark {
/// <summary>
@@ -32,6 +33,7 @@ namespace mbts.spark {
bool _set_name_automatically, _set_ticks_automatically, _set_quantities_automatically, _set_price_mults_automatically, _is_setting_quantities, _is_setting_price_mults;
TickFactors _tick_factors;
ExecutionStrategyImmutable _strategy;
HedgePricing _hedge_pricing;
/// <summary>
/// Inititalizes a new instance of SyntheticEditorVM class. This constructor may only be used for already-existing synthetic securities (id must be non-zero).
@@ -294,6 +296,9 @@ namespace mbts.spark {
public IRaiseCanExecuteChangedCommand commit { get; }
public ICommand remove_leg { get; }
public ContractPickerModel contract_picker_model { get; }
// hedge pricing
public HedgePricing hedge_pricing { get => _hedge_pricing; set => Set(ref _hedge_pricing, value); }
public IEnumerable<HedgePricing> hedge_pricing_options => EnumHelper.get_values<HedgePricing>();
public ExecutionStrategyImmutable get_strategy() {
var mutable_strategy = _strategy.CloneToMutable();
@@ -301,6 +306,7 @@ namespace mbts.spark {
foreach (var lt in leg_tuples) {
mutable_strategy.LegParamsMap.Add(lt.leg.Security.Id, lt.leg_params);
}
mutable_strategy.HedgePricing = hedge_pricing;
return new ExecutionStrategyImmutable(mutable_strategy);
}
@@ -308,6 +314,7 @@ namespace mbts.spark {
_synthetic = synthetic.CloneToMutable();
_synthetic.Exchange = Venue.Bts;
_strategy = strategy;
hedge_pricing = strategy.HedgePricing;
leg_tuples.SetItems(_get_legs(_synthetic, strategy));
RaisePropertyChanged(nameof(name), nameof(tick_factors));
}
@@ -514,6 +514,8 @@
RemoveLegCommand="{Binding remove_leg}"
ContractPickerModel="{Binding contract_picker_model}"
IsEnabled="{Binding IsReadOnly, RelativeSource={RelativeSource AncestorType=usp:AlgoEditorGridView}, Converter={StaticResource NotConverter}}"
HedgePricing="{Binding hedge_pricing}"
HedgePricingItemsSource="{Binding hedge_pricing_options}"
/>
</AdornerDecorator>
</DataTemplate>
@@ -10,7 +10,7 @@ using System.Reactive.Disposables;
namespace mbts.spark {
static class AlgoParamRowsHelper {
public static IDisposable connect(AlgoDefinitionVM algo, ObservableAggregateCollection<AlgoParamRowVM> rows, bool include_algo_type_rows) =>
algo == null ? null : new CompositeDisposable(algo.observe_algo_root().SubscribeEach(a => {
algo == null ? null : new CompositeDisposable(algo.observe_algo_root().OnDispatcher().SubscribeEach(a => {
rows.clear_collections();
if (a == null)
return Disposable.empty;
@@ -77,7 +77,7 @@ namespace mbts.spark {
include_algo_type_rows ?
(ObservableCollection<AlgoParamRowVM>)new ObservableAppendCollection<AlgoParamRowVM>(child_rows, selector_wrapper) :
child_rows,
s.subscribe_selected_algo().SubscribeEach(a => {
s.subscribe_selected_algo().OnDispatcher().SubscribeEach(a => {
s.value = a;
child_rows.clear_collections();
return _wrap_rows(a, selector_wrapper, child_rows, include_algo_type_rows);
@@ -194,20 +194,27 @@ namespace mbts.spark {
readonly bts.persist.algo.AlgoPersistedKey[] _favorite_algos;
[ProtoMember(2)]
public readonly int column_count;
[ProtoMember(3)]
readonly bts.persist.algo.AlgoPersistedKey[] _stickied_algos;
public LadderFavoriteAlgosSettings(AlgoKey[] favorite_algos, int column_count)
: this(ArrayHelper.safe_convert(favorite_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted)), column_count) { }
public LadderFavoriteAlgosSettings(AlgoKey[] favorite_algos, int column_count, AlgoKey[] stickied_algos)
: this(ArrayHelper.safe_convert(favorite_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted)),
column_count,
ArrayHelper.safe_convert(stickied_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted))) { }
LadderFavoriteAlgosSettings(bts.persist.algo.AlgoPersistedKey[] favorite_algos, int column_count) {
LadderFavoriteAlgosSettings(bts.persist.algo.AlgoPersistedKey[] favorite_algos, int column_count, bts.persist.algo.AlgoPersistedKey[] stickied_algos) {
_favorite_algos = favorite_algos;
this.column_count = column_count;
_stickied_algos = stickied_algos;
}
public IReadOnlyList<AlgoKey> favorite_algos => ArrayHelper.safe_convert(_favorite_algos, k => k.to_algo_key());
public IReadOnlyList<AlgoKey> stickied_algos => ArrayHelper.safe_convert(_stickied_algos, k => k.to_algo_key());
public bool Equals(LadderFavoriteAlgosSettings other) =>
column_count == other.column_count &&
favorite_algos.SequenceEqual(other.favorite_algos);
favorite_algos.SequenceEqual(other.favorite_algos) &&
stickied_algos.SequenceEqual(other.stickied_algos);
public override bool Equals(object obj) =>
EqualityComparer.equals_obj(this, obj);
@@ -215,7 +222,8 @@ namespace mbts.spark {
public override int GetHashCode() =>
EqualityComparer.aggregate_hash(
column_count,
EqualityComparer.aggregate_hash_limited(favorite_algos));
EqualityComparer.aggregate_hash_limited(favorite_algos),
EqualityComparer.aggregate_hash_limited(stickied_algos));
public static bool operator ==(LadderFavoriteAlgosSettings a, LadderFavoriteAlgosSettings b) => a.Equals(b);
public static bool operator !=(LadderFavoriteAlgosSettings a, LadderFavoriteAlgosSettings b) => !a.Equals(b);
@@ -273,7 +281,7 @@ namespace mbts.spark {
order_entry_panel_initial_width = _default_order_entry_panel_width;
zoom_factor = _default_zoom_factor;
use_defaults = true;
favorite_algos = new LadderFavoriteAlgosSettings(null, 2);
favorite_algos = new LadderFavoriteAlgosSettings(null, 2, null);
show_warn_on_cross = _default_show_warn_on_cross;
}
@@ -11,6 +11,7 @@ using ProtoBuf;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
@@ -22,6 +23,7 @@ using LadderSettings = mbts.spark.LadderSettings;
namespace bts.shell {
class LadderWindowFactory : ShellWindowFactory<LadderSaveState> {
const string _window_type = "ladder";
const int _version_where_stickied_algos_introduced = 2;
readonly LadderConfig _ladder_conf;
readonly IBus _bus;
readonly IWindowManager _wm;
@@ -38,7 +40,7 @@ namespace bts.shell {
OrdersModel orders_model,
MBOService mbo)
: base(owner, "SparkLadder") {
: base(owner, "SparkLadder", 2) {
_bus = bus;
_wm = wm;
_settings_hub = settings_hub;
@@ -60,6 +62,16 @@ namespace bts.shell {
return null;
}
protected override Task<IShellWindow> try_upgrade_state(Stream load_stream, int version) {
var state = ProtoBuf.Serializer.DeserializeWithLengthPrefix<LadderSaveState>(load_stream, ProtoBuf.PrefixStyle.Fixed32);
if (version < _version_where_stickied_algos_introduced) {
// We want to assign any existing favorite algos to stickied algos upon setting upgrade
var favorite_algos_array = state.settings.favorite_algos.favorite_algos.ToArray();
state.settings.favorite_algos = new LadderFavoriteAlgosSettings(favorite_algos_array, state.settings.favorite_algos.column_count, favorite_algos_array);
}
return load(state);
}
LadderSaveState _get_state(LadderVM vm, uint id) {
LadderSettings s = vm.get_save_state();
if (id != 0) {
@@ -2,6 +2,7 @@
using bts.api;
using bts.api.orderman;
using bts.collections;
using bts.persist.algo;
using bts.shell.orderbook;
using bts.utils;
using mbts.collections;
@@ -136,7 +137,7 @@ namespace mbts.spark {
c.PropertyChanged -= on_prop_changed;
}
AccountTuple? account_factory(KeyValuePair<uint, string> kv) => new AccountTuple(kv.Key, kv.Value);
AlgoDefinitionVM algo_factory(AlgoData data) => AlgoDefinitionVM.create(_model, data);
AlgoDefinitionVM algo_factory(AlgoData data) => AlgoDefinitionVM.create(_model, data, is_synthetic ? AlgoFormats.Spreader : AlgoFormats.Exchange);
}
public event Action result_changed;
@@ -723,12 +724,15 @@ namespace mbts.spark {
readonly IObservableCollection<AlgoDefinitionVM> _algo_definitions;
readonly ObservableCollection<FavoriteAlgoItem> _raw_items = new ObservableCollection<FavoriteAlgoItem>();
int _column_count = 2;
HashSet<AlgoPersistedKey> _sticky_algo_keys;
IDisposable _sticky_algos_hook;
public FavoriteAlgosVM(IObservableCollection<AlgoDefinitionVM> algo_definitions) {
_algo_definitions = algo_definitions;
items = new ObservableAggregateCollection<FavoriteAlgoItem>(_raw_items, new ObservableCollection<FavoriteAlgoItem> { FavoriteAlgoItem.AddButtonPlaceholderItem });
add_item_cmd = new DelegateCommand(() => _raw_items.Add(_item_factory()));
remove_item_cmd = new DelegateCommand<FavoriteAlgoItem>(fai => _raw_items.Remove(fai));
_dispose = Disposable.Create(() => Disposable.dispose(ref _sticky_algos_hook));
}
public ObservableCollection<FavoriteAlgoItem> items { get; }
@@ -745,6 +749,17 @@ namespace mbts.spark {
fai.selector.try_select(k);
return fai;
}));
_sticky_algo_keys = new HashSet<AlgoPersistedKey>(value.stickied_algos.Where(k => k.is_persisted).Select(x => new AlgoPersistedKey(x.persisted)));
Disposable.replace(ref _sticky_algos_hook,
ObservableAutoWrapper.connect_item_hooks(_raw_items, x =>
x.selector.subscribe_value().Subscribe(algo => {
if (algo != null &&
algo.key.is_persisted &&
(x.is_sticky = _sticky_algo_keys.Remove(new AlgoPersistedKey(algo.key.persisted))) &&
_sticky_algo_keys.Count == 0)
//
Disposable.dispose(ref _sticky_algos_hook);
})));
}
public LadderFavoriteAlgosSettings create() =>
@@ -753,7 +768,13 @@ namespace mbts.spark {
.Where(k => k.HasValue && k.Value.is_persisted)
.Select(k => k.Value)
.ToArray(),
column_count);
column_count,
_raw_items
.Where(fai => fai.is_sticky)
.Select(fai => fai.algo_definition?.key ?? fai.selector.desired_key)
.Where(k => k.HasValue && k.Value.is_persisted)
.Select(k => k.Value)
.ToArray());
FavoriteAlgoItem _item_factory() =>
new FavoriteAlgoItem(_algo_definitions, new ListCollectionView<AlgoDefinitionVM>(_algo_definitions) {
@@ -766,6 +787,7 @@ namespace mbts.spark {
public static readonly FavoriteAlgoItem AddButtonPlaceholderItem = new _AddButtonPlaceholderItem();
internal readonly KeyedItemSelector<AlgoDefinitionVM, AlgoKey> selector;
bool _is_sticky;
protected FavoriteAlgoItem() { }
@@ -776,6 +798,7 @@ namespace mbts.spark {
public ICollectionView<AlgoDefinitionVM> algo_definitions_view { get; }
public AlgoDefinitionVM algo_definition { get => selector.value; set => selector.value = value; }
public bool is_sticky { get => _is_sticky; set => Set(ref _is_sticky, value); }
class _AddButtonPlaceholderItem : FavoriteAlgoItem, ITemplateSelectorKey {
public string key => LadderSettingsView.FavoriteAlgoAddButtonTemplateKey;
@@ -1,9 +1,11 @@
using bts.api;
using bts.api.orderman;
using bts.collections;
using bts.shell;
using bts.spark;
using bts.utils;
using mbts.co2;
using mbts.spark.utilities;
using mbts.ui;
using mbts.ui.shell;
using mbts.utils;
@@ -32,6 +34,7 @@ namespace mbts.spark {
_show_tif, _show_order_type, _show_size_preset, _show_auto_clear, _show_clear, _show_cancel_buys,
_show_cancel_sells, _show_cancel_all, _show_zoom;
readonly PropertyAutoWrapper<LadderSettings, Brush> _bid_background, _bid_foreground, _ask_background, _ask_foreground;
readonly HashSet<AlgoKey> _sticky_algos = new HashSet<AlgoKey>();
double _position, _day_position;
bool _show_account_position, _show_day_position;
ulong _misc_time = 0;
@@ -133,7 +136,7 @@ namespace mbts.spark {
//_window_height = backing(nameof(window_height), settings_manager.subscribe_current().OnDispatcher().Select(s => s.zoom_factor), (scale) => scale * 600);
//_window_width = backing(nameof(window_width), settings_manager.subscribe_current().OnDispatcher().Select(s => s.zoom_factor), (scale) => scale * 420);
position_click_command = new DelegateCommand(() => size_calculator.value = DoubleHelper.safe_convert_to_uint(Math.Abs(_show_day_position ? day_position : position)));
send_order_command = new DelegateCommand<(double price, Side? side, MouseButton button)>(send_order);
send_order_command = new AsyncCommand<(double price, Side? side, MouseButton button)>(send_order_async);
cancel_command = new AsyncCommand<LadderModel.CancelType>(_model.cancel_orders, true);
show_book_command = new DelegateCommand(_show_book);
show_ticket_command = new DelegateCommand(_show_ticket);
@@ -223,7 +226,10 @@ namespace mbts.spark {
.SelectManyInSeries(a => _model.order_gateway.on_security_positions(security.Id)
.Select(table => table.state.Values.FirstOrDefault(pos => pos.Item2.Account == a, tup => tup.Item2, (bts.api.position.PositionUnitImmutable?)null)));
return Disposable.Create(
settings.OnDispatcher().Subscribe(s => order_properties_vm.on_favorite_algos(s.favorite_algos)),
settings.OnDispatcher().Subscribe(s => {
_sticky_algos.SetItems(s.favorite_algos.stickied_algos);
order_properties_vm.on_favorite_algos(s.favorite_algos);
}),
order_properties_vm,
position_src.OnDispatcher().Subscribe(pos => {
double total, day;
@@ -400,20 +406,19 @@ namespace mbts.spark {
settings_invalidated?.Invoke();
}
public void send_order((double price, Side? side, MouseButton button) args) {
if (order_properties_vm == null || args.button == MouseButton.Middle)
return;
var size_from_alternate = args.button == MouseButton.Right;
if (DoubleHelper.IsNaNOrInfinity(args.price) || !args.side.HasValue || HasErrors || order_properties_vm.HasErrors || (size_from_alternate && current_settings.alternate_order_size == 0)) {
return;
}
if (!size_from_alternate && (!size_calculator.value.HasValue || size_calculator.value.Value == 0)) {
size_calculator.flash_error();
}
else {
uint size = size_from_alternate ? current_settings.alternate_order_size : (uint)Math.Abs(size_calculator.value ?? 0);
send_order_async(args.side.Value, size, args.price).ignore();
public Task send_order_async((double price, Side? side, MouseButton button) args) {
if (order_properties_vm != null && args.button != MouseButton.Middle) {
var size_from_alternate = args.button == MouseButton.Right;
if (!DoubleHelper.IsNaNOrInfinity(args.price) && args.side.HasValue && !HasErrors && !order_properties_vm.HasErrors && (!size_from_alternate || current_settings.alternate_order_size > 0)) {
if (!size_from_alternate && (!size_calculator.value.HasValue || size_calculator.value.Value == 0)) {
size_calculator.flash_error();
} else {
uint size = size_from_alternate ? current_settings.alternate_order_size : (uint)Math.Abs(size_calculator.value ?? 0);
return send_order_async(args.side.Value, size, args.price);
}
}
}
return Task.CompletedTask;
}
public async Task send_order_async(Side side, uint size, double price) {
@@ -433,6 +438,13 @@ namespace mbts.spark {
await _model.order_gateway.send_order(order, price, size);
if (auto_clear)
size_calculator.value = 0;
var fav_algo = order_properties_vm.selected_favorite_algo_definition;
if (fav_algo != null && !_sticky_algos.Contains(fav_algo.key) && !order_properties_vm.try_pop_selected_algo_definition()) {
var key = new AlgoKey(OrderDataHelper.get_default_algo(OrderDataHelper.get_algo_format(security.ContractCase)));
if (order_properties_vm.try_get_algo_definition(key, out var r)) {
order_properties_vm.selected_algo_definition = r;
}
}
}
void _update_header() {
@@ -805,6 +805,7 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="c0"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="c1"/>
</Grid.ColumnDefinitions>
<Button Command="{Binding DataContext.remove_item_cmd, RelativeSource={RelativeSource AncestorType=ItemsControl}}" CommandParameter="{Binding}" Style="{StaticResource RoundCloseButton}"/>
<ComboBox Grid.Column="1" ItemsSource="{Binding algo_definitions_view}" SelectedItem="{Binding algo_definition}">
@@ -814,6 +815,7 @@
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<CheckBox Grid.Column="2" VerticalAlignment="Center" VerticalContentAlignment="Center" IsChecked="{Binding is_sticky}"> Stay Enabled?</CheckBox>
</Grid>
</DataTemplate>
</u:KeyedTemplateSelector.Default>
@@ -823,6 +825,7 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="c0"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="c1"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="1" HorizontalAlignment="Stretch" Command="{Binding DataContext.add_item_cmd, RelativeSource={RelativeSource AncestorType=ItemsControl}}">Add</Button>
</Grid>
@@ -60,6 +60,7 @@ namespace mbts.spark {
readonly ListCollectionView<AlgoDefinitionVM> _algo_definitions_view, _favorite_algo_definitions_view;
readonly TableUpdateBuffer<AlgoData, AlgoKey> _definitions_buffer = new TableUpdateBuffer<AlgoData, AlgoKey>(d => d.key);
readonly ObservableAggregateCollection<AlgoParamRowVM> _algo_param_rows = new ObservableAggregateCollection<AlgoParamRowVM>();
readonly AlgoDefinitionVM the_anchor_algo_def_vm;
IReadOnlyDictionary<AlgoKey, AlgoDefinitionMetadata> _algo_metadata = DictionaryHelper.empty<AlgoKey, AlgoDefinitionMetadata>();
IReadOnlyDictionary<AlgoKey, int> _favorite_algos_index = DictionaryHelper.empty<AlgoKey, int>();
IDisposable _algo_param_rows_hook;
@@ -68,6 +69,7 @@ namespace mbts.spark {
public OrderPropertiesEditorVM(OrdersModel model, IObservable<SecurityMD> security_md_source, IObservable<InlineOrderProperties> order_properties) {
_model = model;
the_anchor_algo_def_vm = AlgoDefinitionVM.create(_model, OrderDataHelper.Defaults.AlgoData(CustomOrderDefinition.CustomOneofCase.Limit));
var security_source = security_md_source.Select(smd => smd.security);
_security = backing(nameof(security), security_source, SecurityDataHelper.Defaults.SecurityImmutable);
security_source = _security.observe_current(true);
@@ -237,11 +239,15 @@ namespace mbts.spark {
void _selected_algo_definition_Changed(AlgoDefinitionVM old_value, AlgoDefinitionVM new_value, SelectionReason reason) {
Disposable.dispose(ref _algo_param_rows_hook);
if (old_value != null)
// Taha feels that we should always revert to a Limit order either when the user explicity unchecks a sticky button
// or when a non-sticky button is pressed. Rather than completely remove the stack at this time (b/c it may be come
// back in the future), let's just always push a specfic def_vm.key onto it [Limit] ;)
//_selected_algo_stack.Push(old_value.key);
_selected_algo_stack.Push(the_anchor_algo_def_vm.key);
if (new_value != null) {
if (use_algo_param_grid)
_algo_param_rows_hook = _connect_algo_param_rows(new_value, _algo_param_rows);
if (reason != SelectionReason.Explicit)
_selected_algo_stack.Push(new_value.key);
}
if (open_algo_popup_on_select) {
if (reason == SelectionReason.UserSelectedNewValue && new_value?.algo_root is IAlgoVM ar && ar.can_expand)
@@ -277,6 +283,18 @@ namespace mbts.spark {
get => _selected_algo_definition.selected_item;
set => _selected_algo_definition.selected_item = value;
}
public bool try_get_algo_definition(AlgoKey a, out AlgoDefinitionVM result) =>
_algo_definitions.TryGetValue(a, out result);
public bool try_pop_selected_algo_definition() {
if (_selected_algo_stack.TryPop(out AlgoKey k) && _algo_definitions.TryGetValue(k, out AlgoDefinitionVM vm)) {
_selected_algo_definition.select_explicit(vm);
return true;
}
return false;
}
public AlgoDefinitionVM selected_favorite_algo_definition {
get => selected_algo_definition?.is_favorite ?? false ? selected_algo_definition : null;
set {
@@ -353,6 +371,7 @@ namespace mbts.spark {
d.favorite_index = _get_favorite_algo_index(d.key);
}
favorite_algos_column_count = value.column_count;
RaisePropertyChanged(nameof(selected_favorite_algo_definition));
}
static IDisposable _connect_algo_param_rows(AlgoDefinitionVM def, ObservableAggregateCollection<AlgoParamRowVM> rows) =>
@@ -371,4 +390,4 @@ namespace mbts.spark {
algo_definitions_view.Refresh();
}
}
}
}
@@ -34,13 +34,14 @@ namespace bts.shell {
Disposable.dispose(ref _dispose);
}
public abstract Task<IShellWindow> load(T state);
protected virtual Task<IShellWindow> try_upgrade_state(Stream load_stream, int version) => null;
public Task<IShellWindow> load_window(Stream load_stream, int version) {
if (version == this.version) {
var t = ProtoBuf.Serializer.DeserializeWithLengthPrefix<T>(load_stream, ProtoBuf.PrefixStyle.Fixed32);
return load(t);
}
return null;
return try_upgrade_state(load_stream, version);
}
public void save(T data, Stream output) {
var header = new ShellSerializationHeader() {
@@ -110,10 +110,11 @@ namespace mbts.spark.filters {
class DynamicItemsFilter<TRow, TValue, TState> : FilterVMBase<TRow, TValue, TState>, IDisposable {
readonly IEqualityComparer<TValue> _equality_comparer;
readonly IComparer<TValue> _comparer;
readonly Func<ISet<TValue>, TState> _get_state;
readonly Func<TState, IObservable<IEnumerable<TValue>>> _load_state;
readonly HashSet<TValue> _items_set, _selected_items_set;
readonly ObservableCollection<TValue> _unsorted_items;
readonly ObservableCollection<TValue> _items = new ObservableCollection<TValue>();
bool _override_desired_selection;
IDisposable _desired_items_sub, _items_sub;
@@ -129,7 +130,7 @@ namespace mbts.spark.filters {
//
_items_sub = items.OnDispatcher().Subscribe(new_items => {
_items_set.SetItems(new_items.Concat(_selected_items_set));
_unsorted_items.sync_with(_items_set);
_sync_items();
});
}
@@ -148,7 +149,7 @@ namespace mbts.spark.filters {
_items_set.Remove(v);
foreach (var v in update.added)
_items_set.Add(v);
_unsorted_items.sync_with(_items_set);
_sync_items();
});
}
@@ -164,11 +165,12 @@ namespace mbts.spark.filters {
_get_state = get_state;
_load_state = load_state;
_equality_comparer = equality_comparer;
_comparer = comparer;
_selected_items_set = new HashSet<TValue>(_equality_comparer);
_items_set = new HashSet<TValue>(_equality_comparer);
_unsorted_items = new ObservableCollection<TValue>();
items = comparer != null ? ObservableAutoWrapper.create_sorted_wrapper(_unsorted_items, comparer) : ObservableAutoWrapper.create_read_only_wrapper(_unsorted_items);
items = ObservableAutoWrapper.create_read_only_wrapper(_items);
selected_items.CollectionChanged += _on_selected_items_CollectionChanged;
_sync_items();
}
public IReadOnlyObservableCollection<TValue> items { get; }
@@ -238,9 +240,11 @@ namespace mbts.spark.filters {
var copy = new HashSet<TValue>(_selected_items_set, _equality_comparer);
_selected_items_set.SetItems(dsi);
using (selected_items.SuspendHandler(_on_selected_items_CollectionChanged)) {
foreach (var item in _selected_items_set) {
if (_items_set.Add(item))
_unsorted_items.Add(item);
var to_add = _selected_items_set.Where(_items_set.Add);
if (_comparer != null) {
_items.InsertSorted(to_add, _comparer);
} else {
_items.AddRange(to_add);
}
selected_items.sync_with(_selected_items_set);
}
@@ -248,6 +252,14 @@ namespace mbts.spark.filters {
_raise_filter_changed();
}
}
void _sync_items() {
if (_comparer != null) {
_items.sync_with(_items_set.Ordered(_comparer));
} else {
_items.sync_with(_items_set);
}
}
}
class TableUpdateItemsFilter<TRow, TValue, TKey, TState> : FilterVMBase<TRow, TValue, TState>, IObserver<TableUpdate<TValue, TKey>> where TKey : struct, IEquatable<TKey> {
@@ -101,7 +101,8 @@ namespace mbts.ui.controls
case NotifyCollectionChangedAction.Replace:
if (e.OldItems != null) foreach (var item in e.OldItems) _set_is_selected(item, false);
if (e.NewItems != null) foreach (var item in e.NewItems) _set_is_selected(item, true); break;
case NotifyCollectionChangedAction.Reset: foreach (var item in ItemsSource) _set_is_selected(item, false); break;
case NotifyCollectionChangedAction.Reset:
if (ItemsSource != null) foreach (var item in ItemsSource) _set_is_selected(item, false); break;
}
_update_is_all_selected();
}
@@ -687,7 +687,10 @@
<ColumnDefinition Width="{Binding Source={StaticResource HorizontalPush3}}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center">Tick Offset</TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" >Tick Offset</TextBlock>
<c:HelpButton Margin="{StaticResource Margin.LP1}" ToolTip="How many ticks off the inside market to deploy the order, this guards against crossing the market inadventently" />
</StackPanel>
<c:TickUpDownUInt x:Name="PART_TickOffsetOnDeploy_TickUpDownUInt" Grid.Column="2" Value="{Binding tick_offset_on_deploy}"/>
<uag:AlgoPickerNodeView
x:Name="PART_Child_AlgoPickerNodeView"
@@ -905,7 +908,10 @@
<ColumnDefinition Width="{Binding Source={StaticResource HorizontalPush1}}" MaxWidth="{Binding Source={StaticResource HorizontalPush1}}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Margin="{StaticResource Margin.LP3}">Max Show Quantity</TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Margin="{StaticResource Margin.LP3}">Max Show Quantity</TextBlock>
<c:HelpButton Margin="{StaticResource Margin.LP3}" ToolTip="Maximum size to show on GLBX, this is the exchange provided iceberg" />
</StackPanel>
<c:TickUpDownNullableUInt x:Name="PART_MaxShowQuantity_TickUpDownNullableUInt" Grid.Column="2" HorizontalAlignment="Stretch" Value="{Binding max_show_quantity}"/>
</Grid>
</DataTemplate>
@@ -944,7 +950,10 @@
<ColumnDefinition Width="{Binding Source={StaticResource HorizontalPush1}}" MaxWidth="{Binding Source={StaticResource HorizontalPush1}}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Margin="{StaticResource Margin.LP3}">Show Quantity</TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Margin="{StaticResource Margin.LP3}">Show Quantity</TextBlock>
<c:HelpButton Margin="{StaticResource Margin.LP3}" ToolTip="Maximum size to show on exchange, this is the BTS provided iceberg" />
</StackPanel>
<c:TickUpDownDouble x:Name="PART_ShowQuantity_TickUpDownDouble" Grid.Column="2" HorizontalAlignment="Stretch" Value="{Binding show_quantity}"/>
<uag:AlgoPickerNodeView
x:Name="PART_Child_AlgoPickerNodeView"
@@ -1001,6 +1010,8 @@
LegTuples="{Binding leg_tuples}"
RemoveLegCommand="{Binding remove_leg}"
ContractPickerModel="{Binding contract_picker_model}"
HedgePricing="{Binding hedge_pricing}"
HedgePricingItemsSource="{Binding hedge_pricing_options}"
/>
<c:DialogSkirt Grid.Row="1" Margin="-4" VerticalAlignment="Top" RightItems="{Binding skirt_items}"/>
</Grid>
@@ -1020,9 +1031,16 @@
<ColumnDefinition Width="{Binding Source={StaticResource HorizontalPush1}}" MaxWidth="{Binding Source={StaticResource HorizontalPush1}}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="{StaticResource Margin.LP3}">Expose Quantity</TextBlock>
<StackPanel Orientation="Horizontal" Grid.Row="0" >
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="{StaticResource Margin.LP3}">Expose Quantity</TextBlock>
<c:HelpButton Margin="4,0,0,0" ToolTip="The quantity we want visible on the exchange" />
</StackPanel>
<c:TickUpDownUInt Grid.Column="2" HorizontalAlignment="Stretch" Value="{Binding exposed}"/>
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="{StaticResource Margin.LP3}">Max Order Quantity</TextBlock>
<StackPanel Orientation="Horizontal" Grid.Row="1" >
<TextBlock Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="{StaticResource Margin.LP3}">Max Order Quantity</TextBlock>
<c:HelpButton Margin="{StaticResource Margin.LP3}" ToolTip="No single order will have a quantity greater than this quantity (Clip Size)" />
</StackPanel>
<c:TickUpDownUInt Grid.Row="1" Grid.Column="2" HorizontalAlignment="Stretch" Value="{Binding max_order_qty}"/>
<uag:AlgoPickerNodeView
x:Name="PART_Child_AlgoPickerNodeView"
@@ -236,12 +236,12 @@ namespace mbts.ui {
throw new NotImplementedException("This ICommand does not implement IRaiseCanExecuteChanged");
}
public static async Task ExecuteAsync(this ICommand command, object parameter) {
public static Task ExecuteAsync(this ICommand command, object parameter) {
ExceptionAssert.Argument.NotNull(command, nameof(command));
if (command is IAsyncCommand acmd)
await acmd.Execute(parameter);
return acmd.Execute(parameter);
else
await Task.Run(() => command.Execute(parameter));
return Task.Run(() => command.Execute(parameter));
}
public static void TryExecuteIfCan(this ICommand command, object parameter) {
@@ -10,8 +10,8 @@
xmlns:autocomplete="clr-namespace:WPFTextBoxAutoComplete;assembly=WPFTextBoxAutoComplete"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Name="_login_view"
Width="460"
Height="254"
Width="520"
Height="230"
WindowStyle="None"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
@@ -27,7 +27,7 @@
</ui:StateManager.Groups>
<Window.Resources>
<ResourceDictionary>
<sys:Double x:Key="LoginControlPaddingLeft">40</sys:Double>
<sys:Double x:Key="LoginControlPaddingLeft">10</sys:Double>
<sys:Double x:Key="LoginControlPaddingTop">10</sys:Double>
<sys:Double x:Key="LoginControlPaddingRight">22</sys:Double>
<converters:BooleanToVisibilityConverter x:Key="InverseBoolToVisibility" VisibilityForFalse="Visible" VisibilityForTrue="Collapsed"/>
@@ -206,7 +206,7 @@
x:Name="_error_control"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
HorizontalAlignment="Left"
Visibility="Hidden"
Opacity="0"
>
@@ -251,10 +251,10 @@
<c:DialogSkirt x:Name="_dialog_skirt" Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
<c:DialogSkirt.RightItems>
<x:Array Type="{x:Type Button}">
<Button x:Name="_login_button" Width="60" Margin="10" IsDefault="True" IsHitTestVisible="True" Command="{Binding LoginCommand}">
<Button x:Name="_login_button" Width="60" Margin="10,0" IsDefault="True" IsHitTestVisible="True" Command="{Binding LoginCommand}">
Login
</Button>
<Button x:Name="_cancel_button" Width="60" Margin="10" IsCancel="True" IsHitTestVisible="True" Command="{Binding CancelCommand}">
<Button x:Name="_cancel_button" Width="60" Margin="10,0" IsCancel="True" IsHitTestVisible="True" Command="{Binding CancelCommand}">
Cancel
</Button>
</x:Array>
@@ -136,8 +136,8 @@ namespace mbts.spark {
var skip_local = profiles.WrapSkip(1);
var skip_local_wrapper = skip_local.WrapSelector(
p => new SettingsProfile<T>(p.id, p.name, p.value.create(), p.security_criteria),
ns => new ProfileVM(ns.id, vm_factory(ns.value), ns.name, ns.security_criteria));
profiles.Add(_local_profile = new ProfileVM(0, vm_factory(init), "Custom", template_key: ShellSettingsDialog.LocalProfileItemTemplateKey));
ns => new ProfileVM(ns.id, vm_factory(ns.value), ns.name, ns.security_criteria, target_value: ns.value));
profiles.Add(_local_profile = new ProfileVM(0, vm_factory(init), "Custom", template_key: ShellSettingsDialog.LocalProfileItemTemplateKey, target_value: init));
_selected_profile = backing(nameof(selected_profile), _local_profile);
// dialog skirt items
_apply_item = new DialogSkirtItem("Apply", new DelegateCommand(apply));
@@ -325,26 +325,37 @@ namespace mbts.spark {
//
SecurityCriteria _security_criteria;
SettingsProfile<T> _committed, _last_result;
T _target_value;
string _name, _template_key;
bool _is_selected;
IDisposable _dispose;
public ProfileVM(uint id, TVM value, string name, SecurityCriteria security_criteria = null, string template_key = null) {
public ProfileVM(uint id, TVM value, string name, SecurityCriteria security_criteria = null, string template_key = null, T target_value = null) {
this.id = id;
this.value = value;
_name = name;
_security_criteria = security_criteria;
_template_key = template_key;
_target_value = target_value;
_committed = _last_result = create();
_is_dirty = backing(nameof(is_dirty), () => !_last_result.Equals(_committed));
_refresh_is_dirty = new DeferrableActionWrapper(_is_dirty.refresh);
var sub = value.Subscribe(v => {
_last_result = _last_result.with(value: v);
_refresh_is_dirty.execute();
_on_value_changed();
});
_dispose = value is IDisposable d ? Disposable.Create(sub, d) : sub;
}
void _on_value_changed() {
if (_target_value != null && is_dirty && _last_result.value.Equals(_target_value)) {
_target_value = null;
_committed = _last_result;
_refresh_is_dirty.execute();
}
}
public uint id { get; }
public TVM value { get; }
public string name {
@@ -380,21 +391,26 @@ namespace mbts.spark {
/// assign directly to <see cref="_last_result"/>, to capture props that aren't visible in the dialog (i.e., props that are manipulated in the main window)
_last_result = data;
}
_on_value_changed();
}
public void load_value_from(T value) {
using (_refresh_is_dirty.defer_execution())
this.value.load_from(value);
_on_value_changed();
}
public void commit(SettingsProfile<T> data) {
using (_refresh_is_dirty.defer_execution())
_load_from(_committed = data);
_on_value_changed();
}
public void commit_current() {
_committed = _last_result;
_target_value = _committed.value;
_refresh_is_dirty.execute();
_on_value_changed();
}
public void revert() {
@@ -402,6 +418,7 @@ namespace mbts.spark {
_load_from(_committed);
_last_result = _committed;
}
_on_value_changed();
}
public IObservable<bool> subscribe_is_dirty() => _is_dirty.observe_current(true);
@@ -414,6 +431,7 @@ namespace mbts.spark {
public override string ToString() => _name;
void _load_from(SettingsProfile<T> data) {
_target_value = data.value;
name = data.name;
security_criteria = data.security_criteria;
value.load_from(data.value);
+17 -1
View File
@@ -197,6 +197,7 @@ namespace mbts.spark {
static class TickStore {
public static readonly RegionalTickFactors default_rtf = new RegionalTickFactors(new TickFactors(1000, 1), new TickFactors(1000, 1), double.MaxValue);
static readonly ConcurrentDictionary<SpecKey, RegionalTickFactors> _exchange_ticks = new ConcurrentDictionary<SpecKey, RegionalTickFactors>();
static readonly bool _som_ticks_fix_enabled = config.Configuration.get<bts.config.toggles.SOMTicksFix>().enabled;
public static RegionalTickFactors get(ContractSpecification spec) =>
_exchange_ticks.GetOrAdd(new SpecKey(spec), _create_rtf);
@@ -249,8 +250,23 @@ namespace mbts.spark {
var tf = _try_create_tf(tick_size, tick_base);
if (tf != null && display_digits_override > 0) {
int display_digit_diff = (int)display_digits_override - tf.display_digits();
if (display_digit_diff != 0)
if (_som_ticks_fix_enabled) {
// we can always add display_digits (i.e. dislpay_digit_diff > 0), of course the ticks can be expressed precisely with extra 0s.
// but if we are going to remove display_digits (i.e display_digit_diff < 0), we must make sure the tick_unit is large enough to be expressed precisely with that many fewer digits
// - "-display_digit_diff <= Math.Ceiling(Math.Log10(tf.tick_unit))" will tell us if the digits can be removed without compromising precision
// - unfortunately, we cannot rely on the exchange's ContractSpec for this, there is 1 known case where the data they give us is incorrect
// SOM spreads ContractSpec (from the exchange):
// LowTick: 0.0025 (aka 1/400, or 2/800)
// MainFraction: 8
// SubFraction: 0
// PriceDisplayFormat: 1
// - as you can see, this cannot possibly be formatted with 1 display digit, it ticks in increments of 1/400
// - in practice, to maintain the '8' base, we format this in increments of 2/800 (e.g. 1-000, 1-002, 1-004, and so on up to 1-778, 2-000)
if (display_digit_diff > 0 || (display_digit_diff < 0 && -display_digit_diff <= Math.Ceiling(Math.Log10(tf.tick_unit))))
tf = _inflate_to_base(tf, tf.tick_base * Math.Pow(10, display_digit_diff));
} else if (display_digit_diff != 0) {
tf = _inflate_to_base(tf, tf.tick_base * Math.Pow(10, display_digit_diff));
}
}
return tf;
}
+1 -12
View File
@@ -87,22 +87,11 @@ Example:
### Excel
```
spark_sdk\bin\Debug\net471> start spark_excel-addin64-packed.xll
spark_sdk\bin\Debug\net471> start spark_excel-addin64.xll
```
* This will start excel and load the bts addin
* Check the [```excel```](excel/) directory for an example spreadsheet
### Dotnet core
* Right now we only support c# Windows 10 clients, but the package targets both net471 and .net core 2.1.6, so in theory one could run a .net core or c++ client on linux with a little work.
* https://dotnet.microsoft.com/
```
spark_client_sdk\src\spark_sdk> dotnet build
...> dotnet spark_sdk.dll
```
* Send us an email for help: api_support@bluetradesys.com
+1 -1
View File
@@ -142,7 +142,7 @@ namespace bts.sdk
Console.WriteLine("This command subscribes to market data for an exchange-type-symbol channel and writes to console.");
Console.WriteLine("Marketdata is read off the wire on the same thread as is used to read and print");
Console.WriteLine(" example: md GLBX Future ES --user=bts --pass=password");
Console.WriteLine(" md GLBX Future ES ESZ8 --user=bts --pass=password");
Console.WriteLine(" md SIM Future ES SIM:ESZ8 --user=bts --pass=password");
Console.WriteLine(" md GLBX Spread ES --user=bts --pass=password");
Environment.Exit(1);
}
+1 -1
View File
@@ -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/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/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/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.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/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.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/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;mercury/actors/IPollableActor.cpp;mercury/broker/Broker.cpp;mercury/broker/BrokerProxy.cpp;mercury/broker/ILocalBroker.cpp;mercury/broker/IRemoteBroker.cpp;mercury/common/mercury_common.cpp;mercury/events/TimerEvent.cpp;mercury/executor/Executor.cpp;mercury/topics/Topic.cpp;metrics/metrics.cpp;metrics/system_metrics.cpp;orderman/actors/AsyncFactory.cpp;orderman/actors/ExecutionGateway.cpp;orderman/actors/FillStore.cpp;orderman/actors/MDSupplementarySource.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/OrderMLine truncated
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/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/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/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.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/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.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/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;mercury/actors/IPollableActor.cpp;mercury/broker/Broker.cpp;mercury/broker/BrokerProxy.cpp;mercury/broker/ILocalBroker.cpp;mercury/broker/IRemoteBroker.cpp;mercury/common/mercury_common.cpp;mercury/events/TimerEvent.cpp;mercury/executor/Executor.cpp;mercury/topics/Topic.cpp;metrics/metrics.cpp;metrics/system_metrics.cpp;orderman/actors/AsyncFactory.cpp;orderman/actors/ExecutionGateway.cpp;orderman/actors/FillStore.cpp;orderman/actors/MDSupplementarySource.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/OrderMLine truncated
+1 -1
View File
@@ -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/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/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/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.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/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.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/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/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/AuthSessionManager.cpp;utils/AuthToken.cpp;utils/Dispatcher.cpp;utils/GrowableSPSCQueue.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/crypto/CipherType.cpp;utils/crypto/CryptoInit.cpp;utils/crypto/Digest.cpp;utils/crypto/KeyCodeHelper.cpp;utils/crypto/PasswordCallback.cpp;utils/crypto/PrivateKey.cpp;utils/cryptoLine truncated
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/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/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/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.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/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityMapper.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.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/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/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/AuthSessionManager.cpp;utils/AuthToken.cpp;utils/Dispatcher.cpp;utils/GrowableSPSCQueue.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/crypto/CipherType.cpp;utils/crypto/CryptoInit.cpp;utils/crypto/Digest.cpp;utils/crypto/KeyCodeHelper.cpp;utils/crypto/PasswordCallback.cpp;utils/crypto/PrivaLine truncated
+11
View File
@@ -94,3 +94,14 @@ MDBootDelayWindow {
}
}
}
DisplayFactorOverride {
value {
override {
symbol: "SOM"
exchange: "GLBX"
type: "SPREAD"
price_multiplier: 1
}
}
}
+129 -53
View File
@@ -90,8 +90,6 @@ CppConfig
cpp_entry { key: "8D" value: 1000 }
cpp_entry { key: "8W" value: 1000 }
cpp_entry { key: "8XN" value: 2500 }
cpp_entry { key: "8ZN" value: 2500 }
cpp_entry { key: "9FN" value: 2500 }
cpp_entry { key: "9Q" value: 1000 }
cpp_entry { key: "A0D" value: 100 }
cpp_entry { key: "A0F" value: 100 }
@@ -163,6 +161,7 @@ CppConfig
cpp_entry { key: "AAW" value: 42000 }
cpp_entry { key: "AB3" value: 80 }
cpp_entry { key: "AB7" value: 1000 }
cpp_entry { key: "ABF" value: 100 }
cpp_entry { key: "ABH" value: 42000 }
cpp_entry { key: "ABI" value: 1000 }
cpp_entry { key: "ABS" value: 1000 }
@@ -170,6 +169,7 @@ CppConfig
cpp_entry { key: "ABX" value: 1000 }
cpp_entry { key: "ABY" value: 1000 }
cpp_entry { key: "AC0" value: 42000 }
cpp_entry { key: "ACB" value: 1000 }
cpp_entry { key: "ACD" value: 200000 }
cpp_entry { key: "ACM" value: 1000 }
cpp_entry { key: "ACT" value: 1000 }
@@ -183,7 +183,7 @@ CppConfig
cpp_entry { key: "AE5" value: 1000 }
cpp_entry { key: "AE8" value: 5 }
cpp_entry { key: "AE9" value: 80 }
cpp_entry { key: "AEJ" value: 960 }
cpp_entry { key: "AEB" value: 1000 }
cpp_entry { key: "AEP" value: 25 }
cpp_entry { key: "AET" value: 1000 }
cpp_entry { key: "AEZ" value: 42000 }
@@ -222,7 +222,6 @@ CppConfig
cpp_entry { key: "AJB" value: 1000 }
cpp_entry { key: "AJJ" value: 5 }
cpp_entry { key: "AJL" value: 42000 }
cpp_entry { key: "AJP" value: 960 }
cpp_entry { key: "AJR" value: 1000 }
cpp_entry { key: "AJS" value: 42000 }
cpp_entry { key: "AJU" value: 42000 }
@@ -346,7 +345,6 @@ CppConfig
cpp_entry { key: "BCF" value: 50 }
cpp_entry { key: "BCH" value: 50 }
cpp_entry { key: "BDB" value: 1000 }
cpp_entry { key: "BDI" value: 100 }
cpp_entry { key: "BDS" value: 1000 }
cpp_entry { key: "BFR" value: 100 }
cpp_entry { key: "BG" value: 1000 }
@@ -357,13 +355,12 @@ CppConfig
cpp_entry { key: "BOO" value: 6350 }
cpp_entry { key: "BOS" value: 250 }
cpp_entry { key: "BR7" value: 1000 }
cpp_entry { key: "BSW" value: 136 }
cpp_entry { key: "BSF" value: 25 }
cpp_entry { key: "BTC" value: 5 }
cpp_entry { key: "BTT" value: 50 }
cpp_entry { key: "BUB" value: 1000 }
cpp_entry { key: "BUC" value: 42000 }
cpp_entry { key: "BUS" value: 20 }
cpp_entry { key: "BUW" value: 20 }
cpp_entry { key: "BWF" value: 50 }
cpp_entry { key: "BWH" value: 50 }
cpp_entry { key: "BZ" value: 1000 }
@@ -394,6 +391,7 @@ CppConfig
cpp_entry { key: "CFB" value: 1000 }
cpp_entry { key: "CFC" value: 1000 }
cpp_entry { key: "CGB" value: 42000 }
cpp_entry { key: "CHB" value: 1000 }
cpp_entry { key: "CHI" value: 250 }
cpp_entry { key: "CHL" value: 100000 }
cpp_entry { key: "CHP" value: 50000000 }
@@ -406,9 +404,11 @@ CppConfig
cpp_entry { key: "CL" value: 1000 }
cpp_entry { key: "CL1" value: 1000 }
cpp_entry { key: "CL2" value: 1000 }
cpp_entry { key: "CLD" value: 1000 }
cpp_entry { key: "CLL" value: 1000 }
cpp_entry { key: "CLS" value: 1000 }
cpp_entry { key: "CLT" value: 1000 }
cpp_entry { key: "CMB" value: 1000 }
cpp_entry { key: "CMF" value: 1000 }
cpp_entry { key: "CNH" value: 100000 }
cpp_entry { key: "COL" value: 80 }
@@ -431,7 +431,6 @@ CppConfig
cpp_entry { key: "CUS" value: 250 }
cpp_entry { key: "CY" value: 1000 }
cpp_entry { key: "CZK" value: 4000000 }
cpp_entry { key: "CZN" value: 2500 }
cpp_entry { key: "D0" value: 20 }
cpp_entry { key: "D0X" value: 20 }
cpp_entry { key: "D0Z" value: 20 }
@@ -461,9 +460,9 @@ CppConfig
cpp_entry { key: "DDO" value: 1000 }
cpp_entry { key: "DEB" value: 744 }
cpp_entry { key: "DEN" value: 250 }
cpp_entry { key: "DEP" value: 252 }
cpp_entry { key: "DEP" value: 264 }
cpp_entry { key: "DFL" value: 100 }
cpp_entry { key: "DFT" value: 100 }
cpp_entry { key: "DFN" value: 100 }
cpp_entry { key: "DG2" value: 100 }
cpp_entry { key: "DG3" value: 100 }
cpp_entry { key: "DGH" value: 1000 }
@@ -472,7 +471,6 @@ CppConfig
cpp_entry { key: "DGT" value: 100 }
cpp_entry { key: "DHA" value: 80 }
cpp_entry { key: "DHI" value: 1000 }
cpp_entry { key: "DIH" value: 2500 }
cpp_entry { key: "DJR" value: 100 }
cpp_entry { key: "DKR" value: 1000 }
cpp_entry { key: "DMB" value: 100 }
@@ -503,7 +501,6 @@ CppConfig
cpp_entry { key: "EAC" value: 80 }
cpp_entry { key: "EAD" value: 125000 }
cpp_entry { key: "EAE" value: 5 }
cpp_entry { key: "EAF" value: 1000 }
cpp_entry { key: "EAW" value: 80 }
cpp_entry { key: "EBE" value: 1000 }
cpp_entry { key: "ECD" value: 125000 }
@@ -542,7 +539,6 @@ CppConfig
cpp_entry { key: "EST" value: 50 }
cpp_entry { key: "ETT" value: 100 }
cpp_entry { key: "EUB" value: 80 }
cpp_entry { key: "EUL" value: 1000 }
cpp_entry { key: "EURADC" value: 1 }
cpp_entry { key: "EURBPC" value: 1 }
cpp_entry { key: "EURBPN" value: 1 }
@@ -668,17 +664,24 @@ CppConfig
cpp_entry { key: "H4X" value: 20 }
cpp_entry { key: "H4Z" value: 20 }
cpp_entry { key: "H5" value: 20 }
cpp_entry { key: "H5B" value: 1000 }
cpp_entry { key: "H5F" value: 1000 }
cpp_entry { key: "H5G" value: 1000 }
cpp_entry { key: "H5L" value: 80 }
cpp_entry { key: "H5X" value: 20 }
cpp_entry { key: "H5Z" value: 20 }
cpp_entry { key: "HB" value: 2500 }
cpp_entry { key: "HBC" value: 1000 }
cpp_entry { key: "HBR" value: 1000 }
cpp_entry { key: "HCL" value: 1000 }
cpp_entry { key: "HDB" value: 1000 }
cpp_entry { key: "HE" value: 400 }
cpp_entry { key: "HET" value: 400 }
cpp_entry { key: "HG" value: 25000 }
cpp_entry { key: "HG0" value: 25000 }
cpp_entry { key: "HGB" value: 1000 }
cpp_entry { key: "HGF" value: 25000 }
cpp_entry { key: "HGK" value: 25000 }
cpp_entry { key: "HGS" value: 25000 }
cpp_entry { key: "HGT" value: 25000 }
cpp_entry { key: "HH" value: 10000 }
@@ -703,11 +706,16 @@ CppConfig
cpp_entry { key: "HQX" value: 20 }
cpp_entry { key: "HQZ" value: 20 }
cpp_entry { key: "HRC" value: 20 }
cpp_entry { key: "HRP" value: 20 }
cpp_entry { key: "HS" value: 20 }
cpp_entry { key: "HSX" value: 20 }
cpp_entry { key: "HSZ" value: 20 }
cpp_entry { key: "HTA" value: 1000 }
cpp_entry { key: "HTB" value: 1000 }
cpp_entry { key: "HTC" value: 1000 }
cpp_entry { key: "HTE" value: 1000 }
cpp_entry { key: "HTI" value: 1000 }
cpp_entry { key: "HTM" value: 1000 }
cpp_entry { key: "HTT" value: 1000 }
cpp_entry { key: "HUF" value: 30000000 }
cpp_entry { key: "HWA" value: 80 }
@@ -719,7 +727,6 @@ CppConfig
cpp_entry { key: "ICI" value: 1000 }
cpp_entry { key: "IDL" value: 5 }
cpp_entry { key: "IH" value: 50 }
cpp_entry { key: "ILB" value: 1750 }
cpp_entry { key: "ILS" value: 1000000 }
cpp_entry { key: "IN" value: 2500 }
cpp_entry { key: "IP" value: 50 }
@@ -727,11 +734,12 @@ CppConfig
cpp_entry { key: "IPT" value: 10 }
cpp_entry { key: "IS" value: 50 }
cpp_entry { key: "ITB" value: 744 }
cpp_entry { key: "ITP" value: 252 }
cpp_entry { key: "ITP" value: 264 }
cpp_entry { key: "IW" value: 50 }
cpp_entry { key: "J4L" value: 80 }
cpp_entry { key: "J7" value: 6250000 }
cpp_entry { key: "JA" value: 1000 }
cpp_entry { key: "JCC" value: 1000 }
cpp_entry { key: "JDL" value: 80 }
cpp_entry { key: "JE" value: 42000 }
cpp_entry { key: "JET" value: 42000 }
@@ -740,7 +748,7 @@ CppConfig
cpp_entry { key: "JKB" value: 10000 }
cpp_entry { key: "JKF" value: 10000 }
cpp_entry { key: "JKM" value: 10000 }
cpp_entry { key: "JML" value: 200 }
cpp_entry { key: "JML" value: 480 }
cpp_entry { key: "JNC" value: 1000 }
cpp_entry { key: "JNG" value: 10000 }
cpp_entry { key: "JNL" value: 80 }
@@ -809,6 +817,9 @@ CppConfig
cpp_entry { key: "LSW" value: 1000 }
cpp_entry { key: "LT" value: 42000 }
cpp_entry { key: "LWB" value: 1000 }
cpp_entry { key: "M1B" value: 10 }
cpp_entry { key: "M2K" value: 5 }
cpp_entry { key: "M35" value: 10 }
cpp_entry { key: "M5F" value: 10 }
cpp_entry { key: "M6A" value: 10000 }
cpp_entry { key: "M6B" value: 6250 }
@@ -839,10 +850,11 @@ CppConfig
cpp_entry { key: "MEB" value: 100 }
cpp_entry { key: "MEE" value: 100 }
cpp_entry { key: "MEF" value: 10 }
cpp_entry { key: "MEL" value: 840 }
cpp_entry { key: "MEO" value: 100 }
cpp_entry { key: "MES" value: 5 }
cpp_entry { key: "MEW" value: 100 }
cpp_entry { key: "MFB" value: 1000 }
cpp_entry { key: "MFC" value: 100 }
cpp_entry { key: "MFD" value: 100 }
cpp_entry { key: "MFF" value: 1000 }
cpp_entry { key: "MFP" value: 100 }
@@ -879,6 +891,7 @@ CppConfig
cpp_entry { key: "MNE" value: 100 }
cpp_entry { key: "MNG" value: 2500 }
cpp_entry { key: "MNH" value: 10000 }
cpp_entry { key: "MNQ" value: 2 }
cpp_entry { key: "MNS" value: 635 }
cpp_entry { key: "MNT" value: 80 }
cpp_entry { key: "MO" value: 1000 }
@@ -910,6 +923,7 @@ CppConfig
cpp_entry { key: "MXB" value: 35000 }
cpp_entry { key: "MXL" value: 5 }
cpp_entry { key: "MXR" value: 35000 }
cpp_entry { key: "MYM" value: 0.5 }
cpp_entry { key: "N1B" value: 1000 }
cpp_entry { key: "N1R" value: 10 }
cpp_entry { key: "N1T" value: 10 }
@@ -927,7 +941,6 @@ CppConfig
cpp_entry { key: "NCF" value: 100 }
cpp_entry { key: "NCO" value: 5 }
cpp_entry { key: "NCP" value: 100 }
cpp_entry { key: "NEN" value: 2500 }
cpp_entry { key: "NEO" value: 5 }
cpp_entry { key: "NEP" value: 80 }
cpp_entry { key: "NFC" value: 1000 }
@@ -941,10 +954,14 @@ CppConfig
cpp_entry { key: "NHN" value: 2500 }
cpp_entry { key: "NHO" value: 5 }
cpp_entry { key: "NHP" value: 80 }
cpp_entry { key: "NIM" value: 500 }
cpp_entry { key: "NIT" value: 500 }
cpp_entry { key: "NIY" value: 500 }
cpp_entry { key: "NJ" value: 2500 }
cpp_entry { key: "NKD" value: 5 }
cpp_entry { key: "NKM" value: 5 }
cpp_entry { key: "NKN" value: 2500 }
cpp_entry { key: "NKT" value: 5 }
cpp_entry { key: "NL" value: 2500 }
cpp_entry { key: "NLS" value: 42000 }
cpp_entry { key: "NMO" value: 5 }
@@ -984,7 +1001,7 @@ CppConfig
cpp_entry { key: "NYR" value: 42000 }
cpp_entry { key: "NYT" value: 1000 }
cpp_entry { key: "NZDUSC" value: 1 }
cpp_entry { key: "NZN" value: 2500 }
cpp_entry { key: "NZDUSD" value: 1 }
cpp_entry { key: "OAD" value: 1 }
cpp_entry { key: "ODO" value: 1000 }
cpp_entry { key: "OFF" value: 5 }
@@ -1000,6 +1017,7 @@ CppConfig
cpp_entry { key: "OVL" value: 5 }
cpp_entry { key: "PA" value: 100 }
cpp_entry { key: "PAL" value: 80 }
cpp_entry { key: "PAM" value: 10 }
cpp_entry { key: "PAT" value: 100 }
cpp_entry { key: "PBO" value: 5 }
cpp_entry { key: "PBP" value: 80 }
@@ -1020,7 +1038,6 @@ CppConfig
cpp_entry { key: "PHF" value: 5 }
cpp_entry { key: "PHO" value: 5 }
cpp_entry { key: "PHP" value: 80 }
cpp_entry { key: "PIO" value: 500 }
cpp_entry { key: "PJY" value: 125000 }
cpp_entry { key: "PKP" value: 80 }
cpp_entry { key: "PL" value: 50 }
@@ -1082,6 +1099,8 @@ CppConfig
cpp_entry { key: "R2T" value: 10 }
cpp_entry { key: "R2V" value: 50 }
cpp_entry { key: "R53" value: 1000 }
cpp_entry { key: "R5B" value: 1000 }
cpp_entry { key: "R5E" value: 1000 }
cpp_entry { key: "R5F" value: 1000 }
cpp_entry { key: "R5M" value: 100 }
cpp_entry { key: "R5O" value: 10 }
@@ -1091,6 +1110,7 @@ CppConfig
cpp_entry { key: "RBF" value: 100 }
cpp_entry { key: "RBG" value: 42000 }
cpp_entry { key: "RBL" value: 42000 }
cpp_entry { key: "RBM" value: 100 }
cpp_entry { key: "RBS" value: 42000 }
cpp_entry { key: "RBT" value: 42000 }
cpp_entry { key: "REX" value: 100 }
@@ -1119,13 +1139,15 @@ CppConfig
cpp_entry { key: "RYA" value: 42000 }
cpp_entry { key: "S1U" value: 1000 }
cpp_entry { key: "S53" value: 1000 }
cpp_entry { key: "S5B" value: 1000 }
cpp_entry { key: "S5F" value: 1000 }
cpp_entry { key: "S5M" value: 100 }
cpp_entry { key: "S5O" value: 10 }
cpp_entry { key: "SBM" value: 100 }
cpp_entry { key: "SBT" value: 50 }
cpp_entry { key: "SD" value: 1000 }
cpp_entry { key: "SDA" value: 250 }
cpp_entry { key: "SDD" value: 1600 }
cpp_entry { key: "SDD" value: 1760 }
cpp_entry { key: "SDG" value: 250 }
cpp_entry { key: "SDI" value: 1000 }
cpp_entry { key: "SDM" value: 100 }
@@ -1157,12 +1179,14 @@ CppConfig
cpp_entry { key: "SMT" value: 100 }
cpp_entry { key: "SMU" value: 1000 }
cpp_entry { key: "SMW" value: 100 }
cpp_entry { key: "SOM" value: 500 }
cpp_entry { key: "SON" value: 2500 }
cpp_entry { key: "SP" value: 250 }
cpp_entry { key: "SR1" value: 4167 }
cpp_entry { key: "SR3" value: 2500 }
cpp_entry { key: "SR5" value: 1000 }
cpp_entry { key: "SRT" value: 1600 }
cpp_entry { key: "SRB" value: 1000 }
cpp_entry { key: "SRT" value: 1760 }
cpp_entry { key: "SSI" value: 1000 }
cpp_entry { key: "SSP" value: 5000 }
cpp_entry { key: "SSW" value: 1000 }
@@ -1173,25 +1197,31 @@ CppConfig
cpp_entry { key: "STY" value: 1000 }
cpp_entry { key: "SU" value: 250 }
cpp_entry { key: "SUT" value: 250 }
cpp_entry { key: "T02" value: 800 }
cpp_entry { key: "T03" value: 800 }
cpp_entry { key: "T04" value: 800 }
cpp_entry { key: "T06" value: 800 }
cpp_entry { key: "T07" value: 800 }
cpp_entry { key: "T08" value: 800 }
cpp_entry { key: "T09" value: 800 }
cpp_entry { key: "T12" value: 800 }
cpp_entry { key: "T13" value: 800 }
cpp_entry { key: "T14" value: 800 }
cpp_entry { key: "T17" value: 800 }
cpp_entry { key: "T18" value: 800 }
cpp_entry { key: "T15" value: 800 }
cpp_entry { key: "T16" value: 800 }
cpp_entry { key: "T19" value: 800 }
cpp_entry { key: "T1U" value: 1000 }
cpp_entry { key: "T20" value: 800 }
cpp_entry { key: "T21" value: 800 }
cpp_entry { key: "T24" value: 800 }
cpp_entry { key: "T22" value: 800 }
cpp_entry { key: "T23" value: 800 }
cpp_entry { key: "T26" value: 800 }
cpp_entry { key: "T27" value: 800 }
cpp_entry { key: "T28" value: 800 }
cpp_entry { key: "T29" value: 800 }
cpp_entry { key: "T2B" value: 1000 }
cpp_entry { key: "T2D" value: 1000 }
cpp_entry { key: "T2M" value: 100 }
cpp_entry { key: "T31" value: 800 }
cpp_entry { key: "T30" value: 800 }
cpp_entry { key: "T3B" value: 1000 }
cpp_entry { key: "T3L" value: 80 }
cpp_entry { key: "T4B" value: 1000 }
@@ -1207,6 +1237,7 @@ CppConfig
cpp_entry { key: "TC" value: 2500 }
cpp_entry { key: "TC6" value: 1000 }
cpp_entry { key: "TC9" value: 1000 }
cpp_entry { key: "TCS" value: 1000 }
cpp_entry { key: "TD3" value: 1000 }
cpp_entry { key: "TD8" value: 1000 }
cpp_entry { key: "TEX" value: 1000 }
@@ -1216,6 +1247,7 @@ CppConfig
cpp_entry { key: "THB" value: 1000 }
cpp_entry { key: "THD" value: 10000 }
cpp_entry { key: "TIC" value: 500 }
cpp_entry { key: "TIL" value: 1000 }
cpp_entry { key: "TIO" value: 500 }
cpp_entry { key: "TK" value: 1000 }
cpp_entry { key: "TKB" value: 1000 }
@@ -1252,7 +1284,6 @@ CppConfig
cpp_entry { key: "TUT" value: 1000 }
cpp_entry { key: "TUX" value: 1000 }
cpp_entry { key: "TW" value: 1000 }
cpp_entry { key: "TXN" value: 2500 }
cpp_entry { key: "TYT" value: 1000 }
cpp_entry { key: "TYX" value: 1000 }
cpp_entry { key: "TZ6" value: 2500 }
@@ -1262,10 +1293,12 @@ CppConfig
cpp_entry { key: "UB" value: 1000 }
cpp_entry { key: "UCM" value: 100 }
cpp_entry { key: "UDL" value: 80 }
cpp_entry { key: "UFB" value: 100 }
cpp_entry { key: "UFE" value: 100 }
cpp_entry { key: "UFG" value: 100 }
cpp_entry { key: "UFN" value: 100 }
cpp_entry { key: "UFU" value: 100 }
cpp_entry { key: "UFZ" value: 100 }
cpp_entry { key: "UFV" value: 100 }
cpp_entry { key: "UGG" value: 42000 }
cpp_entry { key: "UKG" value: 310 }
cpp_entry { key: "ULB" value: 42000 }
@@ -1276,10 +1309,12 @@ CppConfig
cpp_entry { key: "UNB" value: 1000 }
cpp_entry { key: "UNS" value: 1000 }
cpp_entry { key: "UR" value: 1000 }
cpp_entry { key: "USC" value: 1000 }
cpp_entry { key: "USDBRL" value: 1 }
cpp_entry { key: "USDCAC" value: 1 }
cpp_entry { key: "USDCAD" value: 1 }
cpp_entry { key: "USDCAN" value: 1 }
cpp_entry { key: "USDCHF" value: 10 }
cpp_entry { key: "USDCKC" value: 1 }
cpp_entry { key: "USDCLP" value: 1 }
cpp_entry { key: "USDCNY" value: 1 }
@@ -1309,6 +1344,7 @@ CppConfig
cpp_entry { key: "USDTLC" value: 1 }
cpp_entry { key: "USDTWD" value: 1 }
cpp_entry { key: "USDZRC" value: 1 }
cpp_entry { key: "USE" value: 1000 }
cpp_entry { key: "UV" value: 1000 }
cpp_entry { key: "UX" value: 250 }
cpp_entry { key: "V3L" value: 5 }
@@ -1338,6 +1374,7 @@ CppConfig
cpp_entry { key: "WTA" value: 1000 }
cpp_entry { key: "WTD" value: 1000 }
cpp_entry { key: "WTI" value: 1000 }
cpp_entry { key: "WTL" value: 1000 }
cpp_entry { key: "WTS" value: 1000 }
cpp_entry { key: "WTT" value: 1000 }
cpp_entry { key: "X0" value: 1000 }
@@ -1390,6 +1427,7 @@ CppConfig
cpp_entry { key: "YWE" value: 80 }
cpp_entry { key: "YWF" value: 5 }
cpp_entry { key: "YWK" value: 5 }
cpp_entry { key: "Z00000" value: 1000 }
cpp_entry { key: "Z1B" value: 100 }
cpp_entry { key: "Z3N" value: 2000 }
cpp_entry { key: "Z4" value: 1000 }
@@ -1507,8 +1545,6 @@ CmeSymbolMics
cme_mic { key: "8D" value: NYMEX }
cme_mic { key: "8W" value: NYMEX }
cme_mic { key: "8XN" value: NYMEX }
cme_mic { key: "8ZN" value: NYMEX }
cme_mic { key: "9FN" value: NYMEX }
cme_mic { key: "9Q" value: NYMEX }
cme_mic { key: "A0D" value: NYMEX }
cme_mic { key: "A0F" value: NYMEX }
@@ -1580,6 +1616,7 @@ CmeSymbolMics
cme_mic { key: "AAW" value: NYMEX }
cme_mic { key: "AB3" value: NYMEX }
cme_mic { key: "AB7" value: NYMEX }
cme_mic { key: "ABF" value: NYMEX }
cme_mic { key: "ABH" value: NYMEX }
cme_mic { key: "ABI" value: NYMEX }
cme_mic { key: "ABS" value: NYMEX }
@@ -1587,6 +1624,7 @@ CmeSymbolMics
cme_mic { key: "ABX" value: NYMEX }
cme_mic { key: "ABY" value: NYMEX }
cme_mic { key: "AC0" value: NYMEX }
cme_mic { key: "ACB" value: NYMEX }
cme_mic { key: "ACD" value: CME }
cme_mic { key: "ACM" value: NYMEX }
cme_mic { key: "ACT" value: NYMEX }
@@ -1600,7 +1638,7 @@ CmeSymbolMics
cme_mic { key: "AE5" value: NYMEX }
cme_mic { key: "AE8" value: NYMEX }
cme_mic { key: "AE9" value: NYMEX }
cme_mic { key: "AEJ" value: NYMEX }
cme_mic { key: "AEB" value: NYMEX }
cme_mic { key: "AEP" value: COMEX }
cme_mic { key: "AET" value: NYMEX }
cme_mic { key: "AEZ" value: NYMEX }
@@ -1639,7 +1677,6 @@ CmeSymbolMics
cme_mic { key: "AJB" value: NYMEX }
cme_mic { key: "AJJ" value: NYMEX }
cme_mic { key: "AJL" value: NYMEX }
cme_mic { key: "AJP" value: NYMEX }
cme_mic { key: "AJR" value: NYMEX }
cme_mic { key: "AJS" value: NYMEX }
cme_mic { key: "AJU" value: NYMEX }
@@ -1763,7 +1800,6 @@ CmeSymbolMics
cme_mic { key: "BCF" value: CBT }
cme_mic { key: "BCH" value: CBT }
cme_mic { key: "BDB" value: NYMEX }
cme_mic { key: "BDI" value: CME }
cme_mic { key: "BDS" value: DME }
cme_mic { key: "BFR" value: NYMEX }
cme_mic { key: "BG" value: NYMEX }
@@ -1774,13 +1810,12 @@ CmeSymbolMics
cme_mic { key: "BOO" value: NYMEX }
cme_mic { key: "BOS" value: CME }
cme_mic { key: "BR7" value: NYMEX }
cme_mic { key: "BSW" value: CBT }
cme_mic { key: "BSF" value: CBT }
cme_mic { key: "BTC" value: CME }
cme_mic { key: "BTT" value: CME }
cme_mic { key: "BUB" value: CBT }
cme_mic { key: "BUC" value: NYMEX }
cme_mic { key: "BUS" value: NYMEX }
cme_mic { key: "BUW" value: NYMSW }
cme_mic { key: "BWF" value: CBT }
cme_mic { key: "BWH" value: CBT }
cme_mic { key: "BZ" value: NYMEX }
@@ -1811,6 +1846,7 @@ CmeSymbolMics
cme_mic { key: "CFB" value: NYMEX }
cme_mic { key: "CFC" value: NYMEX }
cme_mic { key: "CGB" value: NYMEX }
cme_mic { key: "CHB" value: NYMEX }
cme_mic { key: "CHI" value: CME }
cme_mic { key: "CHL" value: CME }
cme_mic { key: "CHP" value: CME }
@@ -1823,9 +1859,11 @@ CmeSymbolMics
cme_mic { key: "CL" value: NYMEX }
cme_mic { key: "CL1" value: NYMEX }
cme_mic { key: "CL2" value: NYMEX }
cme_mic { key: "CLD" value: NYMEX }
cme_mic { key: "CLL" value: NYMEX }
cme_mic { key: "CLS" value: NYMEX }
cme_mic { key: "CLT" value: NYMEX }
cme_mic { key: "CMB" value: NYMEX }
cme_mic { key: "CMF" value: NYMEX }
cme_mic { key: "CNH" value: CME }
cme_mic { key: "COL" value: NYMEX }
@@ -1848,7 +1886,6 @@ CmeSymbolMics
cme_mic { key: "CUS" value: CME }
cme_mic { key: "CY" value: NYMEX }
cme_mic { key: "CZK" value: CME }
cme_mic { key: "CZN" value: NYMEX }
cme_mic { key: "D0" value: CME }
cme_mic { key: "D0X" value: CME }
cme_mic { key: "D0Z" value: CME }
@@ -1880,7 +1917,7 @@ CmeSymbolMics
cme_mic { key: "DEN" value: CME }
cme_mic { key: "DEP" value: NYMEX }
cme_mic { key: "DFL" value: CBT }
cme_mic { key: "DFT" value: CBT }
cme_mic { key: "DFN" value: CBT }
cme_mic { key: "DG2" value: CBT }
cme_mic { key: "DG3" value: CBT }
cme_mic { key: "DGH" value: DME }
@@ -1889,7 +1926,6 @@ CmeSymbolMics
cme_mic { key: "DGT" value: CBT }
cme_mic { key: "DHA" value: NYMEX }
cme_mic { key: "DHI" value: DME }
cme_mic { key: "DIH" value: NYMEX }
cme_mic { key: "DJR" value: CBT }
cme_mic { key: "DKR" value: DME }
cme_mic { key: "DMB" value: DME }
@@ -1920,7 +1956,6 @@ CmeSymbolMics
cme_mic { key: "EAC" value: NYMEX }
cme_mic { key: "EAD" value: CME }
cme_mic { key: "EAE" value: NYMEX }
cme_mic { key: "EAF" value: NYMEX }
cme_mic { key: "EAW" value: NYMEX }
cme_mic { key: "EBE" value: NYMEX }
cme_mic { key: "ECD" value: CME }
@@ -1959,7 +1994,6 @@ CmeSymbolMics
cme_mic { key: "EST" value: CME }
cme_mic { key: "ETT" value: CME }
cme_mic { key: "EUB" value: NYMEX }
cme_mic { key: "EUL" value: NYMEX }
cme_mic { key: "EURADC" value: CME }
cme_mic { key: "EURBPC" value: CME }
cme_mic { key: "EURBPN" value: CME }
@@ -2085,17 +2119,24 @@ CmeSymbolMics
cme_mic { key: "H4X" value: CME }
cme_mic { key: "H4Z" value: CME }
cme_mic { key: "H5" value: CME }
cme_mic { key: "H5B" value: NYMEX }
cme_mic { key: "H5F" value: NYMEX }
cme_mic { key: "H5G" value: NYMEX }
cme_mic { key: "H5L" value: NYMEX }
cme_mic { key: "H5X" value: CME }
cme_mic { key: "H5Z" value: CME }
cme_mic { key: "HB" value: NYMEX }
cme_mic { key: "HBC" value: NYMEX }
cme_mic { key: "HBR" value: NYMEX }
cme_mic { key: "HCL" value: NYMEX }
cme_mic { key: "HDB" value: NYMEX }
cme_mic { key: "HE" value: CME }
cme_mic { key: "HET" value: CME }
cme_mic { key: "HG" value: COMEX }
cme_mic { key: "HG0" value: COMEX }
cme_mic { key: "HGB" value: NYMEX }
cme_mic { key: "HGF" value: COMEX }
cme_mic { key: "HGK" value: COMEX }
cme_mic { key: "HGS" value: COMEX }
cme_mic { key: "HGT" value: COMEX }
cme_mic { key: "HH" value: NYMEX }
@@ -2120,11 +2161,16 @@ CmeSymbolMics
cme_mic { key: "HQX" value: CME }
cme_mic { key: "HQZ" value: CME }
cme_mic { key: "HRC" value: NYMEX }
cme_mic { key: "HRP" value: COMEX }
cme_mic { key: "HS" value: CME }
cme_mic { key: "HSX" value: CME }
cme_mic { key: "HSZ" value: CME }
cme_mic { key: "HTA" value: NYMEX }
cme_mic { key: "HTB" value: NYMEX }
cme_mic { key: "HTC" value: NYMEX }
cme_mic { key: "HTE" value: NYMEX }
cme_mic { key: "HTI" value: NYMEX }
cme_mic { key: "HTM" value: NYMEX }
cme_mic { key: "HTT" value: NYMEX }
cme_mic { key: "HUF" value: CME }
cme_mic { key: "HWA" value: NYMEX }
@@ -2136,7 +2182,6 @@ CmeSymbolMics
cme_mic { key: "ICI" value: NYMEX }
cme_mic { key: "IDL" value: NYMEX }
cme_mic { key: "IH" value: MGE }
cme_mic { key: "ILB" value: NYMEX }
cme_mic { key: "ILS" value: CME }
cme_mic { key: "IN" value: NYMEX }
cme_mic { key: "IP" value: MGE }
@@ -2149,6 +2194,7 @@ CmeSymbolMics
cme_mic { key: "J4L" value: NYMEX }
cme_mic { key: "J7" value: CME }
cme_mic { key: "JA" value: NYMEX }
cme_mic { key: "JCC" value: NYMEX }
cme_mic { key: "JDL" value: NYMEX }
cme_mic { key: "JE" value: NYMEX }
cme_mic { key: "JET" value: NYMEX }
@@ -2226,6 +2272,9 @@ CmeSymbolMics
cme_mic { key: "LSW" value: NYMEX }
cme_mic { key: "LT" value: NYMEX }
cme_mic { key: "LWB" value: NYMEX }
cme_mic { key: "M1B" value: NYMEX }
cme_mic { key: "M2K" value: CME }
cme_mic { key: "M35" value: NYMEX }
cme_mic { key: "M5F" value: NYMEX }
cme_mic { key: "M6A" value: CME }
cme_mic { key: "M6B" value: CME }
@@ -2256,10 +2305,11 @@ CmeSymbolMics
cme_mic { key: "MEB" value: NYMEX }
cme_mic { key: "MEE" value: NYMEX }
cme_mic { key: "MEF" value: NYMEX }
cme_mic { key: "MEL" value: NYMEX }
cme_mic { key: "MEO" value: NYMEX }
cme_mic { key: "MES" value: CME }
cme_mic { key: "MEW" value: NYMEX }
cme_mic { key: "MFB" value: NYMEX }
cme_mic { key: "MFC" value: CBT }
cme_mic { key: "MFD" value: NYMEX }
cme_mic { key: "MFF" value: NYMEX }
cme_mic { key: "MFP" value: NYMEX }
@@ -2296,6 +2346,7 @@ CmeSymbolMics
cme_mic { key: "MNE" value: NYMEX }
cme_mic { key: "MNG" value: NYMEX }
cme_mic { key: "MNH" value: CME }
cme_mic { key: "MNQ" value: CME }
cme_mic { key: "MNS" value: NYMEX }
cme_mic { key: "MNT" value: NYMEX }
cme_mic { key: "MO" value: NYMEX }
@@ -2327,6 +2378,7 @@ CmeSymbolMics
cme_mic { key: "MXB" value: NYMEX }
cme_mic { key: "MXL" value: NYMEX }
cme_mic { key: "MXR" value: NYMEX }
cme_mic { key: "MYM" value: CBT }
cme_mic { key: "N1B" value: NYMEX }
cme_mic { key: "N1R" value: CME }
cme_mic { key: "N1T" value: CME }
@@ -2344,7 +2396,6 @@ CmeSymbolMics
cme_mic { key: "NCF" value: NYMEX }
cme_mic { key: "NCO" value: NYMEX }
cme_mic { key: "NCP" value: NYMEX }
cme_mic { key: "NEN" value: NYMEX }
cme_mic { key: "NEO" value: NYMEX }
cme_mic { key: "NEP" value: NYMEX }
cme_mic { key: "NFC" value: NYMEX }
@@ -2358,10 +2409,14 @@ CmeSymbolMics
cme_mic { key: "NHN" value: NYMEX }
cme_mic { key: "NHO" value: NYMEX }
cme_mic { key: "NHP" value: NYMEX }
cme_mic { key: "NIM" value: CME }
cme_mic { key: "NIT" value: CME }
cme_mic { key: "NIY" value: CME }
cme_mic { key: "NJ" value: NYMEX }
cme_mic { key: "NKD" value: CME }
cme_mic { key: "NKM" value: CME }
cme_mic { key: "NKN" value: NYMEX }
cme_mic { key: "NKT" value: CME }
cme_mic { key: "NL" value: NYMEX }
cme_mic { key: "NLS" value: NYMEX }
cme_mic { key: "NMO" value: NYMEX }
@@ -2401,7 +2456,7 @@ CmeSymbolMics
cme_mic { key: "NYR" value: NYMEX }
cme_mic { key: "NYT" value: NYMEX }
cme_mic { key: "NZDUSC" value: CME }
cme_mic { key: "NZN" value: NYMEX }
cme_mic { key: "NZDUSD" value: FXS }
cme_mic { key: "OAD" value: NYMEX }
cme_mic { key: "ODO" value: DME }
cme_mic { key: "OFF" value: NYMEX }
@@ -2417,6 +2472,7 @@ CmeSymbolMics
cme_mic { key: "OVL" value: NYMEX }
cme_mic { key: "PA" value: NYMEX }
cme_mic { key: "PAL" value: NYMEX }
cme_mic { key: "PAM" value: NYMEX }
cme_mic { key: "PAT" value: NYMEX }
cme_mic { key: "PBO" value: NYMEX }
cme_mic { key: "PBP" value: NYMEX }
@@ -2437,7 +2493,6 @@ CmeSymbolMics
cme_mic { key: "PHF" value: NYMEX }
cme_mic { key: "PHO" value: NYMEX }
cme_mic { key: "PHP" value: NYMEX }
cme_mic { key: "PIO" value: NYMEX }
cme_mic { key: "PJY" value: CME }
cme_mic { key: "PKP" value: NYMEX }
cme_mic { key: "PL" value: NYMEX }
@@ -2499,6 +2554,8 @@ CmeSymbolMics
cme_mic { key: "R2T" value: CME }
cme_mic { key: "R2V" value: CME }
cme_mic { key: "R53" value: NYMEX }
cme_mic { key: "R5B" value: NYMEX }
cme_mic { key: "R5E" value: NYMEX }
cme_mic { key: "R5F" value: NYMEX }
cme_mic { key: "R5M" value: NYMEX }
cme_mic { key: "R5O" value: NYMEX }
@@ -2508,6 +2565,7 @@ CmeSymbolMics
cme_mic { key: "RBF" value: NYMEX }
cme_mic { key: "RBG" value: NYMEX }
cme_mic { key: "RBL" value: NYMEX }
cme_mic { key: "RBM" value: NYMEX }
cme_mic { key: "RBS" value: NYMEX }
cme_mic { key: "RBT" value: NYMEX }
cme_mic { key: "REX" value: CBT }
@@ -2536,9 +2594,11 @@ CmeSymbolMics
cme_mic { key: "RYA" value: NYMEX }
cme_mic { key: "S1U" value: CBT }
cme_mic { key: "S53" value: NYMEX }
cme_mic { key: "S5B" value: NYMEX }
cme_mic { key: "S5F" value: NYMEX }
cme_mic { key: "S5M" value: NYMEX }
cme_mic { key: "S5O" value: NYMEX }
cme_mic { key: "SBM" value: NYMEX }
cme_mic { key: "SBT" value: CBT }
cme_mic { key: "SD" value: NYMEX }
cme_mic { key: "SDA" value: CME }
@@ -2574,11 +2634,13 @@ CmeSymbolMics
cme_mic { key: "SMT" value: CME }
cme_mic { key: "SMU" value: NYMEX }
cme_mic { key: "SMW" value: NYMEX }
cme_mic { key: "SOM" value: CBT }
cme_mic { key: "SON" value: CME }
cme_mic { key: "SP" value: CME }
cme_mic { key: "SR1" value: CME }
cme_mic { key: "SR3" value: CME }
cme_mic { key: "SR5" value: NYMEX }
cme_mic { key: "SRB" value: NYMEX }
cme_mic { key: "SRT" value: NYMEX }
cme_mic { key: "SSI" value: NYMEX }
cme_mic { key: "SSP" value: COMEX }
@@ -2590,25 +2652,31 @@ CmeSymbolMics
cme_mic { key: "STY" value: NYMEX }
cme_mic { key: "SU" value: CME }
cme_mic { key: "SUT" value: CME }
cme_mic { key: "T02" value: NYMEX }
cme_mic { key: "T03" value: NYMEX }
cme_mic { key: "T04" value: NYMEX }
cme_mic { key: "T06" value: NYMEX }
cme_mic { key: "T07" value: NYMEX }
cme_mic { key: "T08" value: NYMEX }
cme_mic { key: "T09" value: NYMEX }
cme_mic { key: "T12" value: NYMEX }
cme_mic { key: "T13" value: NYMEX }
cme_mic { key: "T14" value: NYMEX }
cme_mic { key: "T17" value: NYMEX }
cme_mic { key: "T18" value: NYMEX }
cme_mic { key: "T15" value: NYMEX }
cme_mic { key: "T16" value: NYMEX }
cme_mic { key: "T19" value: NYMEX }
cme_mic { key: "T1U" value: CBT }
cme_mic { key: "T20" value: NYMEX }
cme_mic { key: "T21" value: NYMEX }
cme_mic { key: "T24" value: NYMEX }
cme_mic { key: "T22" value: NYMEX }
cme_mic { key: "T23" value: NYMEX }
cme_mic { key: "T26" value: NYMEX }
cme_mic { key: "T27" value: NYMEX }
cme_mic { key: "T28" value: NYMEX }
cme_mic { key: "T29" value: NYMEX }
cme_mic { key: "T2B" value: NYMEX }
cme_mic { key: "T2D" value: NYMEX }
cme_mic { key: "T2M" value: NYMEX }
cme_mic { key: "T31" value: NYMEX }
cme_mic { key: "T30" value: NYMEX }
cme_mic { key: "T3B" value: NYMEX }
cme_mic { key: "T3L" value: NYMEX }
cme_mic { key: "T4B" value: NYMEX }
@@ -2624,6 +2692,7 @@ CmeSymbolMics
cme_mic { key: "TC" value: NYMEX }
cme_mic { key: "TC6" value: NYMEX }
cme_mic { key: "TC9" value: NYMEX }
cme_mic { key: "TCS" value: NYMEX }
cme_mic { key: "TD3" value: NYMEX }
cme_mic { key: "TD8" value: NYMEX }
cme_mic { key: "TEX" value: CBT }
@@ -2633,6 +2702,7 @@ CmeSymbolMics
cme_mic { key: "THB" value: NYMEX }
cme_mic { key: "THD" value: NYMEX }
cme_mic { key: "TIC" value: NYMEX }
cme_mic { key: "TIL" value: NYMEX }
cme_mic { key: "TIO" value: NYMEX }
cme_mic { key: "TK" value: NYMEX }
cme_mic { key: "TKB" value: NYMEX }
@@ -2669,7 +2739,6 @@ CmeSymbolMics
cme_mic { key: "TUT" value: CBT }
cme_mic { key: "TUX" value: CBT }
cme_mic { key: "TW" value: NYMEX }
cme_mic { key: "TXN" value: NYMEX }
cme_mic { key: "TYT" value: CBT }
cme_mic { key: "TYX" value: CBT }
cme_mic { key: "TZ6" value: NYMEX }
@@ -2679,10 +2748,12 @@ CmeSymbolMics
cme_mic { key: "UB" value: CBT }
cme_mic { key: "UCM" value: NYMEX }
cme_mic { key: "UDL" value: NYMEX }
cme_mic { key: "UFB" value: CBT }
cme_mic { key: "UFE" value: CBT }
cme_mic { key: "UFG" value: CBT }
cme_mic { key: "UFN" value: CBT }
cme_mic { key: "UFU" value: CBT }
cme_mic { key: "UFZ" value: CBT }
cme_mic { key: "UFV" value: CBT }
cme_mic { key: "UGG" value: NYMEX }
cme_mic { key: "UKG" value: NYMEX }
cme_mic { key: "ULB" value: NYMEX }
@@ -2693,10 +2764,12 @@ CmeSymbolMics
cme_mic { key: "UNB" value: NYMEX }
cme_mic { key: "UNS" value: NYMEX }
cme_mic { key: "UR" value: NYMEX }
cme_mic { key: "USC" value: NYMEX }
cme_mic { key: "USDBRL" value: CME }
cme_mic { key: "USDCAC" value: CME }
cme_mic { key: "USDCAD" value: FXS }
cme_mic { key: "USDCAN" value: CME }
cme_mic { key: "USDCHF" value: FXS }
cme_mic { key: "USDCKC" value: CME }
cme_mic { key: "USDCLP" value: CME }
cme_mic { key: "USDCNY" value: CME }
@@ -2726,6 +2799,7 @@ CmeSymbolMics
cme_mic { key: "USDTLC" value: CME }
cme_mic { key: "USDTWD" value: CME }
cme_mic { key: "USDZRC" value: CME }
cme_mic { key: "USE" value: NYMEX }
cme_mic { key: "UV" value: NYMEX }
cme_mic { key: "UX" value: NYMEX }
cme_mic { key: "V3L" value: NYMEX }
@@ -2755,6 +2829,7 @@ CmeSymbolMics
cme_mic { key: "WTA" value: NYMEX }
cme_mic { key: "WTD" value: NYMEX }
cme_mic { key: "WTI" value: NYMEX }
cme_mic { key: "WTL" value: NYMEX }
cme_mic { key: "WTS" value: NYMEX }
cme_mic { key: "WTT" value: NYMEX }
cme_mic { key: "X0" value: NYMEX }
@@ -2807,6 +2882,7 @@ CmeSymbolMics
cme_mic { key: "YWE" value: NYMEX }
cme_mic { key: "YWF" value: NYMEX }
cme_mic { key: "YWK" value: NYMEX }
cme_mic { key: "Z00000" value: CME }
cme_mic { key: "Z1B" value: NYMEX }
cme_mic { key: "Z3N" value: CBT }
cme_mic { key: "Z4" value: NYMEX }
+10
View File
@@ -216,3 +216,13 @@ message CMETradingSchedule {
message SecurityExpirationCutoff {
optional uint32 max_days_after_expiration =1 [default = 7];
}
message DisplayFactorOverride {
message Override {
required string symbol = 1;
required string exchange = 2;
optional string type = 3;
optional double price_multiplier = 10;
}
repeated Override override = 1;
}
+4
View File
@@ -48,6 +48,10 @@ message RejectStopAndStopLimitOrders {
optional bool enabled = 1 [default = true];
}
message SOMTicksFix {
optional bool enabled = 1 [default = true];
}
message EnsureOnScreenWithWorkAreaRect {
// Defaulting to false bc this is near the end of the cycle (04/27/2019),
// and the new ensure_onscreen code has only been tested with a single monitor arrangement.
+16 -12
View File
@@ -16,12 +16,12 @@ namespace md {
// Owns shared memory for a single symbol+type
class MDProducerImpl {
public:
MDProducerImpl(const string& symbol, SecurityType type, Venue exchange, Platform platform, bool shared) :
MDProducerImpl(const string& symbol, SecurityType type, Venue exchange, Platform platform, MDProducerFlags flags) :
_symbol(symbol),
_type(type),
_exchange(exchange),
_hot(hot_segment_name(symbol, type, exchange, platform), 1024, 1024, shared),
_cold(cold_segment_name(symbol, type, exchange, platform), 8192, 2048, shared),
_hot(hot_segment_name(symbol, type, exchange, platform), 1024, 1024, flags & MDProducerFlags::Shared),
_cold(cold_segment_name(symbol, type, exchange, platform), 8192, 2048, flags & MDProducerFlags::Shared),
_trades(_cold.header().trade_buffer, BTS_ARRAYSIZE(_cold.header().trade_buffer), true),
_rfqs(_cold.header().rfq_buffer, BTS_ARRAYSIZE(_cold.header().rfq_buffer), true)
{
@@ -33,7 +33,7 @@ public:
// static_assert(sizeof(HotEntry) <= 32,"HotEntry should be less than 32 bytes");
}
MDProducerHandle add_security(const FixedSecurity& security) {
MDProducerHandle add_security(const FixedSecurity& security, SecurityMapper& smapper) {
void* h_entry = nullptr;
if (has_depth()) {
h_entry = new (_hot.add(sizeof(HotDepthEntry))) HotDepthEntry();
@@ -45,6 +45,7 @@ public:
// Calculating the size for the variable sized entries is tricky
ColdEntry* c_entry = new (_cold.add(ColdEntry::fixed_size() + security.size)) ColdEntry(security.size);
memcpy(&c_entry->security, &security, security.size);
smapper.apply(c_entry->security);
MDProducerHandle handle(_cold.header(), _hot.header(), *c_entry, h_entry, MDProducerChannel(*this));
@@ -102,27 +103,30 @@ private:
// MDProducer
//
MDProducer::MDProducer(Platform platform, bool shared) :
MDProducer::MDProducer(Platform platform, MDProducerFlags flags) :
_mutex(new std::mutex()),
_producers(),
_id_recorder(),
_platform(platform),
_shared(shared)
_flags(flags),
_smapper(flags & MDProducerFlags::SecurityMapper)
{ }
#ifndef WIN32
MDProducer::MDProducer(Platform platform, SecurityIDRecorder recorder, bool shared) :
MDProducer::MDProducer(Platform platform, SecurityIDRecorder recorder, MDProducerFlags flags) :
_mutex(new std::mutex()),
_producers(),
_id_recorder(std::make_unique<SecurityIDRecorder>(recorder)),
_platform(platform),
_shared(shared)
_flags(flags),
_smapper(flags & MDProducerFlags::SecurityMapper)
{ }
#endif
MDProducer::MDProducer(MDProducer&& other) :
_mutex(std::move(other._mutex)),
_producers(std::move(other._producers)),
_platform(other._platform),
_shared(other._shared)
_flags(other._flags),
_smapper(_flags & MDProducerFlags::SecurityMapper)
{}
MDProducer::~MDProducer() {}
@@ -141,10 +145,10 @@ MDProducerImpl& MDProducer::get_producer(const char* symbol, SecurityType type,
unique_ptr<MDProducerImpl> newp;
if (type == api::SECURITYTYPE_SYNTHETIC) {
// synthetics are special. We don't want to allocate a separate section for each one so we put them all in one
newp.reset(new MDProducerImpl(SYNTHETIC_SYMBOL, api::SECURITYTYPE_SYNTHETIC, Venue::VENUE_BTS, _platform, _shared));
newp.reset(new MDProducerImpl(SYNTHETIC_SYMBOL, api::SECURITYTYPE_SYNTHETIC, Venue::VENUE_BTS, _platform, _flags));
}
else {
newp.reset(new MDProducerImpl(symbol, type, exchange, _platform, _shared));
newp.reset(new MDProducerImpl(symbol, type, exchange, _platform, _flags));
}
_producers.push_back(move(newp));
return *_producers.back();
@@ -155,7 +159,7 @@ MDProducerHandle MDProducer::add_security(const FixedSecurity& security) {
bts_assert(security.size >= sizeof(FixedSecurity));
std::lock_guard<std::mutex> lock(*_mutex);
auto& impl = get_producer(security.symbol(), security.type, security.exchange);
auto result = impl.add_security(security);
auto result = impl.add_security(security, _smapper);
if (security.key != invalid_security_key) { result.set_key(security.key); }
else if(_id_recorder) {
_id_recorder->ensure_key(result);
+17 -3
View File
@@ -7,6 +7,7 @@
#include "MDProducerHandle.h"
#include "MDProducerChannel.h"
#include "Shm/FixedSecurity.h"
#include "SecurityMapper.h"
#include <vector>
#include <memory>
#include <mutex>
@@ -17,11 +18,23 @@ namespace md {
class MDProducerImpl;
class SecurityIDRecorder;
enum class MDProducerFlags {
None = 0x0,
Shared = 0x1,
SecurityMapper = 0x2,
};
constexpr MDProducerFlags operator+(MDProducerFlags a, MDProducerFlags b) { return (MDProducerFlags)((uint32_t)a | (uint32_t)b); }
constexpr MDProducerFlags operator-(MDProducerFlags a, MDProducerFlags b) { return (MDProducerFlags)((uint32_t)a | (uint32_t)b); }
constexpr bool operator&(const MDProducerFlags a, const MDProducerFlags b) { return ((uint32_t)a & (uint32_t)b) == (uint32_t)b; }
constexpr MDProducerFlags DefaultMDProducerFlags = MDProducerFlags::Shared + MDProducerFlags::SecurityMapper;
class BTS_EXPORT MDProducer
{
public:
MDProducer(Platform platform, bool shared=true);
MDProducer(Platform platform, SecurityIDRecorder recorder, bool shared=true);
MDProducer(Platform platform, MDProducerFlags flags=DefaultMDProducerFlags);
MDProducer(Platform platform, SecurityIDRecorder recorder, MDProducerFlags flags=DefaultMDProducerFlags);
MDProducer(MDProducer&& other);
~MDProducer();
@@ -45,7 +58,8 @@ private:
std::vector<std::unique_ptr<MDProducerImpl>> _producers;
std::unique_ptr<SecurityIDRecorder> _id_recorder;
Platform _platform;
bool _shared;
MDProducerFlags _flags;
SecurityMapper _smapper;
};
+72
View File
@@ -0,0 +1,72 @@
#include "SecurityMapper.h"
#include "UserSymbol.h"
#include "PriceSize.h"
#include "lib/config/config.h"
#include "lib/config/protos/MarketData.pb.h"
#include "lib/domain_model/Security.h"
#include "lib/utils/parse_enum.h"
#ifndef _WIN32
#include "google/btree/btree_map.h"
namespace bts {
namespace md {
struct DisplayFactorMapper : public ISecurityMapper
{
btree::btree_map<UserSymbol, int> _mapped;
DisplayFactorMapper() : _mapped() {
for (const auto& ov : config::get<DisplayFactorOverride>().override()) {
if (ov.has_price_multiplier()) {
auto venue = parse_enum<api::Venue>(ov.exchange(), "VENUE", api::Venue_Parse);
bts_assert_msg(venue, fmt::format("Invalid venue `{}`", ov.exchange()));
auto type = parse_enum<SecurityType>(ov.type(), "SECURITYTYPE", api::SecurityType_Parse);
if (type) {
_mapped.insert(
std::make_pair(
UserSymbol { uppercase_copy(ov.symbol()), *venue, *type },
-to_exponent(ov.price_multiplier())));
}
else {
for (auto t : {
SecurityType::SECURITYTYPE_FUTURE,
SecurityType::SECURITYTYPE_SPREAD,
SecurityType::SECURITYTYPE_OPTION }) {
_mapped.insert(
std::make_pair(
UserSymbol { uppercase_copy(ov.symbol()), *venue, t },
-to_exponent(ov.price_multiplier())));
}
}
}
}
}
void apply(FixedSecurity& f) const override {
UserSymbol key { f.symbol(), f.exchange, f.type };
auto iter = _mapped.find(key);
if (iter != _mapped.end()) {
f.display_factor = iter->second;
}
}
};
SecurityMapper::SecurityMapper(bool enabled): _impl() {
if (enabled) {
_impl.push_back(std::make_unique<DisplayFactorMapper>());
// Register more mappers HERE
}
}
#else
namespace bts {
namespace md {
SecurityMapper::SecurityMapper(bool): _impl() {}
#endif
SecurityMapper::~SecurityMapper() { }
void SecurityMapper::apply(FixedSecurity& security) {
for (const auto& m : _impl) {
m->apply(security);
}
}
}} //namespace
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include "Shm/FixedSecurity.h"
#include <memory>
#include <vector>
namespace bts {
namespace md {
struct ISecurityMapper {
virtual void apply(FixedSecurity&) const = 0;
};
class SecurityMapper {
std::vector<std::unique_ptr<ISecurityMapper>> _impl;
public:
SecurityMapper(bool enabled);
~SecurityMapper();
// apply various mappings to the security
void apply(FixedSecurity&);
};
}} //namespace
+1 -1
View File
@@ -140,7 +140,7 @@ std::string security_descriptor(const api::Security& security) {
return result.str();
}
void get_contract_spec(const FixedSecurity& source, api::ContractSpecification& spec) {
void get_contract_spec(const FixedSecurity& source, /*out*/ api::ContractSpecification& spec) {
spec.set_price_break(source.price_break);
spec.set_low_tick(source.low_tick);
spec.set_high_tick(source.high_tick);
+3 -1
View File
@@ -100,7 +100,9 @@ public:
MDProducer& ensure_producer(Platform platform) {
auto find_result = _producers.find(platform);
if (find_result == _producers.end()) {
auto result = _producers.insert(make_pair(platform, MDProducer(platform, _shared)));
// relay never wants to enable SecurityMapper. Securities should always match the relay source.
auto flags = _shared ? MDProducerFlags::Shared : MDProducerFlags::None;
auto result = _producers.insert(make_pair(platform, MDProducer(platform, flags)));
if (result.second) {
return result.first->second;
}
+1 -1
View File
@@ -120,7 +120,7 @@ extern "C" BTS_EXPORT TestProducer* co2_produce_test_md() {
" }"
"}");
auto* tp = new TestProducer();
tp->md = std::make_shared<MDProducer>(PLATFORM_SIM, false);
tp->md = std::make_shared<MDProducer>(PLATFORM_SIM, MDProducerFlags::None);
tp->handles = create_test_securities(*(tp->md));
auto& producers = tp->handles;
assign_ids(producers.begin(), producers.end());
@@ -6,9 +6,13 @@
#include "lib/orderman/orders/spreader_orders/spreader/LegPropertyData.h"
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderLegData.h"
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderBookkeepingData.h"
#include "lib/orderman/orders/spreader_orders/spreader/NLegsHedgeRecompData.h"
#include "lib/orderman/events/SettlementUpdateEvent.h"
#include "lib/tracing/bts_trace.h"
#include "lib/utils/helper_macros.h"
#include "lib/config/config.h"
#include "lib/config/protos/spreader.pb.h"
#include "lib/os/os.h"
namespace bts {
namespace orderman {
@@ -337,7 +341,7 @@ bool SpreaderOrder::_all_hedger_orders_in_terminal_state(){
}
bool SpreaderOrder::_any_quoter_in_irrecoverable_error() const{
for (size_t q_idx = 0; q_idx < _bookkeeping_data().n_legs(); q_idx++){
const SpreaderLegData& leg_data = _bookkeeping_data().get_leg_data(q_idx);
const SpreaderLegData& leg_data = _bookkeeping_data().get_leg_data(q_idx);
if (leg_data.leg_property_data().is_active_quoting())
if (leg_data.quoter().irrecoverable_error())
return true;
@@ -373,6 +377,28 @@ void SpreaderOrder::_send_hedge(size_t hedge_leg_index,
hedge_price,
hedge_qty);
}
void SpreaderOrder::_compute_nlegs_crossed_hedges(size_t filled_leg_index,
Price filled_price,
double filled_quantity){
SpreaderBookkeepingData& bk_data = _bookkeeping_data();
NLegsHedgeRecompData& recomp_data = bk_data.hedge_recomp_data();
recomp_data.set_last_call_succ(false);
if(recomp_data.activated){
const LegPropertyData& q_leg_data =
bk_data.get_leg_data(filled_leg_index).leg_property_data();
const ISpreaderManager& spreader = *this;
bool is_succ =
SpreaderUtils::compute_nlegs_crossed_hedges(bk_data.side(),
bk_data.effective_price(),
bk_data.n_legs(),
q_leg_data,
filled_price,
filled_quantity,
spreader,
recomp_data.hedges());
recomp_data.set_last_call_succ(is_succ);
}
}
void SpreaderOrder::_compute_hedge_price_quantity(size_t filled_leg_index,
Price fill_price,
double fill_quantity,
@@ -392,16 +418,22 @@ void SpreaderOrder::_compute_hedge_price_quantity(size_t filled_leg_index,
computed_hedge_price,
hedge_quantity);
else{
const QuoteLegDriver& driver_data = filled_leg_data.quoter().driver_data(quote_order_price, hedge_leg_index);
// QuoteLegDriver driver_data;
// driver_data.set(quote_order_price,Quantity(1),Quantity(1));
SpreaderUtils::compute_hedge_price_size_n_legs (filled_leg_data.leg_property_data(),
fill_price,
fill_quantity,
hedged_leg_data.leg_property_data(),
driver_data,
computed_hedge_price,
hedge_quantity);
NLegsHedgeRecompData& recomp_data = _bookkeeping_data().hedge_recomp_data();
if(recomp_data.activated && recomp_data.last_call_succ()){
auto& crossed_hedge = recomp_data.hedges()[hedge_leg_index];
computed_hedge_price = crossed_hedge.first;
hedge_quantity = crossed_hedge.second;
}
else{
const QuoteLegDriver& driver_data = filled_leg_data.quoter().driver_data(quote_order_price, hedge_leg_index);
SpreaderUtils::compute_hedge_price_size_n_legs (filled_leg_data.leg_property_data(),
fill_price,
fill_quantity,
hedged_leg_data.leg_property_data(),
driver_data,
computed_hedge_price,
hedge_quantity);
}
}
hedge_price = SpreaderUtils::apply_pre_hedge_parameters (hedged_leg_data.leg_property_data().leg_params().pre_hedge_params(),
hedged_leg_data.book(),
@@ -18,8 +18,6 @@
#include "lib/orderman/events/OrderStateUpdateEvent.h"
#include "lib/orderman/events/BookUpdateEvent.h"
#include "lib/mercury/events/TimerEvent.h"
#include "lib/config/config.h"
#include "lib/config/protos/spreader.pb.h"
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderCacheWarmingState.h"
namespace bts {
@@ -63,7 +61,7 @@ private:
// this is the main data
bool _cancel_hedges_on_cancel;
// helps with forced calls, and all the artificiality of these
// calls are trapped here
// calls are trapped here
CacheWarmingState _cw_helper;
// timeout before cancel waiting goes to end
const int64_t _cancel_timeout;
@@ -236,6 +234,13 @@ private:
void _send_hedge(size_t hedge_leg_index,
Price hedge_price,
Quantity hedge_qty);
// computes the hedges in the case of nlegs
// from crossing the hedge markets. If the
// crossing doesnt result in better hedge prices
// 0's are stored in the qty's in
void _compute_nlegs_crossed_hedges(size_t filled_leg_index,
Price filled_price,
double filled_quantity);
void _compute_hedge_price_quantity(size_t filled_leg_index,
Price filled_price,
double filled_quantity,
@@ -0,0 +1,23 @@
#include "NLegsHedgeRecompData.h"
#include "lib/config/config.h"
#include "lib/config/protos/spreader.pb.h"
namespace bts{
namespace orderman {
NLegsHedgeRecompData::NLegsHedgeRecompData(
size_t n_legs,
bts::spark::ExecutionStrategy::HedgePricing hedge_pricing)
:
_last_call_succ(false),
_hedges(),
activated(n_legs > 2 &&
hedge_pricing == bts::spark::ExecutionStrategy::RECALCULATE_CROSSES){
if(activated){
_hedges.reserve(n_legs);
for(size_t i=0; i<n_legs; i++)
_hedges.emplace_back(std::pair<Price, double>(os::nan(),0.0));
}
}
}}
@@ -0,0 +1,44 @@
#pragma once
#include "lib/orderman/orderman_utils/orderman_common.h"
#include "lib/sparkproto/SparkProtos.pb.h"
namespace bts{
namespace orderman {
// This is the data related to recomputing the hedges
// for >2 legs on a fill.
// When this is activated, then on a fill, the hedge markets
// are analyzed to reduce the chances of getting legged
class NLegsHedgeRecompData{
private:
bool _last_call_succ;
// this is used as an out variable to the function
// that calculates the hedges based on crossing the
// hedge markets.
// this could have been a return variable from the
// function, but this is allocated once and reused to
// avoid allocations in the critical path
std::vector<std::pair<Price,double>> _hedges;
public:
// activated if > 2 legs and configured
const bool activated;
public:
NLegsHedgeRecompData(size_t n_legs,
bts::spark::ExecutionStrategy::HedgePricing hedge_pricing);
NLegsHedgeRecompData() = delete;
NLegsHedgeRecompData(const NLegsHedgeRecompData&) = delete;
NLegsHedgeRecompData(NLegsHedgeRecompData&&) = delete;
NLegsHedgeRecompData& operator=(const NLegsHedgeRecompData&) = delete;
NLegsHedgeRecompData& operator=(NLegsHedgeRecompData&&) = delete;
bool last_call_succ() const{
return _last_call_succ;
}
std::vector<std::pair<Price,double>>& hedges(){
return _hedges;
}
void set_last_call_succ (bool val){
_last_call_succ = val;
}
};
}}
@@ -1,4 +1,5 @@
#include "SpreaderBookkeepingData.h"
#include "lib/os/os.h"
namespace bts{
namespace orderman{
@@ -18,8 +19,11 @@ SpreaderBookkeepingData::SpreaderBookkeepingData (
_inited_new (inited_new),
_n_legs(legs.size()),
_n_quoting_legs(_calc_n_quoting_legs(legs)),
_side(order_def.side()),
_order_def(order_def),
_reported_state(){
_reported_state(),
_hedge_recomp_data(legs.size(),
order_def.custom_def().spreader().execution_strategy().hedge_pricing()){
LOG(OrderMan, Info, "SpreaderBookkeepingData.cons started "
"key: {} n_legs: {}",
spreader_order_key.value(), _n_legs);
@@ -10,9 +10,10 @@
#include "lib/orderman/orders/spreader_orders/spreader/external_interfacing/SpreaderOrderBuilder.h"
#include "lib/orderman/orders/spreader_orders/spreader/hedger/UnhedgedDelta.h"
#include "lib/orderman/orders/spreader_orders/spreader/hedger/HedgerManager.h"
#include "NLegsHedgeRecompData.h"
namespace bts{
namespace orderman {
namespace orderman {
class SingleFillHedger;
// encapsulates, organizes and provides easy access
// and lookups for data needed by the spreader.
@@ -24,6 +25,7 @@ private:
const bool _inited_new;
const size_t _n_legs;
const size_t _n_quoting_legs;
const api::Side _side;
// when the order is not created from the disk
// (ie created live) this is set to true
const api::orderman::OrderDefinition _order_def;
@@ -35,6 +37,7 @@ private:
Price _input_price;
Price _effective_price;
Quantity _quantity;
NLegsHedgeRecompData _hedge_recomp_data;
private:
size_t _calc_n_quoting_legs(const std::vector<LegPropertyData>& legs);
public:
@@ -61,10 +64,14 @@ public:
/////////////////////////////////
size_t n_legs() const { return _n_legs; }
bool all_legs_resolved() const {return n_legs() > 0;}
api::Side side() const {return _side;}
const api::orderman::OrderDefinition& order_def() const {return _order_def;}
Price input_price () const {return _input_price;}
Price effective_price () const {return _effective_price;}
Quantity quantity () const {return _quantity;}
NLegsHedgeRecompData& hedge_recomp_data(){
return _hedge_recomp_data;
}
// gets leg data from leg's sec key
SpreaderLegData& get_leg_data (SecurityKey security_key){
boost::container::flat_map<uint32_t, size_t>::const_iterator l_it = _sec_key_to_index.find(security_key.value());
@@ -794,6 +794,58 @@ public:
quote_fill_quantity,
hedge_leg);
}
// Given a quoting leg fill (ie leg id, fill price and
// fill qty), this function calculates the hedge prices,
// computed by crossing into the hedge market to get the
// required fill size.
// Function returns false if
// i. one of the hedging markets can not support the hedging
// size requirement
// ii. the computed spread price =
// q_leg_ratio*q_fill_price + sum(hedge_leg_ratio*hedge_cross_price)
// is worse than the spreader price
static bool compute_nlegs_crossed_hedges(
api::Side spr_side,
Price spr_price,
size_t n_legs,
const LegPropertyData& q_leg,
Price q_fill_price,
double q_fill_qty,
const ISpreaderManager& spreader,
std::vector<std::pair<Price,double>>& out_drivers){
// spr_cross_price = q_leg_ratio*q_fill_price +
// sum(hedge_leg_ratio*hedge_cross_price)
double spr_cross_price = q_fill_price.value()*q_leg.price_multiplier();
for (size_t i=0;i<n_legs;i++)
if(i!=q_leg.leg_index()){
Price hedge_price;
Quantity hedge_qty;
const auto& hedge_leg=spreader.get_leg_data(i);
double hedge_qty_needed_raw =
get_leg_quantity_from_another_leg_quantity(q_leg,
q_fill_qty,
hedge_leg);
Quantity hedge_qty_needed_rounded_up =
Quantity(_round_hedge_target(hedge_qty_needed_raw));
// since it is being hedged, we look at the opp side
api::Side hedge_market_side = invert_side(hedge_leg.trading_side());
traverse_depth_for_quantity(
spreader.get_book(i),
hedge_market_side,
hedge_qty_needed_rounded_up,
hedge_price,
hedge_qty);
if(hedge_qty.value()<hedge_qty_needed_rounded_up.value())
return false;
spr_cross_price += hedge_price.value()*hedge_leg.price_multiplier();
auto& driver_i=out_drivers[i];
driver_i.first=hedge_price;
driver_i.second=hedge_qty_needed_raw;
}
return securities::is_equal_or_better(spr_side,
spr_price,
Price(spr_cross_price));
}
////////////////////////////////////////////////////
// Rounding functions //////////////////////////////
////////////////////////////////////////////////////
@@ -99,6 +99,15 @@ void SpreaderWorkingStateWorker::on_quoter_order_fill(SpreaderLegData& leg_data)
// getting overfilled
Quantity filled_qty=cw.comp_fill_qty(updated_order);
bts_assert (filled_qty.value() > 0);
// this is a round about way to do this, so we
// dont have to change the structure of this code.
// this function fills in the value of the cross hedges
// in _bookkeeping_data().nlegs_crossed_hedges(), which
// is later retreived in _compute_hedge_price_quantity
_spreader->_compute_nlegs_crossed_hedges(
leg_data.leg_property_data().leg_index(),
updated_order.last_update_filled_price(),
filled_qty.value());
for (size_t q_idx = 0; q_idx < _spreader->_bookkeeping_data().n_legs(); q_idx++){
if (q_idx!=leg_data.leg_property_data().leg_index()){
SpreaderLegData& other_leg_data =
@@ -2614,6 +2614,237 @@ TEST_CASE ("nlegs_compute_driver", "[spreader]"){
REQUIRE(std::abs(hedge_quantity - 3.333333) < 0.000001);
}
}
TEST_CASE ("nlegs_crossed_hedges", "[spreader]"){
SECTION ("buy"){
bts::orderman::OrderKey order_key(1);
ContractLeg leg_1, leg_2, leg_3, leg_4;
fill_future_contract_leg (leg_1, 1, "CL", bts::api::Venue::VENUE_GLBX, 2021, 1, 15, 1.0, 1.0, api::Side::SIDE_BUY, 1.0, 0.01);
fill_future_contract_leg (leg_2, 2, "CL", bts::api::Venue::VENUE_GLBX, 2021, 2, 15, 1.0, 1.0, api::Side::SIDE_BUY, 1.0, 0.01);
fill_future_contract_leg (leg_3, 3, "CL", bts::api::Venue::VENUE_GLBX, 2021, 3, 15, 1.0, 1.0, api::Side::SIDE_BUY, 1.0, 0.01);
fill_future_contract_leg (leg_4, 4, "CL", bts::api::Venue::VENUE_GLBX, 2021, 4, 15, -1.0, -1.0, api::Side::SIDE_SELL, 1.0, 0.01);
std::vector<ContractLeg> legs;
legs.push_back(leg_1);legs.push_back(leg_2);legs.push_back(leg_3);legs.push_back(leg_4);
Security sec;
fill_synthetic_security (sec, 2000, "4legs", legs);
// execution params/order def
LegSpreaderParams lsp_1, lsp_2, lsp_3, lsp_4;
fill_leg_spreader_params(lsp_1, 1.0, false, 1.0);fill_leg_spreader_params(lsp_2, 1.0, false, 1.0);
fill_leg_spreader_params(lsp_3, 1.0, false, 1.0);fill_leg_spreader_params(lsp_4, -1.0, true, 1.0);
// // post hedge time out here
std::vector<LegSpreaderParams> params;
params.push_back(lsp_1);params.push_back(lsp_2);
params.push_back(lsp_3);params.push_back(lsp_4);
bts::api::orderman::OrderDefinition order_def;
fill_spreader_order_definition(order_def, Side::SIDE_BUY, sec, params);
// putting it together in SpreaderBookkeepingData
SpreaderPreActivationOrderServices::TestOnlySpreaderPreActivationOrderServices
testonly_spreader_pao_services = _create_spreader_pao_services(sec);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
std::vector<bts::api::orderman::OrderDefinition> quoter_ord_defs,
hedger_ord_defs;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,quoter_ord_defs,hedger_ord_defs);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props,quoter_ord_defs,hedger_ord_defs);
SpreaderBookkeepingData& bookkeeping_data = spreader_manager.bookkeeping_data();
fill_book(spreader_manager, 0, new double[5]{65.31,65.32,65.34,65.36, 65.40},
new uint16_t[5]{12,18,31,19,20},
bts::api::Side::SIDE_SELL,
true);
fill_book(spreader_manager, 1, new double[5]{64.40,64.41,64.43,64.45,64.50},
new uint16_t[5]{35,5,20,12,28},
bts::api::Side::SIDE_SELL,
true);
fill_book(spreader_manager, 2, new double[5]{64.10,64.18,64.19,64.20,64.21},
new uint16_t[5]{11,3,2,4,80},
bts::api::Side::SIDE_SELL,
true);
// buying at -0.03
std::vector<std::pair<Price,double>> drivers;
drivers.reserve(4);
// not enough to hedge
bool res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_BUY,
Price(-0.03),
4,
spreader_manager.get_leg_data(3),
Price(193.99),
101,
spreader_manager,
drivers);
REQUIRE(!res);
// 65.34 + 64.41 + 64.21 - 193.99 = -0.03
res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_BUY,
Price(-0.03),
4,
spreader_manager.get_leg_data(3),
Price(193.99),
40,
spreader_manager,
drivers);
REQUIRE(res);
REQUIRE(securities::is_same(drivers[0].first,Price(65.34)));
REQUIRE(securities::is_same(drivers[1].first,Price(64.41)));
REQUIRE(securities::is_same(drivers[2].first,Price(64.21)));
REQUIRE(securities::is_same(Price(drivers[0].second),Price(40)));
REQUIRE(securities::is_same(Price(drivers[1].second),Price(40)));
REQUIRE(securities::is_same(Price(drivers[2].second),Price(40)));
// quote gets better fill
res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_BUY,
Price(-0.03),
4,
spreader_manager.get_leg_data(3),
Price(193.99+0.01),
40,
spreader_manager,
drivers);
REQUIRE(res);
// quote gets worse fill
res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_BUY,
Price(-0.03),
4,
spreader_manager.get_leg_data(3),
Price(193.99-0.01),
40,
spreader_manager,
drivers);
REQUIRE(!res);
// // generalize the above
for (int i=0;i<1000;i++){
double quote_fill_price=gen_rand(193.99-1.0,193.99+1.0,0.01);
res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_BUY,
Price(-0.03),
4,
spreader_manager.get_leg_data(3),
Price(quote_fill_price),
40,
spreader_manager,
drivers);
if(quote_fill_price>=193.99)
REQUIRE(res);
else
REQUIRE(!res);
}
}
SECTION ("sell"){
bts::orderman::OrderKey order_key(1);
ContractLeg leg_1, leg_2, leg_3, leg_4;
fill_future_contract_leg (leg_1, 1, "CL", bts::api::Venue::VENUE_GLBX, 2021, 1, 15, 1.0, 1.0, api::Side::SIDE_BUY, 1.0, 0.01);
fill_future_contract_leg (leg_2, 2, "CL", bts::api::Venue::VENUE_GLBX, 2021, 2, 15, 1.0, 1.0, api::Side::SIDE_BUY, 1.0, 0.01);
fill_future_contract_leg (leg_3, 3, "CL", bts::api::Venue::VENUE_GLBX, 2021, 3, 15, 1.0, 1.0, api::Side::SIDE_BUY, 1.0, 0.01);
fill_future_contract_leg (leg_4, 4, "CL", bts::api::Venue::VENUE_GLBX, 2021, 4, 15, -1.0, -1.0, api::Side::SIDE_SELL, 1.0, 0.01);
std::vector<ContractLeg> legs;
legs.push_back(leg_1);legs.push_back(leg_2);legs.push_back(leg_3);legs.push_back(leg_4);
Security sec;
fill_synthetic_security (sec, 2000, "4legs", legs);
// execution params/order def
LegSpreaderParams lsp_1, lsp_2, lsp_3, lsp_4;
fill_leg_spreader_params(lsp_1, 1.0, false, 1.0);fill_leg_spreader_params(lsp_2, 1.0, false, 1.0);
fill_leg_spreader_params(lsp_3, 1.0, false, 1.0);fill_leg_spreader_params(lsp_4, -1.0, true, 1.0);
// // post hedge time out here
std::vector<LegSpreaderParams> params;
params.push_back(lsp_1);params.push_back(lsp_2);
params.push_back(lsp_3);params.push_back(lsp_4);
bts::api::orderman::OrderDefinition order_def;
fill_spreader_order_definition(order_def, Side::SIDE_SELL, sec, params);
// putting it together in SpreaderBookkeepingData
SpreaderPreActivationOrderServices::TestOnlySpreaderPreActivationOrderServices
testonly_spreader_pao_services = _create_spreader_pao_services(sec);
SpreaderPreActivationOrderServices pao_services (&testonly_spreader_pao_services);
std::vector<LegPropertyData> leg_props;
std::vector<bts::api::orderman::OrderDefinition> quoter_ord_defs,
hedger_ord_defs;
SpreaderUtils::resolve_synthetic_spread(pao_services, order_def, leg_props,quoter_ord_defs,hedger_ord_defs);
SpreaderManagerForTest spreader_manager (order_key, order_def, pao_services, leg_props,quoter_ord_defs,hedger_ord_defs);
SpreaderBookkeepingData& bookkeeping_data = spreader_manager.bookkeeping_data();
fill_book(spreader_manager, 0, new double[5]{62.1, 62, 61.99, 61.95, 61.93},
new uint16_t[5]{18,12,30,19,21},
bts::api::Side::SIDE_BUY,
true);
fill_book(spreader_manager, 1, new double[5]{63.2, 63.15, 62.99, 62.93, 61.90},
new uint16_t[5]{11,15,2,32,40},
bts::api::Side::SIDE_BUY,
true);
fill_book(spreader_manager, 2, new double[5]{65.2, 65.18, 64.98, 64.93, 64.90},
new uint16_t[5]{11,12,19,9,50},
bts::api::Side::SIDE_BUY,
true);
// selling at 0.02, fill of 101
// 61.93 + 61.90 + 64.90 - 189.83 = -1.1
std::vector<std::pair<Price,double>> drivers;
drivers.reserve(4);
// not enough to hedge
bool res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_SELL,
Price(0.02),
4,
spreader_manager.get_leg_data(3),
Price(189.83),
101,
spreader_manager,
drivers);
REQUIRE(!res);
// selling at 0.02, fill of 50 @ 189.83
// 61.99 + 62.93 + 64.93 = 189.85
// 189.85 - 189.83 = 0.02
res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_SELL,
Price(0.02),
4,
spreader_manager.get_leg_data(3),
Price(189.83),
50,
spreader_manager,
drivers);
REQUIRE(res);
// quote gets better fill
// 189.85 - x >= 0.02
// x <= 189.83
res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_SELL,
Price(0.02),
4,
spreader_manager.get_leg_data(3),
Price(189.83-0.01),
50,
spreader_manager,
drivers);
REQUIRE(res);
// quote gets worse fill
res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_SELL,
Price(0.02),
4,
spreader_manager.get_leg_data(3),
Price(189.83+0.01),
50,
spreader_manager,
drivers);
REQUIRE(!res);
// generalize the above
for (int i=0;i<1000;i++){
double quote_fill_price=gen_rand(189.83-1.0,189.83+1.0,0.01);
res = SpreaderUtils::compute_nlegs_crossed_hedges(
api::Side::SIDE_SELL,
Price(0.02),
4,
spreader_manager.get_leg_data(3),
Price(quote_fill_price),
50,
spreader_manager,
drivers);
if(quote_fill_price<=189.83)
REQUIRE(res);
else
REQUIRE(!res);
}
}
}
TEST_CASE ("quote driver caching", "[spreader]"){
SECTION("zero_search"){
QuoteDriverSetHistory driver_cache(5,10,0.05);
@@ -2834,6 +3065,7 @@ TEST_CASE ("spreader_perf_2legs", "[spreader]")
}
TEST_CASE ("spreader_perf_4legs", "[spreader]")
{
bool recomp = false;//gen_rand(0,10) > 5;
bts::orderman::OrderKey order_key(0);
Price spreader_price = Price (40);
Quantity spreader_quantity = Quantity (250);
@@ -3016,7 +3248,7 @@ TEST_CASE ("spreader_perf_4legs", "[spreader]")
0.005));
REQUIRE(securities::test_price_equality(
bookkeeping_data.get_leg_data (2).hedger_manager().test_only_get_hedger_at (0).order_state().out_price().value(),
19.995,
recomp ? 19.990 : 19.995,
0.005));
// back to leg1's hedger, this is what will
// be mainly tested here on
@@ -3025,7 +3257,7 @@ TEST_CASE ("spreader_perf_4legs", "[spreader]")
REQUIRE(hedger_1_1.order_state().out_quantity().value() == 1);
REQUIRE(securities::test_price_equality(
hedger_1_1.order_state().out_price().value(),
20.015,
recomp ? 20.005 : 20.015,
0.005));
REQUIRE(hedger_1_1.state()==HedgerState::WAITING_FOR_FIRST_ACK);
spreader.test_only_on_child_order_update (hedger_1_1.order_state().order_key(),
@@ -3060,7 +3292,7 @@ TEST_CASE ("spreader_perf_4legs", "[spreader]")
REQUIRE(hedger_1_1.order_state().out_quantity().value() == 1);
REQUIRE(securities::test_price_equality(
hedger_1_1.order_state().out_price().value(),
20.015,
recomp ? 20.005 : 20.015,
0.005));
REQUIRE(hedger_1_1.state()==HedgerState::WAITING_FOR_FIRST_ACK);
spreader.test_only_on_child_order_update (hedger_1_1.order_state().order_key(),
@@ -3097,7 +3329,7 @@ TEST_CASE ("spreader_perf_4legs", "[spreader]")
REQUIRE(h.order_state().out_quantity().value()==2);
REQUIRE(securities::test_price_equality(
h.order_state().out_price().value(),
20.015,
recomp ? 20.005 : 20.015,
0.005));
}
// send order acks //////////
@@ -3112,7 +3344,7 @@ TEST_CASE ("spreader_perf_4legs", "[spreader]")
REQUIRE(h.order_state().out_quantity().value()==2);
REQUIRE(securities::test_price_equality(
h.order_state().out_price().value(),
20.015,
recomp ? 20.005 : 20.015,
0.005));
}
REQUIRE(hm_1.n_active_hedgers()==4);
@@ -3129,7 +3361,7 @@ TEST_CASE ("spreader_perf_4legs", "[spreader]")
REQUIRE(h.order_state().out_quantity().value()==2);
REQUIRE(securities::test_price_equality(
h.order_state().out_price().value(),
20.015,
recomp ? 20.005 : 20.015,
0.005));
}
REQUIRE(hm_1.n_active_hedgers()==4);
@@ -3155,60 +3387,6 @@ TEST_CASE ("spreader_perf_4legs", "[spreader]")
REQUIRE(securities::test_price_equality(t_price.value(),20.03,0.005));
REQUIRE(t_qty.value()==10);
}
// SECTION ("N_requotes_1_hedge_M_times"){
// // N book updates followed by M fills
// // (does the hedge time stays the same as
// // in a tight loop in the "hedges" test ?)
// uint32_t n_runs=5,
// n_book_updates=200,
// n_hedges = 5;
// // since its the same quoting order we are filling
// // and the code downstream expects accumulated filled qty
// uint32_t total_filled_qty = 0, hi = 0;
// for (uint32_t i=0; i<n_runs; i++){
// test_sleep(5000,false);
// std::vector<double> hedge_perfs;
// hedge_perfs.reserve(n_hedges);
// auto t0=utils::TimeStamp::now();
// for (uint32_t b=0; b<n_book_updates; b++){
// spreader.test_only_on_book_update (BookUpdateEvent(book_1_alt,
// trace::CorID()));
// spreader.test_only_on_book_update (BookUpdateEvent(book_2_alt,
// trace::CorID()));
// spreader.test_only_on_book_update (BookUpdateEvent(book_3_alt,
// trace::CorID()));
// spreader.test_only_on_book_update (BookUpdateEvent(book_1,
// trace::CorID()));
// spreader.test_only_on_book_update (BookUpdateEvent(book_2,
// trace::CorID()));
// spreader.test_only_on_book_update (BookUpdateEvent(book_3,
// trace::CorID()));
// spreader.test_only_on_child_order_update (qleg_data_4.order_key(),
// api::orderman::OrderStatus::ORDER_STATUS_WORKING,
// Quantity (total_filled_qty),
// Price (20.045));
// }
// auto t1=utils::TimeStamp::now();
// double avg_bookupdate_time=(t1-t0).nanoseconds()/(1000.0 * 6*n_book_updates);
// for(uint32_t h=0; h<n_hedges; h++){
// auto t0=utils::TimeStamp::now();
// spreader.test_only_on_child_order_update (qleg_data_4.order_key(),
// api::orderman::OrderStatus::ORDER_STATUS_WORKING,
// Quantity (++total_filled_qty),
// Price (20.045));
// auto t1=utils::TimeStamp::now();
// hedge_perfs.push_back((t1-t0).nanoseconds());
// }
// for (auto d : hedge_perfs)
// std::cout << ++hi << " hedge: " << d << std::endl;
// double min, max, mean, median;
// stats(hedge_perfs,min,max,mean,median);
// std::cout << "1Q 3H legs, requoting mean=" << avg_bookupdate_time << std::endl;
// std::cout << "1Q 3H legs, hedging median=" << median << " mean=" << mean << std::endl;
// std::cout << "------------------------------------------------------" << std::endl;
// }
// }
}
TEST_CASE ("simple book addition", "[spreader]"){
SECTION ("direct, book"){
+5
View File
@@ -465,6 +465,11 @@ message ExecutionStrategy
bool deleted = 1;
map<uint32, LegSpreaderParams> leg_params_map = 20;
bool cancel_hedges_on_cancel = 30;
enum HedgePricing{
CACHED_DRIVERS = 0;
RECALCULATE_CROSSES = 1;
}
HedgePricing hedge_pricing = 40;
}
// EVERYTHING BELOW THIS LINE IS OBSOLETE
+56
View File
@@ -0,0 +1,56 @@
#pragma once
// An incomplete version of std::optional which should work well enough on Windows until it catch up
#ifdef _WIN32
#include <exception>
namespace std {
class bad_optional_access : exception { };
template <class T>
class optional {
bool _has_value;
union {
T _value;
int _unused;
};
public:
optional(const T& value) : _has_value(true), _value(value) { }
optional(T&& value) : _has_value(true), _value(value) { }
optional() : _has_value(false)
~optional() { reset(); }
bool has_value() const { return _has_value; }
operator bool() { return b.has_value(); }
T& operator *() {
if (has_value()) {
return _value;
}
else throw std::bad_optional_access();
}
const T& operator*() const { return **this; }
T& operator->() { return **this; }
const T& operator->() const { return **this; }
bool operator==(const std::optional<T>& other) const {
if (!_has_value && !other.has_value()) return true;
return _has_value == other._has_value && _value == other.value();
}
bool operator!=(const std::optional<T>& other) const { return !(*this == other); }
T& value() { return **this; }
const T& value() const { return **this; }
T value_or(T default_value) {
if (has_value()) return _value;
else return default_value;
}
void reset() {
if (has_value()) {
_value.~T();
_has_value = false;
}
}
// This class is incomplete. Add methods as necessary
};
template <class T>
constexpr optional<T> nullopt = {};
}
#else
#include <optional>
#endif
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <string>
#include "lib/utils/optional.h"
namespace bts {
inline std::string uppercase_copy(const std::string& cs) {
std::string s = cs;
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
return s;
}
template <class T, class T2>
std::optional<T> parse_enum(const std::string& value, const std::string& prefix, T2 parse) {
auto temp = value;
T result;
if (temp.find(prefix) == std::string::npos) {
temp = prefix + "_" + temp;
}
if(parse(temp, &result)) {
return {result};
}
else {
return std::nullopt;
}
}
}
+88 -80
View File
@@ -9,11 +9,8 @@ Our offering consists of a client UI ([Spark Client](https://www.bluetradingsyst
This API extension point is intended for users that require adding functionality to our Spark Server. Using the **Spark Server SDK** users can create [new order types](https://github.com/BlueTradingSystems/spark_sdk/blob/master/examples/order_plugin_example.cpp), [new market data sources](https://github.com/BlueTradingSystems/spark_sdk/blob/master/examples/md_publisher_example.cpp) and soon new execution gateways. In this case users implement the new functionality in C++, producing a shared library that is loaded at run time by our Spark Server.
If you are interested in sending orders or otherwise controlling a spark server remotely please see the BTS [Spark Client SDK](https://github.com/BlueTradingSystems/spark_client_sdk) repo.
If you are interested in sending orders to or otherwise controlling a spark server remotely please see the BTS [Spark Client SDK](https://github.com/BlueTradingSystems/spark_client_sdk) repo.
### In Depth
* [Spark Algo Descriptions](doc/algos.md)
## Getting Started
@@ -32,118 +29,129 @@ $ docker pull bluetradingsystems/linux_docker
2) Start the docker container
```
$ docker run \
--net host \
--shm-size=1024m \
--cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
-w $PWD \
-v /home:/home \
--name bts_sdk \
-i \
-t bluetradingsystems/linux_docker \
/bin/bash
--rm \
--net host \
-i \
-h $(hostname)_spark \
-v /etc/passwd:/etc/passwd \
-e "TZ=America/New_York" \
--security-opt seccomp=unconfined \
-v /var/log/syslog:/var/log/syslog \
-v /etc/group:/etc/group \
-v /tmp:/tmp \
--shm-size=2048m \
-u $UID \
-v /home:/home \
-w /home/$USER \
--name bts_sdk \
-t bluetradingsystems/linux_docker \
/bin/bash
```
* Note that the lifetime of docker instance above is tied to the life of the shell instance, so if you exit bash, the container stops running. To start and re-attach to the container, use:
```
$ docker start --attach -i bts_sdk
```
* If you prefer to run docker as a daemon, check out [``~/spark_sdk/sdk_shell.sh``](sdk_shell.sh)
### Git
* We assume the git you are using is git-lfs compatible; if you're using the git that comes with our docker, you're all set.
* else go here: https://github.com/git-lfs/git-lfs/wiki/Installation
Now that you're ssh'd into the docker container, clone the repo into ```~/spark_sdk/``` and cd to that directory
Now that you're inside the docker container, clone the repo into ```~/spark_sdk/```
```
$ cd
$ git clone https://github.com/BlueTradingSystems/spark_sdk.git
$ cd spark_sdk
~$ git clone https://github.com/BlueTradingSystems/spark_sdk.git
```
### Start the server
```
~$ cd ~/spark_sdk/lib
~/spark_sdk/lib$ ./sparkd run
```
### Connect to the Spark Admin tool via the browser
```
Browse to http://<your_ip>:8000
```
* You should see a Spark Admin login screen, enter user bts with no password
* Add or manage user trading and market data permissions by clicking the Users icon on the left side
* Add or manage accounts and risk limits by clicking on the Accounts icon on the left side
### Connect Spark Front End (Windows)
* Download spark windows executable here: <spark_client>
* Then start the client and point it at your running server:
```
> spark.exe -ConfigServer http://<your_ip>:8000/config
```
### Development
## Algo Development
Algo Orders typically implement the [IAlgoOrder](include/spark/lib/orderman/orders/algo/IAlgoOrder.h) interface to respond to events and use the [IAlgoServices](include/spark/lib/orderman/orders/algo/IAlgoServices.h) interface to create and control child orders as well as manage their own life cycles. See [examples/order_plugin_example.cpp](examples/order_plugin_example.cpp) for a fully fledged example
Look at [examples/md_publisher_example.cpp](examples/md_publisher_example.cpp) to look at how to build a custom market data producer
First kill your running sparkd by hitting ctrl-c
```
bts@spark-vm_spark:~/spark_sdk/lib$ ./sparkd run
^C
bts@spark-vm_spark:~/spark_sdk/lib$
```
run ```build_examples.sh``` to make sure you can build the examples, this will produce an ```order_plugin_example.so```
Run ```build_examples.sh``` to make sure you can build the examples, this will produce an ```order_plugin_example.so```
```
$ cd ~/spark_sdk/examples
$ ./build_examples.sh
~$ cd ~/spark_sdk/examples
~/spark_sdk/examples$ ./build_examples.sh
```
#### Server Layout
* Spark servers reside on a port, usually 8000, but your production instance could be on a different $PORT
The server process looks in the ```plugins``` directory to load these shared objects. First navigate to the plugins directory to verify the shared object (```order_plugin_example.so```) has been built
```
$ cd ~/spark_sdk/lib/plugins
~/spark_sdk/lib/plugins$ ls
order_plugin_example.so
~/spark_sdk/lib/plugins$
```
Now move back to the lib directory and bounce the server
```
~$ cd ~/spark_sdk/lib
~/spark_sdk/lib$ ./sparkd run
```
## Dev Notes
##### SDK Package Layout
* The sdk puts logs in ``~/sparkdata/data/logging/log``
* The sdk package has binaries in ``spark_skd/lib``
* Put plugins in ``spark_sdk/lib/plugins/`` for debugging
* The sdk package has binaries in ``~/spark_sdk/lib``
* Plugins go in ``~/spark_sdk/lib/plugins/``
##### Production layout
* Production Logs are in ``~/$PORT/sparkdata/data/logging/log`` on the host
* Spark servers reside on a port, usually 8000, but your production instance could be on a different PORT
* Production Logs are in ``~/PORT/sparkdata/data/logging/log`` on the host
* Production binaries are in ``/sparkbin`` inside the docker container
* Production algo plugins should go into the ``/sparkbin/plugins`` directory
#### Recorded market data
* We first check for http://mdreplay/spark/futures.coconut
* Then fall back to ``./data_files/ relative to the sparkd binary``
#### Debugging
## Debugging
Copy the order_plugin_example.so to ``spark_sdk/lib/plugins/`` and start the sparkd server process inside gdb
Use this command to start the sparkd server process inside gdb
```
$ cp -f order_plugin_example.so ~/spark_sdk/lib/plugins/
$ cd ~/spark_sdk/lib
$ gdb --args ./sparkd run
~/spark_sdk/lib$ gdb --args ./sparkd run
```
In gdb:
* https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf
```
(gdb) break order_plugin_example.cpp:366
```
## Running without debugger
```
$ cp -f order_plugin_example.so ~/spark_sdk/lib/plugins/
$ cd ~/spark_sdk/lib
$ ./sparkd run
```
## Connect to Admin (Risk) UI to set limits or add users
* Browse to http://location:$PORT
* Login as bts, no password
* Add or manage user trading and market data permissions by clicking the Users icon on the left side
* Add or manage accounts and risk limits by clicking on the Accounts icon on the left side
## Other interesting web accessible things
* When you have a running server you can:
* Browse to http://location/$PORT/config to check configuration overrides
* Browse to http://location:$PORT/perf_trace to see socket to socket latencies
* Send us an email for help: api_support@bluetradesys.com
#### Spark windows client
* Download spark windows executable here: <spark_client>
## Connect Spark windows client
* To start a spark client, use the -ConfigServer parameter to point at this new server
```
> spark.exe -ConfigServer http://location:$PORT/config
```
Or create a file called spark.conf at %APPDATA%\bts\conf\ that contains:
```
include: "http://location:$PORT/config/"
```
## Download the Spark windows client
* Download the bts installer here:
-46
View File
@@ -1,46 +0,0 @@
+++
title = "BTS Basic Algos"
weight = 3
sort_by = "weight"
insert_anchor_links = "right"
+++
## Lean
The goal of the lean order is to watch the opposite-inside market size and cross when that size goes below the threshold (this also implies a cross if that size goes to zero and the market trades away from you) If the market trades toward you, you can opt into several different behaviors
##### Parameters
* Cross Thresh - size thresh in absolute or ratio terms
* Max Chase Ticks - max levels to pay up, in ticks
## Join
The goal of the join order is to watch the opposite-inside market and join when the market flips (that is, when the best offer becomes the best bid) and has at least threshold size.
##### Parameters
* Join Thresh - size thresh in absolute or ratio terms
## Top
The goal of the top order is to not trade by yourself, but the intent at the time of order entry is to get filled.If the order is on the market (say current bid price) AND the quantity on that bid price is below top thresh then cancel the order else remain working.
##### Parameters
* Top Thresh - size thresh in absolute or ratio terms
## Cover
A Cover order’s purpose is to fire a hedge order (of any type) in response to fills from it’s child order on the opposite side of the market N ticks away
##### Parameters
* Profit Ticks - ticks above or below fill price to place profit / cover order
## OCO
An OCO order creates a relationship between a child order and a 'stop' or 'other' order such that when one of these is cancelled, both cancel, or when one is filled, the other order's size is debited in the amount of the fill.
Composing this order with Cover simulates scalping functionality
##### Parameters
* Stop Ticks - ticks below or above main order to place stop / other order
+8 -8
View File
@@ -16,6 +16,7 @@
#include "lib/md/SecurityDB.h"
#include "server/sparkd/exchange_sim/ExchangeSim.h"
#include "lib/utils/thread_manager.h"
#include "lib/utils/parse_enum.h"
#include <boost/filesystem.hpp>
@@ -169,16 +170,14 @@ string& uppercase(string& s) {
return s;
}
template <class T, class T2>
bool parse_enum(const string& value, const string& prefix, T2 parse, T default_value, T* presult) {
string temp = value;
if (temp.find(prefix) == string::npos) {
temp = prefix + "_" + temp;
}
if(parse(temp, presult)) {
bool parse_enum(const string& value, const string& prefix, T2 parse, T default_value, T* result) {
auto opt = ::bts::parse_enum<T>(value, prefix, parse);
if (opt) {
*result = opt.value();
return true;
}
else {
*presult = default_value;
*result = default_value;
return false;
}
}
@@ -208,13 +207,14 @@ struct MDArgs {
MDArgs parse_md_args(const vector<string>& args) {
using namespace api;
using namespace co2;
auto venue = VENUE_UNSET; // Default to glbx. If you change this change below (used) also
auto venue = VENUE_UNSET;
auto platform = PLATFORM_UNSET;
auto type = SECURITYTYPE_UNSET;
bool hot = false;
long number = 0;
std::string symbol;
for (auto str : args) {
// Iterate through each argument and see if it parses to one of these enums
uppercase(str);
bool used =
(venue == VENUE_UNSET && parse_enum(str, "VENUE", Venue_Parse, venue, &venue)) ||
Regular → Executable
View File
File mode changed.
+5 -5
View File
@@ -1,14 +1,14 @@
qa_sprint_id=18
qa_sprint_id=20
testers=(
#'pedro.pinto'
# 'eric.harding'
'jake.norbut'
'michael.harding'
# 'jake.norbut'
# 'michael.harding'
'karl.ellefsen'
'pete.fisher'
'taha.afzal'
'john.colvin'
# 'taha.afzal'
# 'john.colvin'
'kevin.darby'
'brian.muhr'
)
+2 -3
View File
@@ -20,10 +20,9 @@ On Toward=No Change
5. Select all the lean orders and change the Trade Toward Behavior to Cancel (don't commit yet).
As the parameter is changed its name should turn Green along with a *. Revert back and it should go to
No Change. Select a few of the leans and make sure Trade Toward Behavior is No Change. Now Change it
to Cancel and commit. Make sure it is set to Cancel for all the lean orders.
to Cancel and commit. Make sure it is set to Cancel for all the lean orders. This should cancel all the lean orders.
6. Move the ask book to 20.040. This should cancel all the leans (verifies the change
in 5 made through). Move the market back to 20.050
6. Move the market back to 20.050
7. Enter 2 leans, 4 and 6 lots (configured like 3) at 20.025 and 20.020 respectively. In the orderbook
select both and make sure the Price and Size show as - (since they are different). Change the Trade Toward
Regular → Executable
View File
File mode changed.
+1
View File
@@ -28,3 +28,4 @@ Sym,Mult,Exch
"BOB",1000,CBT
"BUB",1000,CBT
"FNU",1000,CBT
"SOM",500,CBT
1 Sym Mult Exch
28 BOB 1000 CBT
29 BUB 1000 CBT
30 FNU 1000 CBT
31 SOM 500 CBT
+1 -1
View File
@@ -2,6 +2,6 @@
if [ -f /.dockerenv ]; then
ninja
else
cid=`docker ps | grep bluetradingsystems/linux_docker | awk '{print $1}'`
cid=`docker ps | grep -P "emacs_ide|bluetradingsystems/linux_docker" | awk '{print $1}'`
docker exec $cid /bin/bash -c "cd build/clang_debug/ && ninja"
fi