Compare commits

...
242 Commits
Author SHA1 Message Date
Kevin Darby 2677144bfa buffer cancel and updates because ice sucks 2019-10-10 17:43:28 -04:00
Kevin Darby 6b30c42c0d added gt_cert jetfix rule to conf per Pete 2019-10-10 14:56:32 -04:00
Kevin Darby 2f62d29f66 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-10-09 14:03:11 -04:00
John Colvin dc8e65923d fix adminModel typo '&&' -> '||' (users need admin OR trade permissions to see account) 2019-10-09 12:00:25 -05:00
Eric Harding 1469373b9c fix Sparkcmd -h help printer 2019-10-08 15:59:15 -04:00
Kevin Darby 820e937336 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-10-08 12:49:58 -04:00
John Colvin 8b73878782 null check for TradingPermissions (fixes login crash) 2019-10-08 11:46:32 -05:00
Kevin Darby b15106dac4 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-10-08 11:43:22 -04:00
Michael Harding 100316b791 SP-246: Fix System Tests 2019-10-08 11:06:41 -04:00
Kevin Darby 3c98425226 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-10-07 12:53:44 -04:00
John Colvin 1aa9c46367 fix build (bad using directives after merge) 2019-10-07 10:48:12 -05:00
Kevin Darby 5211cab351 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-10-07 10:24:36 -04:00
Pedro Pinto e89a4cce53 Merged in sim_prorata (pull request #350)
RTM. Documented OrderMatcher better.
2019-10-07 13:38:41 +00:00
Eric Harding cb56b90737 Merged in SP-229-shell-crash-dumps (pull request #346)
RTM: SP-229 shell crash dumps

Approved-by: Jake Norbut <jake.norbut@bluetradesys.com>
2019-10-07 13:38:00 +00:00
Pedro Pinto 761a89f052 Updated release notes 2019-10-07 09:37:00 -04:00
Pedro Pinto cab6b56606 Merged master 2019-10-07 09:36:21 -04:00
Pedro Pinto 8a743a91a5 Updated release notes. 2019-10-07 09:29:30 -04:00
Taha Afzal 5dec5dc392 Merged in SP-232 (pull request #345)
RTM. Fixing SP-232

Approved-by: Pedro Pinto <pedro.pinto+atlassian@bluetradesys.com>
2019-10-07 13:28:30 +00:00
Eric Harding 27aa4fca26 Merged in system-tests (pull request #349)
RTM: System tests

Approved-by: Michael Harding <michael.harding@bluetradesys.com>
Approved-by: Pedro Pinto <pedro.pinto+atlassian@bluetradesys.com>
2019-10-07 13:20:35 +00:00
Pedro Pinto 84a2e50bf7 Updated release notes. 2019-10-07 09:19:18 -04:00
John Colvin 297eb5b25b Merged in SP-181-no-spreads-in-man-fills (pull request #352)
RTM SP-181 Remove the option to enter manual fills of spreads

Approved-by: Jake Norbut <jake.norbut@bluetradesys.com>
2019-10-07 13:18:26 +00:00
Pedro Pinto d9d0e1f4ef Updated release notes. 2019-10-07 09:15:21 -04:00
Eric Harding 6ec0cc8bbe Merged in SP-236-websocketpp (pull request #353)
RTM: SP-236 Disable websocketpp open_handshake timeout
2019-10-07 13:13:30 +00:00
Pedro Pinto 795b77ea3f Updated release notes. 2019-10-07 09:12:45 -04:00
John Colvin 91c97d32bb Merged in SP-223-som-synth-crash (pull request #355)
RTM add dispatcher thread name to assert log

Approved-by: Eric Harding <eric.harding@bluetradesys.com>
2019-10-07 13:11:57 +00:00
John Colvin e0c50703d7 Merged in SPARK-2534-fills-time-filter-bug (pull request #357)
RTM SPARK-2534 fills time filter bug

Approved-by: Jake Norbut <jake.norbut@bluetradesys.com>
2019-10-07 13:11:03 +00:00
Pedro Pinto dab1e76766 Updated release notes. 2019-10-07 09:10:32 -04:00
Pedro Pinto b8c927df27 Merge branch 'master' into SPARK-2534-fills-time-filter-bug 2019-10-07 09:02:25 -04:00
Pedro Pinto 2684d25f09 Updated release notes 2019-10-07 09:01:48 -04:00
John Colvin 7c95a77ae2 Merged in update-naggle-test (pull request #360)
RTM unit test for update.naggle fix
2019-10-07 13:00:06 +00:00
John Colvin 31b115d13b Merged in bts-admin-permissions (pull request #356)
RTM Bts admin permissions
2019-10-07 12:58:42 +00:00
Pedro Pinto d681a6924b Updated release notes. 2019-10-07 08:39:01 -04:00
Pedro Pinto d0cce84d2e Merge branch 'master' into bts-admin-permissions 2019-10-07 08:38:07 -04:00
Pedro Pinto 532591c34f Updated release notes. 2019-10-07 08:36:14 -04:00
John Colvin 7f187224c1 add .Replay(1).RefCount() to AdminModel.on_accounts 2019-10-02 13:40:29 -05:00
John Colvin 79b2121f5e OrderBookVM disposes order_mod_vm 2019-10-02 13:40:28 -05:00
John Colvin 0bd477594c FillsVM disposes filters 2019-10-02 13:36:58 -05:00
John Colvin 149cd90fb4 apply permission filter to pnl stream 2019-10-02 11:54:38 -05:00
John Colvin f74e719a9f sort accounts/users in filter dropdowns for OrderBook/Fills/PNL 2019-10-02 11:54:38 -05:00
John Colvin 8b68beae96 Merge remote-tracking branch 'origin/master' into bts-admin-permissions 2019-10-02 10:52:45 -05:00
Pedro Pinto 9cc0b471f2 Added support for tag 1031, defaults to Y. 2019-10-02 10:32:23 -04:00
Kevin Darby 50e61604ba move default keycode exp to 12/31/2019 to fix unit tests 2019-09-30 11:53:44 -04:00
Kevin Darby 6bd23f106f Merged in fix_nan_pnl (pull request #361)
add temporary config to ignore nan day pnl to stop the loss limit from keeping traders out of market
2019-09-30 15:07:11 +00:00
Kevin Darby dfd8348724 add temporary config to ignore nan day pnl to stop the loss limit from keeping traders out of market 2019-09-30 11:03:03 -04:00
John Colvin d2e9352e48 unit test for update.naggle fix 2019-09-25 12:01:31 -05:00
Kevin Darby da42e95754 fixed externals and docker 2019-09-25 10:59:58 -04:00
Kevin Darby a878a55ac1 moved externals 2019-09-25 10:00:20 -04:00
John Colvin 4305d560aa Merged in pnl-rounding-error (pull request #359)
RTM Pnl rounding error

Approved-by: Jake Norbut <jake.norbut@bluetradesys.com>
Approved-by: Eric Harding <eric.harding@bluetradesys.com>
2019-09-25 13:57:52 +00:00
John Colvin 055f0015e7 Update.naggle pr edit: 'TryPop' is an innappropriate name (just use 'Remove') 2019-09-24 17:28:06 -05:00
Kevin Darby a39d91ceb3 Merge branch 'pnl-rounding-error' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-24 14:38:26 -04:00
John Colvin ddc50e1fba pnl initial calc type was not being applied to data 2019-09-24 13:32:54 -05:00
John Colvin ffb571d1cf fix pnl rounding issues (use 9 decimal places) 2019-09-24 13:32:53 -05:00
John Colvin 2a36c05d75 fix PNLRowData Equals impl (was not comparing market prices) 2019-09-24 13:32:53 -05:00
John Colvin a3730eb203 Update.naggle merge maintains changes (could get into state where changes became adds/removes) 2019-09-24 13:32:53 -05:00
John Colvin d033275694 remove unused member OrdersModel.on_account_pnl 2019-09-24 13:32:53 -05:00
Jake Norbut 016ddf9b69 fixing pay less definition 2019-09-24 08:21:56 -05:00
John Colvin 0cc5817932 expand synthetic leg columns to fit name 2019-09-24 01:04:28 -05:00
Michael Harding 032836dea4 Test updates 2019-09-23 15:54:33 -04:00
Kevin Darby a06461eb5e Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-23 13:58:22 -04:00
Kevin Darby 34e7d6a617 remove ice bust handling 2019-09-23 13:57:43 -04:00
Kevin Darby 31e44d8c10 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-23 13:03:20 -04:00
Kevin Darby 8fdab4a510 note about expired securities in sod tests 2019-09-23 12:47:48 -04:00
Kevin Darby 385adaa1b0 Merge branch 'fix_expired_fill_crash' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-23 12:36:16 -04:00
Kevin Darby f9506bc9ad Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-23 12:36:00 -04:00
Kevin Darby 6b5b517d70 slight nit in GLBXExecutionGateway 2019-09-23 12:29:38 -04:00
John Colvin 80850146c1 TableUpdate.AggregateLatest shouldn't share seed across subscriptions 2019-09-23 00:08:12 -05:00
John Colvin 0680dddab4 normalize line endings in TickUpDown.xaml 2019-09-22 15:22:57 -05:00
John Colvin 70aa62c0cf add border to DateTimePicker 'time' part view 2019-09-22 15:22:20 -05:00
John Colvin 06165b3842 SPARK-2534 Fills Form seems to always have SOD orders in there 2019-09-22 15:06:03 -05:00
John Colvin f21902d60d remove unused files AdminModelWrapper/PermissionFilter.cs 2019-09-22 14:46:52 -05:00
John Colvin a27f383b62 remove LoginContainer MEF Export consts (replace usages with UserTuple) 2019-09-22 12:58:46 -05:00
John Colvin 35d4fcc513 make UserTuple public (it's referenced in multiple assemblies) 2019-09-22 12:58:46 -05:00
John Colvin 8a96b00f64 add 'User' column to Synthetic Management window 2019-09-22 12:58:46 -05:00
John Colvin 2d06fd3d92 [non-functional] style cop/whitespace changes to SyntheticManagementDialogVM.cs 2019-09-22 12:58:45 -05:00
John Colvin 76050e0722 SyntheticManagement vm uses 'DataGridFilterHelper.hook_all' method to eliminate risk of omitting column filters 2019-09-22 12:58:45 -05:00
John Colvin a3f0c2fbf6 pass UserTuple to SyntheticManagement row (for imminent user column), remove dependency on securitymd 2019-09-22 12:58:45 -05:00
John Colvin 1ccc4c3746 add 'ShowLadderAutoLookupTag' to eschew securitymd depependency 2019-09-22 12:58:45 -05:00
John Colvin e5d85db888 SP-151 BTS user can view/edit all synths/algos 2019-09-22 12:11:15 -05:00
John Colvin e47b1c3048 [non-functional] style cop/whitespace changes in MDSource/Daemon.cs 2019-09-22 12:11:15 -05:00
John Colvin 039791a296 simplify AdminModel, api 'permission filters' use new UserTuple.Permissions enum 2019-09-22 12:11:15 -05:00
John Colvin e6884b6654 add 'Permissions' enum to UserTuple 2019-09-22 11:39:26 -05:00
John Colvin 8cbae28dd8 move UserTuple.cs into spark_api 2019-09-22 11:39:26 -05:00
John Colvin 010a1fecb1 remove unused function 'OrderFactory.subscribe_user_tuples' 2019-09-22 11:39:26 -05:00
Kevin Darby 96bec55ee7 fix build, we will have to handle these ice cpps someplace else 2019-09-20 15:01:56 -04:00
Kevin Darby 424bb36fc7 update jakes script for ice cpps 2019-09-20 14:30:27 -04:00
Kevin Darby c24700195f fixed cpp coming from market data for ice, added the obligatory overrides 2019-09-20 14:15:27 -04:00
Jake Norbut f7184b0949 updating tests 2019-09-20 09:13:01 -05:00
Eric Harding 999973c349 upgrade websocketpp 0.7.0 to 0.8.1 (externals) 2019-09-19 14:59:09 -04:00
Eric Harding 4663ae9e4d SP-236 Disable websocketpp open_handshake timeout 2019-09-19 14:38:00 -04:00
Kevin Darby 34fc6af137 fix mview test 2019-09-19 14:17:53 -04:00
Kevin Darby 6cc25a7337 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-19 13:56:32 -04:00
Kevin Darby 48b62f1cab new externals 2019-09-19 13:40:01 -04:00
Kevin Darby 5a0ceafa66 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-19 13:28:31 -04:00
Kevin Darby d31969606e Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-19 13:27:52 -04:00
John Colvin d7d170f228 SP-181 Remove the option to enter manual fills of spreads 2019-09-19 11:23:36 -05:00
Eric Harding 1d538b4cb0 Code review feedback. Checked DeleteValue 2019-09-18 17:04:38 -04:00
Pedro Pinto b42febdf60 Documented OrderMatcher better. 2019-09-18 16:11:16 -04:00
Eric Harding 71915de4b0 sparkcmd CaseInsensitiveEnumValues 2019-09-18 15:47:53 -04:00
Kevin Darby facb3249d0 Merge branch 'minimal_api_tests' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-18 15:24:51 -04:00
Kevin Darby f323efc61a Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-18 15:24:14 -04:00
Eric Harding be5f54326e sparkcmd test should always respect test type (unit/system) 2019-09-18 15:16:28 -04:00
Michael Harding 65cf042639 Merge branch 'system-tests' into ice_exec3 2019-09-18 13:45:26 -04:00
Michael Harding 57526a5df5 merge system-tests into ice_exec3 2019-09-18 13:12:38 -04:00
Michael Harding 7d26ff641e more ports 2019-09-18 12:20:26 -04:00
Michael Harding a8ffe3a6ec logging ports 2019-09-18 11:20:13 -04:00
Michael Harding bda135c435 Add more logging to system tests 2019-09-18 10:12:40 -04:00
Kevin Darby 0fa97aeb56 added a service call to clear the auth sessions list in case of keycode trouble 2019-09-17 16:43:24 -04:00
Kevin Darby d1422ddc58 fix auth tests 2019-09-17 16:36:16 -04:00
Kevin Darby 51ffa7e7f7 set_mic for synthetics 2019-09-17 16:15:17 -04:00
Kevin Darby 2a89c3721b Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-17 15:20:57 -04:00
Kevin Darby 0156bbfc46 fix id corner case 2019-09-17 15:06:04 -04:00
Taha Afzal f89fb76cb2 Merge branch 'master' into SP-232 2019-09-17 14:11:26 -04:00
Taha Afzal 16adb9ee18 Fixing SP-232 2019-09-17 14:09:34 -04:00
Eric Harding 154a637ee1 Merge branch 'master' of bitbucket.org:bluetradesys/spark into SP-229-shell-crash-dumps 2019-09-16 17:34:36 -04:00
Kevin Darby 8b583fcbec Merge branch 'fix_server_bounce' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-16 17:11:00 -04:00
Kevin Darby 48dfded132 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-16 17:09:52 -04:00
Kevin Darby baaa3c4f98 Fixed case where a non-super user shell denied market data after bring left up through a server restart 2019-09-16 16:28:53 -04:00
Kevin Darby 838550d78a entitlements are tricky 2019-09-16 16:15:38 -04:00
Kevin Darby bf8323e79b fixed ice entitlements 2019-09-16 15:53:50 -04:00
Eric Harding 399e4bf654 SP-229 Detect unclean shell shutdown and automatically upload an error report 2019-09-16 13:48:12 -04:00
Eric Harding 5908b4478e Error reports should be logged on the client 2019-09-16 13:20:03 -04:00
Kevin Darby e6ab7d825a fix fs build 2019-09-16 11:15:56 -04:00
Kevin Darby c78e6e8315 rather large master -> ice merge 2019-09-16 10:43:19 -04:00
Eric Harding 44571a5af5 spark shell should dispose daemons 2019-09-16 10:41:58 -04:00
Eric Harding 62274f5129 Append windows event log and crash dumps to error reports 2019-09-12 17:18:47 -04:00
Eric Harding b5b5101faf SP-229 Allow ErrorReportService to accept an arbitrary list of files 2019-09-12 17:17:57 -04:00
Eric Harding bb232d8f1e Add easy convert to immutable function c# 2019-09-12 17:17:15 -04:00
John Colvin aaca502500 add dispatcher thread name to assert log 2019-09-09 11:42:11 -05:00
Kevin Darby 7d2695e602 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-09-06 11:46:40 -04:00
Eric Harding 14cbd4a174 ICE: make settlement price conditional on onMarketSnapshot 2019-08-19 16:30:37 -04:00
Kevin Darby cc3353e243 messed up the externals 2019-08-14 15:42:16 -04:00
Kevin Darby 683b85c66b subrepos 2019-08-14 15:25:27 -04:00
Kevin Darby 789710d841 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-08-14 15:25:19 -04:00
Kevin Darby 1a9ff09f43 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-08-08 16:58:31 -04:00
Michael Harding 13b09ffc12 add 3 minute delay to system tests 2019-08-07 10:42:41 -04:00
Kevin Darby 83a2a01789 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-08-06 12:06:46 -04:00
Kevin Darby e1137c4e1d go back to statically linked CME 2019-08-06 11:27:38 -04:00
Kevin Darby 0a6cc0cdf1 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-08-01 15:11:04 -04:00
Kevin Darby e96d9112ef SIMICE causing some trouble sharing replay and MBO 2019-08-01 14:25:17 -04:00
Kevin Darby 72aa028bd6 ice orders works again 2019-07-04 14:31:57 -04:00
Kevin Darby f8d5b9bace bookmark initial clordid 2019-07-03 18:20:11 -04:00
Kevin Darby e861e2916f Merge branch 'ice_exec3' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-07-03 17:28:03 -04:00
Kevin Darby 23738b109d changes to use non-static onixs 2019-07-03 17:26:46 -04:00
Pedro Pinto 713e11d146 Merge branch 'ice_exec3' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-07-03 16:26:34 -04:00
Pedro Pinto 444e3154b3 Made exchange id gen asynchronous, improved concurrency. 2019-07-03 16:26:07 -04:00
Kevin Darby 270ee60df9 nonstatic cme 2019-07-03 19:39:22 +00:00
Kevin Darby 1ce041c5e5 called Pedro's new id generator 2019-07-03 15:23:38 -04:00
Pedro Pinto 50940bfd13 Merged 2019-07-03 13:46:48 -04:00
Pedro Pinto 8cb4151f63 Added id generator to order services. 2019-06-30 20:27:48 -04:00
Kevin Darby 7a47b7a85a Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-06-28 13:08:44 -04:00
Pedro Pinto a60a792dfa Ran clang-format. 2019-06-27 14:17:08 -04:00
Pedro Pinto a73a1cc4f5 CMakeDeps updates. 2019-06-27 14:16:05 -04:00
Pedro Pinto 32fbdf8a21 Better handling of unresolved securities. 2019-06-27 14:15:40 -04:00
Pedro Pinto 75c54bbe3e Refactored order factory. 2019-06-27 14:11:40 -04:00
Pedro Pinto 38575039b9 Fixed clang build. 2019-06-27 14:11:23 -04:00
Kevin Darby 43a49b9399 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-06-10 10:40:56 -04:00
Kevin Darby 618c41ce97 synthesized Pedro's cme changes for ice 2019-06-07 17:49:33 -04:00
Kevin Darby bd8c9c354b Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-06-07 17:49:11 -04:00
Kevin Darby 8f5d062a3b Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-05-21 16:58:35 -04:00
Kevin Darby e1a3950051 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-05-20 17:04:53 -04:00
Kevin Darby 7e816c1503 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-05-16 17:56:07 -04:00
Kevin Darby 15d9afb2de added a comment about ice reverse_routing_record 2019-05-16 15:26:21 -04:00
Kevin Darby b5468e5565 changes for ice certification perf testing and to recover an order from an exec report 2019-05-16 15:02:04 -04:00
Kevin Darby a4c3a61f13 fixed ice specific bug with attach detach 2019-05-14 17:55:52 -04:00
Kevin Darby 7ce101f7f7 messed up docker linux pointer 2019-05-14 16:41:49 -04:00
Kevin Darby b61cab397d Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-05-14 16:36:12 -04:00
Kevin Darby 222e1a51dc fixed SOD time for dev
fixed bugs in mview when settle/last/low/high change without a bid or offer changing
2019-05-14 15:50:53 -04:00
Kevin Darby 9fa3464188 ice busts and corrects, ugh... 2019-05-14 09:55:05 -04:00
Kevin Darby fee695d3d9 Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-05-13 16:02:56 -04:00
Kevin Darby 140f1d88ea ice entitlements 2019-05-05 16:41:13 -04:00
Kevin Darby c4eeaf2ec8 this should do it for bust / adjust 2019-05-03 16:28:37 -04:00
Kevin Darby 54dd30245f Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-05-03 15:54:07 -04:00
Kevin Darby 263ff63a37 added concept of active and busted fill to support ice busts 2019-05-03 15:31:23 -04:00
Kevin Darby f3d16502de going a new way on the busts 2019-05-03 13:39:35 -04:00
Kevin Darby 4b7db298c4 something up with settlement re-price 2019-05-03 10:39:54 -04:00
Kevin Darby 65f41452fb work around onixs assert for us financials that does not have an implieds feed 2019-05-02 18:33:54 -04:00
Kevin Darby d7a2ae4b09 added spread marker to last trade display....lotta code for an S 2019-05-02 17:55:46 -04:00
Kevin Darby 61ac626542 ice wants tag 1031 2019-05-02 12:36:14 -04:00
Michael Harding 8d7a2f342e Add Custom Order Instructions 2019-05-02 12:14:50 -04:00
Kevin Darby 0db037175f fixed ice forced logout issue 2019-05-02 12:07:09 -04:00
Kevin Darby 98aa463b4e Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-05-02 11:51:28 -04:00
Kevin Darby 0b40d3971d lining up with ice downtime 2019-05-01 14:05:02 -04:00
Kevin Darby a21a769909 cleaned up todos 2019-04-30 17:43:23 -04:00
Kevin Darby ca8e540453 volume is tricky 2019-04-30 15:09:53 -04:00
Kevin Darby 134950747f bugs found during cert 2019-04-30 14:36:54 -04:00
Kevin Darby 5abc17adf3 settles 2019-04-29 17:58:53 -04:00
Kevin Darby f3cd3a402e ice spread config, workaround for onixs bug 2019-04-29 16:53:50 -04:00
Kevin Darby c7217b8475 Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-29 16:47:26 -04:00
Kevin Darby 99c5129ea7 ice spreads are weird 2019-04-29 16:25:54 -04:00
Kevin Darby d025ee0c89 seems to be an onixs bug that exits a loop early if not provisioned for a market_type 2019-04-29 15:09:56 -04:00
Kevin Darby c24ddaa190 Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-29 10:21:39 -04:00
Kevin Darby 442aa156ac trying to get orance juice market 2019-04-29 10:20:27 -04:00
Kevin Darby e906d41cc2 Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-26 14:48:20 -04:00
Kevin Darby 6e09d9e949 small changes for ice cert 2019-04-26 14:35:36 -04:00
Kevin Darby aea02e212a cleaned up cancel / reject messages 2019-04-25 16:36:07 -04:00
Kevin Darby a94a66234a ice puids 2019-04-25 15:57:04 -04:00
Kevin Darby 4cbbf6972a add, update, remove orders work across logouts 2019-04-25 15:25:07 -04:00
Kevin Darby caa9671c96 ids... 2019-04-24 18:37:45 -04:00
Kevin Darby 20eb3ed39d matched Pedro's ICE deferred cancel / update for ice 2019-04-24 14:07:21 -04:00
Kevin Darby 772a898433 Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-24 14:07:09 -04:00
Kevin Darby b5997d326e f# 64 bit ints, maybe 2019-04-23 18:22:44 -04:00
Kevin Darby f8626f81cd throwing this back to michael for int64 2019-04-23 18:14:14 -04:00
Kevin Darby bc208d2421 Merge branch 'ice_exec3' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-23 17:22:26 -04:00
Kevin Darby 625ebcc762 got a fill 2019-04-23 17:21:52 -04:00
Michael Harding 0a163badf0 SPARK-2289: Add MIFID fields to Spark Admin 2019-04-23 15:45:11 -04:00
Kevin Darby dea95455a0 Merge branch 'ice_exec3' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-23 13:28:45 -04:00
Kevin Darby f0f5988abf almost sending orders 2019-04-23 13:27:50 -04:00
Michael Harding db5f16985c SPARK-2289: Remove IFUnset from ICEMics 2019-04-23 11:00:38 -04:00
Michael Harding f0105867be SPARK-2289: Implement Eric's Map suggestion 2019-04-23 10:03:58 -04:00
Michael Harding 2c0b314428 SPARK-2289: Additional ICE fields 2019-04-23 10:03:12 -04:00
Kevin Darby 3cd74f33f1 changed trader login per Pedro 2019-04-22 16:51:28 -04:00
Kevin Darby a6ee36f4bc typo 2019-04-22 15:16:12 -04:00
Kevin Darby 9cadf635fb Merge branch 'ice_exec3' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-22 14:42:10 -04:00
Kevin Darby 43e043b044 more ice 2019-04-22 14:41:39 -04:00
Michael Harding 6bac75d7ab SPARK-2289: Add ICE to Accounts in Spark Admin 2019-04-22 10:58:26 -04:00
Michael Harding 7ceb170c5f SPARK-2289: Add ICE User data to Spark Admin 2019-04-22 10:36:35 -04:00
Kevin Darby 47c7ee71b4 Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-18 17:46:34 -04:00
Kevin Darby 4f58452771 stop using legacy spread 2019-04-17 18:14:00 -04:00
Kevin Darby d5bf15cc36 ice secondary login 2019-04-17 17:12:25 -04:00
Kevin Darby 9736541385 logon rejected; we're going places 2019-04-16 15:59:45 -04:00
Kevin Darby 5591c8316d about to send a login message 2019-04-16 13:18:39 -04:00
Kevin Darby a44d3a2c26 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-15 13:22:42 -04:00
Kevin Darby dceb300324 Merge branch 'SPARK-2241-add-support-for-multi-char-me' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-15 13:20:56 -04:00
Pedro Pinto 84b9ca3096 Added jetfix suppport for multi char message types. 2019-04-08 17:07:40 -04:00
Pedro Pinto 17e9f1ea96 Ran clang-format. 2019-04-08 13:43:20 -04:00
Kevin Darby 946ec36840 Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-06 22:18:21 -04:00
Kevin Darby 11425a898f honing in on simice 2019-04-05 17:58:28 -04:00
Kevin Darby d0029e7f88 sim doesn't crash, but doesn't give exec reports either 2019-04-05 17:39:04 -04:00
Kevin Darby bdbdda947f Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-05 15:51:51 -04:00
Kevin Darby f88ab57fa0 got the basic structure down, still waiting on ICE for a few things 2019-04-05 15:49:37 -04:00
Kevin Darby 36442a037e more ice 2019-04-03 17:12:52 -04:00
Kevin Darby 5969568dee ice native order 2019-04-02 17:36:12 -04:00
Kevin Darby 96265ea187 Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-02 17:34:54 -04:00
Kevin Darby 9676b1fdca Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec3 2019-04-02 16:21:51 -04:00
Kevin Darby 556132c2dd ice exec moving along 2019-04-01 18:11:48 -04:00
Kevin Darby a22b7b7189 more ice 2019-03-29 16:52:50 -04:00
Kevin Darby 8e41a42ced more ice 2019-03-28 16:18:10 -04:00
Kevin Darby e0f7bdfc13 fix conf 2019-03-27 17:42:23 -04:00
Kevin Darby ec0b96215f Merge branch 'SPARK-1944-attach/detach/update' of bitbucket.org:bluetradesys/spark into ice_exec 2019-03-27 17:29:32 -04:00
Kevin Darby e27a8be526 ICEExecutionGateway 2019-03-27 17:01:07 -04:00
Kevin Darby 70cd9f185e Merge branch 'ice_md' of bitbucket.org:bluetradesys/spark into ice_exec 2019-03-26 18:44:16 -04:00
Kevin Darby 33eaf6f86d beginnings of ICE exec and SIMICE 2019-03-26 18:38:05 -04:00
194 changed files with 6290 additions and 1834 deletions

No files matched your search

@@ -154,7 +154,7 @@ insert_anchor_links = "right"
- Pay Less - If enabled by checking the checkbox, the spreader will
attempt to pay less when the quantity at the level of the calculated
hedge price is more than the threshold defined.  The hedge order is
hedge price is less than the threshold defined.  The hedge order is
paid less by the “Payless Ticks” as defined per leg.
- Pay Up - If enabled by checking the checkbox, the spreader will pay
up when the quantity at the level of the calculated hedge price is
+54 -41
View File
@@ -4,17 +4,30 @@ weight = 3
sort_by = "weight"
insert_anchor_links = "right"
+++
## 2.11.0
### User Visible Changes
- Fixed fills form time filter to also apply to SOD fills
- Addressed an issue that could prevent the web Admin UI from displaying over slow HTTP connections
- Removed the option to enter manual spread fills
- Fixed an issue that could cause erroneous fill account attribution in the event of a crash
### Internal Changes
- Added support for tag 1031. Currently defaults to Y, can it be override through config.
- To facilitate support, allowed the bts user to view and edit algos from all other users
- Improved system tests
- Improved log messages in UI to include dispatcher thread name
- Added support for Windows core dumps in the UI
## 2.10.0
### User Visible Changes
- Fills now include information about the algo that originated the fill
- A new, more powerful PnL form is now available
### API Changes
- Added security state information (pre open, halted, normal, closed, etc)
- Added security state information (pre open, halted, normal, closed, etc)
### Bug Fixes
- Brought back the "select all" check box in the mini order book
- Fixed an issue in the market data subsystem that on rare occasions could result in a startup crash
### Internal Changes
- Fixed an issue that was stopping us from interpreting SOD times as local rather than GMT
- Fixed an issue that was stopping us from interpreting SOD times as local rather than GMT
## 2.9.3
### Internal Changes
- Fixed system test scripts
@@ -30,7 +43,7 @@ insert_anchor_links = "right"
- Avoided shipping production configuration defaults that lead to trying to download a position file for the development sftp server.
### Api
- C# API sample now uses synchronous calls.
## 2.9.0
### User Visible Changes
- Improved Workspace management User Interface
@@ -38,11 +51,11 @@ insert_anchor_links = "right"
- The Spark UI Window group now has a title in the Windows task bar
- Added sound alerts for trade events, see Launcher -> Settings -> Alerts
- Allowed composite algos that are attached to existing orders to identify fills that were already present prior to attachment
- Added import facilities for GMI position files
- Added import facilities for GMI position files
- Added the ability for risk managers to enter manual fills
- Added "raw" P&L columns, that is columns that *do not* include spread legs in their accounting
### Bug Fixes
- Fixed the settings action menu (Load/Save/Reset to Factory)
- Fixed the settings action menu (Load/Save/Reset to Factory)
- Fixed the method used to determine if a security is expired to take into account the start of day time
### API Changes
- Fixed an issue in the Client SDK that could lead to occasional failures to connect to the spark server as well as excessive memory usage.
@@ -79,10 +92,10 @@ insert_anchor_links = "right"
- Made it easier to generate simple UI's for new order types
### API Changes
- Dynamic orders can now use QuantityMeasure parameter types
## 2.7.2
### User Visible Changes
- Changed the login dialog to avoid leaking workspace names from other users.
- Changed the login dialog to avoid leaking workspace names from other users.
- Added new Splitter algo. From the manual: The splitter is useful
for pro-rata markets where you want to vary your exposure
independent of the order quantity that you want to fill. The
@@ -90,13 +103,13 @@ insert_anchor_links = "right"
the order quantity but it will put exposed_qty total size on the
market. Splitter favors order size over queue position.
### Internal Changes
- Made spark more resilient to lack of connectivity to the CME web site for downloading of templates.
- Made spark more resilient to lack of connectivity to the CME web site for downloading of templates.
## 2.7.1
### User Visible Changes
- Fixed some issues with the Cover algo, where in some circumstances
it would erroneously cancel launched hedges on completion.
## 2.7.0
### User Visible Changes
- Allowed algos to process "in-flight" fills while shutting down
@@ -115,25 +128,25 @@ insert_anchor_links = "right"
### User Visible Changes
- Fixed an issue in the ladder where in some cases the mini order book could not be brought up from a badge
- Fixed a rare race condition that could lead to erroneous limit enforcement
- Fixed an issue with the margin limits where an error could occur if an account name with more than 12 chars was used
- Fixed an issue with the margin limits where an error could occur if an account name with more than 12 chars was used
## 2.6.1
### User Visible Changes
- Fixed an issue in the ladder where an error could occur when trying to change ladder settings for the first time
## 2.6.0
### User Visible Changes
- In the ladder made last trade more distinctive when overlayed on the volumn column
- In the ladder, corrected display of volume tool tip
- In the ladder, corrected display of volume tool tip
- In the ladder, changed the consolidation of last trade to consider only the price ignoring aggressor changes
- Added an option for the Top Algo to delete itself if within N ticks from top of book
- Address a rare issue that could lead to an error report on UI exit
- Added margin risk limits
- Added the "Offset" algo. Offset prices a child algo at a parameterizable distance from the top of the book
- Avoided switching the current account and order type on open ladders when limits are changed
- Avoided switching the current account and order type on open ladders when limits are changed
### Internal Changes
- Ensure that admin logins are always allowed to login, regardless of keycode status.
## 2.5.0
### User Visible Changes
- Added loss limit risk check
@@ -163,13 +176,13 @@ insert_anchor_links = "right"
- Made Cover order more independent from its hedging chidren:
- Cover continues to operate even if an hedging child is canceled
- When a cover is canceled it will detach from any running hedging children, instead of canceling them
- Changed Lean, Join and Cover algos to hide themselves in the ladder once they have completed their work
- Changed Lean, Join and Cover algos to hide themselves in the ladder once they have completed their work
- Changed manual fills to appear in day PnL rather than in the SOD records
- Add buy/sell coloring to fill rows in fills window
- Streamlined the mini order book:
- Display of the mini order book popup is quicker
- Only exchange orders are displayed
- Update buttons are only displayed for orders that are under control of an algo with the update applying to the entire algo, not just the exchange order
- Update buttons are only displayed for orders that are under control of an algo with the update applying to the entire algo, not just the exchange order
- We can now select multiple rows to attach, detach, update or cancel multiple orders in a batch
- A checkbox column has been added to make clearer which rows are selected
### API Changes
@@ -179,7 +192,7 @@ insert_anchor_links = "right"
- Added system requirements to Spark documentation
- Implemented keycodes
- Temporarily rejected stop and stop limit orders, pending bug fixes
## 2.2.0
### User Visible Changes
- Made our orders easier to spot in MBO display
@@ -190,30 +203,30 @@ insert_anchor_links = "right"
- Improved handling of orders with undiscovered securities
- Added feedback to the ladder when the user attempts to middle click on bid/ask columns using an order that does not have parameters
- Fixed display of algo studio algo types in order book
- Hid net change setting in synthetic ladders
- Hid net change setting in synthetic ladders
- Fixed a number of problems with filtering on the Fills form
- On the Lean algo, OnToward and Away are now calculated with respect to the opposite inside market at time of the order launch
- Iceberg Spreaders with queue holders are not erroneously cancelled after the first fill
- Added security symbol column to fills window
- Re-organized ladder settings dialog to make it clearer and easier to use
## 2.1.4
### User Visible Changes
- Fixed handling of cancel button in security picker
## 2.1.3
### User Visible Changes
- Fixed a simulator bug in the handling of 0 sized orders
- Fixed a simulator bug in the handling of 0 sized orders
## 2.2.1
### User Visible Changes
- Fixed order book form exception when display a spreader order for whichs the legs were not present yet
## 2.1.1
### User Visible Changes
- Added PIQ to GLBX Iceberg orders
- Corrected handling of stop limit orders
## 2.1.0
### User Visible Changes
- Added support for the GLBX Iceberg order type
@@ -224,7 +237,7 @@ insert_anchor_links = "right"
- Added PIQ to the mini order book
- Fixed a rare bug that could lead to server failure when requesting market data
- Fixed a bug that could cause incorrect price displays for certain types of synthetic securities
## 2.0.5
### User Visible Changes
- Fixed a bug in the handling of rejected QHO orders
@@ -234,19 +247,19 @@ insert_anchor_links = "right"
## 2.0.4
### User Visible Changes
- Fixed performance regression in order manager
### Internal changes
- Improved market data diagnostics for bad configurations
- Changed market data default buffer size
## 2.0.3
### Internal changes
- Improved backwards compatibility in UI settings
## 2.0.2
### User Visible Changes
- Middle click the ladder price column to show the orders for that price level
- Middle click the ladder price column to show the orders for that price level
- Middle click the bid or ask column in the ladder no longer sends an order
### Internal changes
@@ -274,8 +287,8 @@ insert_anchor_links = "right"
- Improved settings manager tool output
- Added diagnostics in the event MD memory corruption is detected
- Added systems tests for join,lean, iceberg and spreader orders
- Made exchange order recovery more resilient in the presence of database loss
- Made exchange order recovery more resilient in the presence of database loss
## 1.6.2
### User Visible Changes
### Exchange simulator
@@ -314,21 +327,21 @@ insert_anchor_links = "right"
- These columns can be restored by toggling their visibility within the PnL's Settings form
- A new Traded Today column has been added to the PnL
- Filtering on this column will allow a user to restrict the report to only show today's position
### Internal changes
- Improved organization of the shell notification architecture
### Internal changes
- Improved organization of the shell notification architecture
- Added logging to help troubleshoot shell exit hang
## 1.5.6
### User Visible Changes
- Fixed a bug that could cause limits to be erroneously enforced
- Fixed a bug that could cause limits to be erroneously enforced
- Improved algo documentation
- Changed how the spreader uses net change
- Simplified trigger algo user interface
### Internal changes
### Internal changes
- Defaulted to not recording sim market data
- Improved documentation build
- Improved documentation build
- Added additional performance tracing
## 1.5.5
- Fixed Market View 'stale working orders' bug
@@ -336,11 +349,11 @@ insert_anchor_links = "right"
- Avoided logging when warming up cache
## 1.5.3
- Fixed sounds startup issue
- Fixed sounds startup issue
## 1.5.2
- Added better logging to AlgoDefinitionService
## 1.5.1
- Fixed missing securities in the Fills and P&L windows.
@@ -361,7 +374,7 @@ insert_anchor_links = "right"
#### Bug Fixes
- Fixed the "Since Open" time filter to use the exchange open time rather than 8:30 AM
- Fixed a bug in the order book where sometimes parent orders would not update their last message column.
#### Algos
- Added OCO Algo
- 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
@@ -369,7 +382,7 @@ insert_anchor_links = "right"
- Improved SDK documentation and usability
- Dynamic orders are now properly identified in the order book
#### Documentation
- Information on the Spark API has been added to the Spark manual
- Information on the Spark API has been added to the Spark manual
- The documentation has been updated and reorganized to make information easier to find
### Internal Changes
- Improved robustness of limit system test
+53 -62
View File
@@ -1,83 +1,74 @@
using bts;
using bts.api.admin;
using bts.api.core;
using bts.utils;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using bts.api.core;
using mbts.ui.shell;
namespace mbts.spark {
[Export]
class AdminModel : IDisposable {
public readonly UserTuple user;
readonly BehaviorSubject<IReadOnlyDictionary<uint, string>>
_accounts_subject = new BehaviorSubject<IReadOnlyDictionary<uint, string>>(new Dictionary<uint, string>()),
_users_subject = new BehaviorSubject<IReadOnlyDictionary<uint, string>>(new Dictionary<uint, string>());
IReadOnlyDictionary<uint, string>
_account_map = new Dictionary<uint, string>(),
_user_map = new Dictionary<uint, string>();
readonly BehaviorSubject<AdminModelWrapper> _wrapper_subject = new BehaviorSubject<AdminModelWrapper>(new AdminModelWrapper());
IDisposable _dispose;
IDisposable _dispose;
IReadOnlyDictionary<uint, string> _account_map = DictionaryHelper.empty<uint, string>();
[ImportingConstructor]
AdminModel(AdminService service, [Import]UserTuple user) {
AdminModel(AdminService service, UserTuple user) {
this.user = user;
_dispose = service.subscribei_admin_data().Select(update => {
_wrapper_subject.OnNext(new AdminModelWrapper(update.all.TryFirst(), user.name));
IEnumerable<BTSUserImmutable> active_users =
from admin_data in update.all
from bts_user in admin_data.Users
where bts_user.Name == user.name && bts_user.HasUserData && bts_user.UserData.HasAccountPermissions
select bts_user;
IEnumerable<BTSAccountImmutable> active_accounts =
from admin_data in update.all
from bts_account in admin_data.Accounts
where bts_account.IsPresent && _wrapper_subject.Value.can_view_account(bts_account.Name)
join account_id in (
from bts_user in active_users
from account_id in bts_user.UserData.AccountPermissions.AccountPermissions.Keys
select account_id
) on bts_account.Id equals account_id
select bts_account;
var users = active_users.ToDictionary(u => u.Id, u => u.Name);
var accounts = active_accounts.ToDictionary(a => a.Id, a => a.Name);
return (users, accounts);
}).Subscribe(t => {
_account_map = t.accounts;
_user_map = t.users;
_users_subject.OnNext(_user_map = t.users);
_accounts_subject.OnNext(_account_map = t.accounts);
});
// accounts
on_accounts = service.subscribei_admin_data()
.Select(up => up.all.TryGetFirst(out var ad) && ad.Users.Where(u => u.Name == user.name).TryGetSingle(out var usr) && usr.HasUserData && usr.UserData.HasAccountPermissions ?
usr.UserData.AccountPermissions.AccountPermissions
.Where(kv => (kv.Value.TradingPermission != null && kv.Value.TradingPermission.HasPermissions) || kv.Value.AdminPermission.HasPermissions)
.Select(kv => ad.Accounts.Where(a => a.Id == kv.Key).TryGetSingle(out var acc) ? acc : (BTSAccountImmutable?)null)
.Where(acc => acc.HasValue)
.Select(acc => acc.Value)
.ToDictionary(acc => acc.Id, acc => acc.Name) :
new Dictionary<uint, string>(0))
.Replay(1)
.RefCount();
// users
on_users = Observable.Return(DictionaryHelper.wrap_value(user.id, user.name));
all_user_tuples = user.permissions == UserTuple.Permissions.Admin ?
service.subscribei_admin_data()
.Select(u => u.all.TryFirst())
.Where(ad => ad.HasValue)
.Select(ad => ad.Value.Users
.Where(u => user.can_access_user_data(u.Id))
.Select(u => new UserTuple(u.Id, u.Name))
.ToDictionary(UserTuple.key_fn))
.Table(UserTuple.key_fn)
.Cache() :
Observable.Return(TableUpdate<UserTuple, uint>.mk_empty(UserTuple.key_fn).with_added(new[] { user }));
_dispose = on_accounts.Subscribe(map => _account_map = map);
}
public IObservable<IReadOnlyDictionary<uint, string>> on_users => _users_subject.AsObservable();
public IObservable<IReadOnlyDictionary<uint, string>> on_accounts => _accounts_subject.AsObservable();
public IObservable<IReadOnlyList<UserTuple>> on_user_tuples => on_users.Select(d => d.Select(kv => new UserTuple(kv.Key, kv.Value)).ToList());
public IObservable<IReadOnlyList<AccountTuple>> on_account_tuples => on_accounts.Select(d => d.Select(kv => new AccountTuple(kv.Key, kv.Value)).ToList());
public IObservable<AdminModelWrapper> on_admin_data => _wrapper_subject.AsObservable();
public IObservable<IReadOnlyDictionary<uint, string>> on_users { get; }
public IObservable<IReadOnlyDictionary<uint, string>> on_accounts { get; }
public IObservable<TableUpdate<UserTuple, uint>> all_user_tuples { get; }
public IObservable<IReadOnlyList<AccountTuple>> on_account_tuples => on_accounts.Select(d => d.Select(kv => new AccountTuple(kv.Key, kv.Value)).ToListSorted(a => a.name));
public AccountTuple? get_default_account() {
foreach (var kv in _account_map) {
return new AccountTuple(kv.Key, kv.Value);
}
return null;
}
public uint? get_user_id(string user) => _id_for_name(user, _user_map);
public uint? get_account_id(string account) => _id_for_name(account, _account_map);
public void Dispose() => Disposable.dispose(ref _dispose);
public IObservable<Update<T, TKey>> permission_filter<T, TKey>(IObservable<Update<T, TKey>> positions, Func<T, uint> get_account_id) where TKey : IEquatable<TKey> =>
user.permissions == UserTuple.Permissions.Admin ?
positions :
positions.Filter(on_accounts.Select(map => new Func<T, bool>(p => map.ContainsKey(get_account_id(p)))));
static uint? _id_for_name(string name, IReadOnlyDictionary<uint, string> map) {
foreach (var kv in map) {
if (kv.Value == name)
return kv.Key;
}
return null;
}
public IObservable<Update<T, TKey>> permission_filter<T, TKey>(IObservable<Update<T, TKey>> positions, Func<T, string> get_account_name) where TKey : IEquatable<TKey> =>
user.permissions == UserTuple.Permissions.Admin ?
positions :
positions.Filter(on_accounts.Select(map => {
var hash = new HashSet<string>(map.Values);
return new Func<T, bool>(v => hash.Contains(get_account_name(v)));
}));
public AccountTuple? get_default_account() =>
_account_map.Select(kv => new AccountTuple(kv.Key, kv.Value)).TryFirst();
public void Dispose() =>
Disposable.dispose(ref _dispose);
}
}
+3 -8
View File
@@ -3,15 +3,10 @@ using mbts;
using mbts.config;
using mbts.spark;
using mbts.ui;
using mbts.ui.shell;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
@@ -23,8 +18,8 @@ namespace bts.ui {
IDisposable _dispose;
[ImportingConstructor]
public AboutDaemon(IBus bus, [Import(LoginContainer.Exports.UserName)]string username) {
_user = username;
public AboutDaemon(IBus bus, UserTuple user) {
_user = user.name;
_bus = bus;
_dispose = bus.subscribe(SparkTags.About).OnDispatcher().Subscribe(_ => show_about());
}
@@ -63,4 +58,4 @@ namespace bts.ui {
Disposable.dispose(ref _dispose);
}
}
}
}
+44 -7
View File
@@ -7,13 +7,11 @@ using mbts.ui;
using System;
using System.ComponentModel.Composition;
using System.Reactive.Linq;
using System.Windows.Threading;
using System.Windows;
using System.Threading.Tasks;
using mbts.ui.shell;
using System.Windows;
using System.Windows.Threading;
namespace bts.spark
{
namespace bts.spark {
[Export, Export(typeof(IShellDaemon))]
public class ErrorReporter : IShellDaemon, IDisposable {
readonly ErrorReportService _svc;
@@ -21,9 +19,9 @@ namespace bts.spark
IDisposable _dispose;
[ImportingConstructor]
public ErrorReporter(ErrorReportService svc, IBus bus, [Import(LoginContainer.Exports.UserName)] string username) {
public ErrorReporter(ErrorReportService svc, IBus bus, UserTuple user) {
_svc = svc;
_username = username;
_username = user.name;
_dispose = bus.subscribe(SparkTags.Support).OnDispatcher().Subscribe(msg => show_support_window(msg, "Report a problem"));
}
@@ -48,6 +46,45 @@ namespace bts.spark
ErrorMessage = message,
});
}
public async Task report_silently(string contact, string description, string userdata) {
var request = append_logs(new ErrorReport {
User = _username,
ErrorMessage = description,
UserDescription = userdata,
Contact = contact
}.immutable());
var reply = await _svc.send_report_async(request);
}
public static ErrorReportImmutable append_logs(ErrorReportImmutable src) {
var result = src.CloneToMutable();
var windows_log = LogUtil.read_windows_event_log();
if (!windows_log.IsEmpty) {
result.Files.Add(new FileData {
Name = "Application.evtx.gz",
Contents = windows_log
});
}
var (data,date) = LogUtil.read_latest_crash_dump();
if (!data.IsEmpty) {
result.Files.Add(new FileData {
Name = $"spark-{date.ToString("s")}.dmp.gz",
Contents = data
});
}
var spark_log = LogUtil.read_logs_compressed();
if (!spark_log.IsEmpty) {
result.Files.Add(new FileData {
Name = "log.gz",
Contents = spark_log
});
}
return result.immutable();
}
}
static class ErrorReporterExtensions {
+13 -21
View File
@@ -1,5 +1,6 @@
using bts.api;
using bts.api.synthetic;
using bts.md;
using mbts;
using mbts.co2;
using mbts.spark;
@@ -7,15 +8,10 @@ using mbts.ui;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Linq;
using SecurityKey = System.UInt32;
using System.Collections.Concurrent;
using System.Threading;
using bts.api.user;
using bts.md;
using mbts.ui.shell;
namespace bts {
[Export(typeof(IInitializable))]
@@ -25,17 +21,21 @@ namespace bts {
readonly Lazy<SyntheticSecurityService> _ss;
readonly Dictionary<SecurityKey, SecurityMD> _deleted_synthetics = new Dictionary<SecurityKey, SecurityMD>();
static uint get_naggle() => mbts.config.Configuration.get<md.RelayOptions>().naggle_ms;
[ImportingConstructor]
public MDDaemon(Lazy<IBus> bus, Lazy<AuthTokenImmutable> token, Lazy<SyntheticSecurityService> ss, [Import(LoginContainer.Exports.UserID)]uint user_id) :
base(get_naggle(), MDSourceOptions.DeferInit, user_id) {
public MDDaemon(Lazy<IBus> bus, Lazy<AuthTokenImmutable> token, Lazy<SyntheticSecurityService> ss, UserTuple user)
: base(mbts.config.Configuration.get<md.RelayOptions>().naggle_ms, MDSourceOptions.DeferInit, user) {
_bus = bus;
_token = token;
_ss = ss;
_ss = ss;
}
override public void initialize() {
public int priority => 55;
[Export]
MDConsumer consumer => _consumer;
IBus bus => _bus.Value;
public override void initialize() {
_relay.set_token(_token.Value);
_dispose.Add(
_ss.Value.subscribei_metadata()
@@ -60,16 +60,8 @@ namespace bts {
// Post full dictionary of syntheics here
bus.post(SparkTags.SyntheticstrategiesTag, t);
}));
_dispose.Add( this.on_securities.Subscribe( (md) => {
bus.post(SparkTags.SecuritiesTag, md);
}));
_dispose.Add(on_securities.Subscribe(md => bus.post(SparkTags.SecuritiesTag, md)));
Task.Run(run);
}
[Export]
MDConsumer consumer => _consumer;
public int priority => 55;
IBus bus => _bus.Value;
}
}
+55
View File
@@ -0,0 +1,55 @@
using System;
using System.ComponentModel.Composition;
using mbts.ui;
using mbts;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace bts.spark {
[Export(typeof(IShellDaemon))]
class OopsDaemon : IShellDaemon, IDisposable {
[ImportingConstructor]
public OopsDaemon(ErrorReporter e) {
var pid = get_pid();
if (pid.HasValue) {
handle_unclean_shutdown(e, pid.Value);
}
save_pid();
}
public void Dispose() {
clear_pid();
}
void handle_unclean_shutdown(ErrorReporter e, int oldpid) {
string extra = "";
try {
var conf = mbts.config.Configuration.get<bts.config.System>();
extra = JsonConvert.SerializeObject(conf, Formatting.Indented);
}
catch { }
Task.Run(() => e.report_silently(
$"Host: {Environment.MachineName}",
$"pid: {oldpid}\n{extra}",
"Automated crash report")
);
}
const string _subkey = @"Software\BTS";
private void save_pid() {
using (var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(_subkey)) {
key.SetValue("pid", System.Diagnostics.Process.GetCurrentProcess().Id, Microsoft.Win32.RegistryValueKind.DWord);
}
}
private void clear_pid() {
using (var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(_subkey)) {
key.DeleteValue("pid",false);
}
}
private int? get_pid() {
using (var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(_subkey)) {
return key.GetValue("pid") as int?;
}
}
}
}
@@ -3,17 +3,13 @@ using bts.metrics;
using mbts;
using mbts.config;
using mbts.ui;
using mbts.ui.shell;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
namespace bts.perf {
[Export, Export(typeof(IShellDaemon))]
class ShellLatencyDaemon : IShellDaemon, IDisposable {
readonly ShellLatencyService _service;
@@ -24,10 +20,10 @@ namespace bts.perf {
Ping _pinger = new Ping();
[ImportingConstructor]
public ShellLatencyDaemon(ShellLatencyService service, [Import(LoginContainer.Exports.UserName)] string user) {
public ShellLatencyDaemon(ShellLatencyService service, UserTuple user) {
_service = service;
_version = Configuration.get<bts.config.System>().version;
_username = user;
_username = user.name;
_hostname = Environment.MachineName;
_forever_ping_host(_pinger);
@@ -105,4 +101,4 @@ namespace bts.perf {
Disposable.dispose(ref _subs);
}
}
}
}
@@ -5,7 +5,6 @@ using mbts.co2;
using mbts.persist;
using mbts.spark;
using mbts.ui;
using mbts.ui.shell;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
@@ -13,13 +12,11 @@ using System.Threading.Tasks;
using System.Windows.Media;
using static mbts.ui.shell.ProtoBufSerializationHelper;
namespace bts.shell
{
namespace bts.shell {
[Export(typeof(IShellModule))]
class MarketShellModule : IShellModule
{
class MarketShellModule : IShellModule {
[ImportingConstructor]
public MarketShellModule(IBus bus, MDConsumer consumer, UserSettingsHub settings_hub, OrdersModel orders_model, [Import(LoginContainer.Exports.UserName)]string user_name) {
public MarketShellModule(IBus bus, MDConsumer consumer, UserSettingsHub settings_hub, OrdersModel orders_model) {
_tsf = new TimeAndSalesWindowFactory(this, bus, consumer, settings_hub);
_mvf = new MarketViewWindowFactory(this, bus, settings_hub, orders_model);
}
@@ -26,6 +26,7 @@ namespace mbts.spark {
readonly ObservableFilterCollection<OrderRecordImmutable> _working_orders, _working_bids, _working_asks;
readonly string _security_text, _security_key_text;
readonly Property<double> _bid_price, _ask_price, _last_price, _day_change, _settlement, _session_high, _session_low;
readonly Property<bool> _last_price_from_spread;
readonly CellProperty<int> _position;
readonly CellProperty<uint> _last_size;
readonly CellProperty<ulong> _volume;
@@ -54,6 +55,7 @@ namespace mbts.spark {
_day_change = backing(nameof(day_change), double.NaN);
_session_low = backing(nameof(session_low), double.NaN);
_session_high = backing(nameof(session_high), double.NaN);
_last_price_from_spread = backing(nameof(last_price_from_spread), false);
_settlement = backing(nameof(settlement), double.NaN);
_volume = new CellProperty<ulong>(this, nameof(volume), 0);
_inside_bids = new CellProperty<bool>(this, nameof(inside_bids));
@@ -109,6 +111,7 @@ namespace mbts.spark {
public int position => _position.value;
public double raw_day_position => _raw_day_position;
public double last_price => _last_price.Value;
public bool last_price_from_spread => _last_price_from_spread.Value;
public uint last_size => _last_size.value;
public double bid_price => _bid_price.Value;
public uint bid_direct_size => _bid_direct_size.Value;
@@ -167,15 +170,17 @@ namespace mbts.spark {
_inside_bids.on_next_distinct(_bid_price.Value >= _working_best_bid.value, ref dirty);
_inside_asks.on_next_distinct(_ask_price.Value <= _working_best_ask.value, ref dirty);
}
if (md.md.get_last_trade(ref _last_ref, out NativePriceSize ps, out DateTime ts, out ulong v)) {
if (md.md.get_last_trade(ref _last_ref, out NativePriceSize ps, out DateTime ts, out ulong v, out bool from_spread)) {
_last_price.set(ps.price);
_last_price_from_spread.set(from_spread);
_last_size.on_next_distinct(ps.size, ref dirty);
_volume.on_next_distinct(v, ref dirty);
}
_settlement.set(md.md.settlement_price);
_session_low.set(md.md.session_low);
_session_high.set(md.md.session_high);
_day_change.set(last_price - settlement);
dirty |= _settlement.set_new(md.md.settlement_price);
dirty |= _session_low.set_new(md.md.session_low);
dirty |= _session_high.set_new(md.md.session_high);
dirty |= _day_change.set_new(last_price - settlement);
_volume.on_next_distinct(md.md.total_volume, ref dirty);
if (dirty)
invalidated?.Invoke();
@@ -38,7 +38,8 @@ namespace mbts.spark {
IMultiValueConverter price_converter = new ui.spark.converters.TickDisplayConverter();
add_col(Columns.Security, "Security", r => r.security.ToString(), nameof(Row.security), DefaultColumnWidths.Security, security_filter, DataGridFilterKnownTemplates.Regex);
add_col(Columns.Volume, "Volume", r => r.volume.ToString(), nameof(Row.volume), DefaultColumnWidths.Volume, volume_filter, DataGridFilterKnownTemplates.ULongMinMax);
add_col(Columns.Last, "Last", r => r.format_price(r.last_price), nameof(Row.last_price), DefaultColumnWidths.Price, last_price_filter, DataGridFilterKnownTemplates.DoubleMinMax);
add_col(Columns.LastSpd, "Spd", r => r.last_price_from_spread ? "S" : "", nameof(Row.last_price_from_spread), DefaultColumnWidths.Side, last_price_from_spread_filter, DataGridFilterKnownTemplates.Regex);
add_col(Columns.Last, "Last", r => r.format_price(r.last_price), nameof(Row.last_price), DefaultColumnWidths.Price, last_price_filter, DataGridFilterKnownTemplates.DoubleMinMax);
add_col(Columns.LastSize, merged_size_col_header, r => r.last_size.ToString(), nameof(Row.last_size), DefaultColumnWidths.Size, last_size_filter, DataGridFilterKnownTemplates.UIntMinMax, h_alignment: System.Windows.HorizontalAlignment.Right);
add_col(Columns.Position, "Pos", r => r.position.ToString(), nameof(Row.position), DefaultColumnWidths.Size, position_filter, DataGridFilterKnownTemplates.IntMinMax, true, h_alignment: System.Windows.HorizontalAlignment.Right);
add_col(Columns.RawDayPosition, "Raw Day Pos", r => SparkUtils.fmt_position(r.raw_day_position), nameof(Row.raw_day_position), DefaultColumnWidths.Size, raw_day_position_filter, DataGridFilterKnownTemplates.DoubleMinMax, true, h_alignment: System.Windows.HorizontalAlignment.Right);
@@ -138,6 +139,7 @@ namespace mbts.spark {
ask_direct_size_filter.load_state(filters.ask_direct_size);
ask_implied_size_filter.load_state(filters.ask_implied_size);
last_price_filter.load_state(filters.last_price);
last_price_from_spread_filter.load_state(filters.last_price_from_spread);
last_size_filter.load_state(filters.last_size);
day_change_filter.load_state(filters.day_change);
settlement_filter.load_state(filters.settlement);
@@ -155,7 +157,7 @@ namespace mbts.spark {
}), DataGridFilterHelper.hook_filters(rows_view, security_filter,
bid_price_filter, bid_merged_size_filter, bid_direct_size_filter, bid_implied_size_filter,
ask_price_filter, ask_merged_size_filter, ask_direct_size_filter, ask_implied_size_filter,
last_price_filter, last_size_filter, day_change_filter, settlement_filter,
last_price_filter, last_price_from_spread_filter, last_size_filter, day_change_filter, settlement_filter,
session_low_filter, session_high_filter, position_filter, raw_day_position_filter, working_bid_volume_filter, working_ask_volume_filter, volume_filter, security_key_filter),
settings_manager.subscribe_current().OnDispatcher().Subscribe(grid_settings_manager),
WorkLoop.Start("MarketView", _refresh)
@@ -218,6 +220,7 @@ namespace mbts.spark {
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> ask_direct_size_filter { get; } = new UIntMinMax<Row>(r => r.ask_direct_size, nameof(Row.ask_direct_size));
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> ask_implied_size_filter { get; } = new UIntMinMax<Row>(r => r.ask_implied_size, nameof(Row.ask_implied_size));
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> last_price_filter { get; } = new DoubleMinMax<Row>(r => r.last_price, nameof(Row.last_price));
public IDataGridColumnPersistentFilter<Row, string> last_price_from_spread_filter { get; } = new RegexFilterVM<Row>(r => r.last_price_from_spread.ToString(), nameof(Row.last_price_from_spread));
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> last_size_filter { get; } = new UIntMinMax<Row>(r => r.last_size, nameof(Row.last_size));
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> day_change_filter { get; } = new DoubleMinMax<Row>(r => r.day_change, nameof(Row.day_change));
public IDataGridColumnPersistentFilter<Row, DoubleMinMaxState> settlement_filter { get; } = new DoubleMinMax<Row>(r => r.settlement, nameof(Row.settlement));
@@ -250,6 +253,7 @@ namespace mbts.spark {
ask_direct_size = ask_direct_size_filter.get_state(),
ask_implied_size = ask_implied_size_filter.get_state(),
last_price = last_price_filter.get_state(),
last_price_from_spread = last_price_from_spread_filter.get_state(),
last_size = last_size_filter.get_state(),
day_change = day_change_filter.get_state(),
settlement = settlement_filter.get_state(),
@@ -12,6 +12,7 @@ namespace mbts.ui.spark {
Security,
Volume,
Last,
LastSpd,
LastSize,
Position,
RawDayPosition,
@@ -100,6 +100,7 @@ namespace bts.shell {
public static GridColumnSettings security => new GridColumnSettings(col_id(Columns.Security), DefaultColumnHeaders.Security, width: DefaultColumnWidths.Security);
public static GridColumnSettings volume => new GridColumnSettings(col_id(Columns.Volume), DefaultColumnHeaders.Volume, width: DefaultColumnWidths.Volume);
public static GridColumnSettings last => new GridColumnSettings(col_id(Columns.Last), DefaultColumnHeaders.Last, width: DefaultColumnWidths.Price);
public static GridColumnSettings last_from_spread => new GridColumnSettings(col_id(Columns.LastSpd), DefaultColumnHeaders.S, width: DefaultColumnWidths.Price, is_visible: false);
public static GridColumnSettings last_size => new GridColumnSettings(col_id(Columns.LastSize), DefaultColumnHeaders.Size, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
public static GridColumnSettings position => new GridColumnSettings(col_id(Columns.Position), DefaultColumnHeaders.Pos, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right);
public static GridColumnSettings raw_day_position => new GridColumnSettings(col_id(Columns.RawDayPosition), DefaultColumnHeaders.RawDayPos, width: DefaultColumnWidths.Size, horizontal_alignment: System.Windows.HorizontalAlignment.Right, is_visible: false);
@@ -138,6 +139,7 @@ namespace bts.shell {
yield return security;
yield return volume;
yield return last;
yield return last_from_spread;
yield return last_size;
yield return position;
yield return raw_day_position;
@@ -224,6 +226,8 @@ namespace bts.shell {
[ProtoMember(25)]
public string strip_name;
[ProtoMember(26)]
public string last_price_from_spread;
[ProtoMember(28)]
public string mic_code;
}
@@ -227,7 +227,7 @@ namespace mbts.ui.spark {
}
DataGridColumn _column_factory(LegSpreaderParamsTuple l) {
var col = new DataGridColumnInternal(l.leg.Security, ParameterCellTemplateConverter, ParameterCellEditingTemplateConverter) { Width = 75, };
var col = new DataGridColumnInternal(l.leg.Security, ParameterCellTemplateConverter, ParameterCellEditingTemplateConverter);
col.HeaderTemplate = (DataTemplate)FindResource(IsNew ? RemovableColumnHeaderTemplateKey : NonRemovableColumnHeaderTemplateKey);
DataGridEx.SetRightBorder(col, new DataGridExVerticalLine(false, true, Colors.DarkGray, 1));
return col;
@@ -1,7 +1,9 @@
using bts.api;
using bts;
using bts.api;
using bts.api.core;
using bts.api.synthetic;
using bts.collections;
using bts.spark;
using mbts.ui.shell;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
@@ -18,11 +20,36 @@ namespace mbts.spark {
readonly uint _user_id;
[ImportingConstructor]
public SpreaderModel(IBus bus, SyntheticSecurityService service, ErrorReporter error, [Import(LoginContainer.Exports.UserID)]uint user_id) {
public SpreaderModel(IBus bus, SyntheticSecurityService service, AdminModel admin_model, ErrorReporter error, UserTuple user) {
_bus = bus;
_service = service;
_error = error;
_user_id = user_id;
_user_id = user.id;
// synthetic tuples
var strategy_source = _bus.subscribe(SparkTags.SyntheticstrategiesTag)
.Select(map => MappedDictionary.create<uint, ExecutionStrategyImmutable, (uint security_id, ExecutionStrategyImmutable strategy)>(map, (k, v) => (k, v)))
.Table(tup => tup.security_id);
var synthetic_source = _bus.subscribe(SparkTags.SecuritiesTag)
.Select(map => new FilteredDictionary<uint, SecurityMD>(map, smd => smd.security.ContractCase == Security.ContractOneofCase.Synthetic))
.Table(smd => smd.security.Id);
var synthetic_user_join = synthetic_source.LeftJoin(
admin_model.all_user_tuples,
SecurityMD.key_fn,
UserTuple.key_fn,
smd => smd.security.Synthetic.UserId,
(smd, sid, ut, uid) => new SyntheticTuple(smd.security, ut.name, null),
(smd, sid, uid) => new SyntheticTuple(smd.security, null, null),
SyntheticTuple.key_fn);
synthetic_tuples = synthetic_user_join.LeftJoin(
strategy_source,
SyntheticTuple.key_fn,
tup => tup.security_id,
(synth_tup, id, strat_tup) => new SyntheticTuple(synth_tup.security, synth_tup.user_name, strat_tup.strategy),
(synth_tup, id) => synth_tup,
SyntheticTuple.key_fn);
}
public IObservable<IReadOnlyDictionary<uint, ExecutionStrategyImmutable>> strategy => _bus.subscribe(SparkTags.SyntheticstrategiesTag);
@@ -36,6 +63,8 @@ namespace mbts.spark {
.LeftJoin(strategies, (security, strategy) => (new ExecutionStrategyImmutable?(strategy), security), security => (new ExecutionStrategyImmutable?(), security))
);
public IObservable<TableUpdate<SyntheticTuple, uint>> synthetic_tuples { get; }
public IObservable<ExecutionStrategyImmutable> security_strategy(uint security_key) =>
strategy.TrySelect(s => {
bool success = s.TryGetValue(security_key, out ExecutionStrategyImmutable result);
@@ -7,8 +7,15 @@ namespace mbts.ui.spark {
/// Interaction logic for SyntheticManagementView.xaml
/// </summary>
partial class SyntheticManagementView : UserControl {
public enum Columns {
Name,
Description,
n_legs,
n_working_orders,
SecurityKey,
User
}
public enum Columns { Name, Description, n_legs, n_working_orders, SecurityKey}
public SyntheticManagementView() =>
InitializeComponent();
}
@@ -10,6 +10,7 @@ using mbts.ui.utility;
using mbts.utils;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reactive.Linq;
using System.Windows;
@@ -27,7 +28,7 @@ namespace mbts.spark {
readonly IWindowSettingsManager<GridSettings> _settings_manager;
public SyntheticManagementWindow(SyntheticManagementWindowFactory factory, IBus bus, OrdersModel orders_model, StartupData state, WindowSettingsManager<GridSettings> settings_manager)
public SyntheticManagementWindow(SyntheticManagementWindowFactory factory, IBus bus, OrdersModel orders_model, StartupData state, IWindowSettingsManager<GridSettings> settings_manager)
: base("Synthetic Management", bus, factory, SparkCommands.ShowSyntheticManagement.icon) {
_orders_model = orders_model;
_state = state;
@@ -66,8 +67,8 @@ namespace mbts.spark {
), SparkCommand.create("Clone", Icons.CloneSynthetic, SparkTags.ShowSyntheticCloneTag).complete(
current_row_connectable_builder.create(observe_row_strategy),
rs => rs.HasValue, select_row_strategy_tuple
), SparkCommands.ShowLadder(SparkCommands.KeyGestures.ShowLadder).complete(
vm_connectable_builder.create(vm => vm.current_security_md), md => md.HasValue, ConvertUtils.ValueOrDefault
), SparkCommands.ShowLadderAutoLookup(SparkCommands.KeyGestures.ShowLadder).complete(
vm_connectable_builder.create(vm => vm.current_security_observable.Select(s => s.HasValue ? ImmutableHashSet<uint>.Empty.Add(s.Value.Id) : null)), id => id != null
), SparkCommands.ShowOrders.complete(() => {
var ob_settings = bts.shell.orderbook.OrderBookStartupData.Default;
ob_settings.filters = new bts.shell.orderbook.FilterStates {
@@ -1,4 +1,5 @@
using bts.api;
using bts.settings;
using mbts.persist;
using mbts.spark;
using mbts.spark.filters;
@@ -7,6 +8,7 @@ using mbts.ui.settings;
using ProtoBuf;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Reactive.Linq;
using System.Threading.Tasks;
using static mbts.ui.controls.DIYGrid;
@@ -33,13 +35,8 @@ namespace bts.shell {
public async void show(SparkTags.Nothing nothing) =>
_bus.post(SparkTags.ShowWindow, await load(new StartupData()));
IShellWindow _create(StartupData state) {
var settings_manager = new WindowSettingsManager<GridSettings>(_settings_hub,
state.grid,
get: us => us.synthetic_management_grid,
set: (us, gs) => us.with(provided_synthetic_management_gridsettings: gs));
return new SyntheticManagementWindow(this, _bus, _orders_model, state, settings_manager);
}
IShellWindow _create(StartupData state) =>
new SyntheticManagementWindow(this, _bus, _orders_model, state, _settings_hub.create_synth_settings_manager(state.grid));
[ProtoContract]
public class StartupData {
@@ -67,6 +64,7 @@ namespace bts.shell {
public static GridColumnSettings n_legs => new GridColumnSettings(col_id(Columns.n_legs), DefaultColumnHeaders.N_Legs, width: DefaultColumnWidths.N_Legs);
public static GridColumnSettings n_working_orders => new GridColumnSettings(col_id(Columns.n_working_orders), DefaultColumnHeaders.N_Working_Orders, width: DefaultColumnWidths.N_Working_Orders);
public static GridColumnSettings security_key => new GridColumnSettings(col_id(Columns.SecurityKey), DefaultColumnHeaders.SecurityKey, is_visible: false, width: DefaultColumnWidths.SecurityKey);
public static GridColumnSettings user => new GridColumnSettings(col_id(Columns.User), DefaultColumnHeaders.User, is_visible: false, width: DefaultColumnWidths.User);
public static IEnumerable<SortingCriteria> default_sorting_criterion {
get {
@@ -81,6 +79,7 @@ namespace bts.shell {
yield return n_legs;
yield return n_working_orders;
yield return security_key;
yield return user;
}
}
@@ -101,6 +100,15 @@ namespace bts.shell {
public UIntMinMaxState n_working_orders;
[ProtoMember(6)]
public string security_key;
[ProtoMember(7)]
public uint[] user;
}
// migration rules
[Export(typeof(ISyntheticManagementMigrationRule))]
class AddMissingColumnsMigrationRule : ISyntheticManagementMigrationRule {
public bool apply(GridSettings settings, out GridSettings new_settings) =>
settings.add_missing_columns(StartupData.DefaultGridSettings.columns, out new_settings);
}
}
}
}
@@ -1,12 +1,15 @@
using bts.api;
using bts;
using bts.api;
using bts.collections;
using bts.spark;
using bts.utils;
using mbts.persist;
using mbts.spark.filters;
using mbts.ui;
using mbts.ui.settings;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive.Linq;
@@ -17,43 +20,45 @@ using static mbts.ui.controls.DIYGrid;
using static mbts.ui.spark.SyntheticManagementView;
namespace mbts.spark {
class SyntheticManagementDialogVM : SecurityMDGrid<SyntheticManagementDialogVM.Row, (ExecutionStrategyImmutable? strategy, SecurityMD md)> {
class SyntheticManagementDialogVM : SecurityGrid<SyntheticManagementDialogVM.Row, SyntheticTuple> {
readonly IBus _bus;
readonly OrdersModel _orders_model;
IWindowSettingsManager<GridSettings> _settings_manager;
readonly IWindowSettingsManager<GridSettings> _settings_manager;
public SyntheticManagementDialogVM(IBus bus, OrdersModel orders_model, IWindowSettingsManager<GridSettings> settings_manager) : this(bus, orders_model, settings_manager, null, null) { }
public SyntheticManagementDialogVM(IBus bus, OrdersModel orders_model, IWindowSettingsManager<GridSettings> settings_manager, IReadOnlyCollection<SortingCriteria> sorting, FilterStates filters)
: base(orders_model.spreader.strategy_tuple.Select(map => map.Values), sorting) {
: base(orders_model.spreader.synthetic_tuples.Select(t => t.state.Values), sorting) {
_bus = bus;
_orders_model = orders_model;
_settings_manager = settings_manager;
// init filters
user_filter = DiscreteValuesFilterVM.CreateTableUpdate<Row, UserTuple, uint>(r => r.user_tuple, UserTuple.key_fn, out var user_filter_items_observer, out var user_filter_items_view, nameof(Row.user_tuple));
user_filter_items_view.CustomSort = Comparer<string>.Default.wrap<string, UserTuple>(ut => ut.name).to_non_generic();
if (filters != null) {
create_time_filter.load_state(filters.create_time);
name_filter.load_state(filters.name);
description_filter.load_state(filters.description);
n_legs_filter.load_state(filters.n_legs);
n_working_orders_filter.load_state(filters.n_working_orders);
security_key_filter.load_state(filters.security_key);
security_key_filter.load_state(filters.security_key);
user_filter.load_state(filters.user);
}
_settings_manager = settings_manager;
// columns
add_col(Columns.Name, DefaultColumnHeaders.Name, r => r.name, nameof(Row.name), name_filter, DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.Security);
add_col(Columns.Description, DefaultColumnHeaders.Description, r => r.description, nameof(Row.description), description_filter, DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.Description);
add_col(Columns.n_legs, DefaultColumnHeaders.N_Legs, r => r.n_legs.ToString(), nameof(Row.n_legs), n_legs_filter, DataGridFilterKnownTemplates.IntMinMax, DefaultColumnWidths.N_Legs);
columns.Add(new HyperlinkElementColumn<Row, Columns>(
Columns.n_working_orders,
new Binding(nameof(Row.n_working_orders)),
Columns.n_working_orders,
new Binding(nameof(Row.n_working_orders)),
new Binding(nameof(Row.show_order_book)),
n_working_orders_filter,
DataGridFilterKnownTemplates.UIntMinMax) {
id = col_id(Columns.n_working_orders),
Header = DefaultColumnHeaders.N_Working_Orders,
Width = DefaultColumnWidths.N_Working_Orders
}
);
});
add_col(Columns.SecurityKey, DefaultColumnHeaders.SecurityKey, r => r.security_key.ToString(), nameof(Row.security_key), security_key_filter, DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.SecurityKey);
add_col(Columns.User, DefaultColumnHeaders.User, r => r.user_name, nameof(Row.user_name), user_filter, DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.User);
//
void add_col(Columns col_key, string header, Func<Row, string> get_text, string prop, IDataGridColumnFilter filter, string filter_template, double width) =>
columns.Add(new RenderTextColumn<Row, Columns>(col_key, get_text, filter, filter_template) {
@@ -63,42 +68,39 @@ namespace mbts.spark {
Width = width
});
//
grid_settings_manager = new SimpleGridSettingsManager<Row>(columns, new Dictionary<string, GridColumnSettingsFeatureFlags> { }, row_vms);
grid_settings_manager = new SimpleGridSettingsManager<Row>(columns, DictionaryHelper.empty<string, GridColumnSettingsFeatureFlags>(), row_vms);
// this will initialize the immutable properties that correspond to the col_settings_flags above (e.g. Bid/Ask font_color_override, etc.)
grid_settings_manager.load_from(settings_manager.current_settings());
_resources.AddRange(
DataGridFilterHelper.hook_filters(rows_view, create_time_filter, name_filter, description_filter, n_legs_filter, n_working_orders_filter, security_key_filter),
orders_model.admin_model.all_user_tuples.OnDispatcher().Subscribe(user_filter_items_observer),
DataGridFilterHelper.hook_all<SyntheticManagementDialogVM, Row>(this, rows_view),
settings_manager.subscribe_current().OnDispatcher().Subscribe(grid_settings_manager)
);
}
protected override Row row_factory((ExecutionStrategyImmutable? strategy, SecurityMD md) row_model) =>
new Row(_bus, row_model.md, row_model.strategy, _orders_model);
protected override void on_row_removed(Row row) => row.Dispose();
public ObservableCollection<ColumnBase> columns { get; } = new ObservableCollection<ColumnBase>();
public ObservableCollection<ColumnBase> columns { get; } = new ObservableCollection<ColumnBase>();
public SimpleGridSettingsManager<Row> grid_settings_manager { get; }
public GridSettings get_grid_save_state() {
if (_settings_manager.instance_settings == null)
return null;
else
return grid_settings_manager.create();
}
public StartupData create() =>
new StartupData(rows_view.get_sorting_criteria(columns), _get_filter_states(), get_grid_save_state());
#region Filters
public IDataGridColumnPersistentFilter<Row, TimeFilterTuple> create_time_filter { get; } = new TimeFilterVM<Row>(r => r.create_time, nameof(Row.create_time));
public IDataGridColumnPersistentFilter<Row, string> name_filter { get; } = new RegexFilterVM<Row>(r => r.name, nameof(Row.name));
public IDataGridColumnPersistentFilter<Row, string> description_filter { get; } = new RegexFilterVM<Row>(r => r.description, nameof(Row.description));
public IDataGridColumnPersistentFilter<Row, IntMinMaxState> n_legs_filter { get; } = new IntMinMax<Row>(r => r.n_legs, nameof(Row.n_legs));
public IDataGridColumnPersistentFilter<Row, UIntMinMaxState> n_working_orders_filter { get; } = new UIntMinMax<Row>(r => r.n_working_orders, nameof(Row.n_legs));
public IDataGridColumnPersistentFilter<Row, string> security_key_filter { get; } = new RegexFilterVM<Row>(r => r.security_key.ToString(), nameof(Row.security_key));
public IDataGridColumnPersistentFilter<Row, uint[]> user_filter { get; }
public GridSettings get_grid_save_state() =>
_settings_manager.instance_settings == null ? null : grid_settings_manager.create();
public StartupData create() =>
new StartupData(rows_view.get_sorting_criteria(columns), _get_filter_states(), get_grid_save_state());
protected override Row row_factory(SyntheticTuple row_model) =>
new Row(_bus, row_model, _orders_model);
protected override void on_row_removed(Row row) =>
row.Dispose();
FilterStates _get_filter_states() =>
new FilterStates {
@@ -107,19 +109,19 @@ namespace mbts.spark {
name = name_filter.get_state(),
n_legs = n_legs_filter.get_state(),
n_working_orders = n_working_orders_filter.get_state(),
security_key = security_key_filter.get_state()
security_key = security_key_filter.get_state(),
user = user_filter.get_state()
};
#endregion
public class Row : SecurityMDRow, IEquatable<Row>, IRowVM, IActionableRowVM {
public readonly ExecutionStrategyImmutable? strategy;
public class Row : SecurityRow, IEquatable<Row>, IRowVM, IActionableRowVM {
public readonly SyntheticTuple synthetic_tuple;
readonly IBus _bus;
readonly Property<uint> _n_working_orders;
public Row(IBus bus, SecurityMD security_md, ExecutionStrategyImmutable? strategy, OrdersModel orders_model) : base(security_md) {
public Row(IBus bus, SyntheticTuple synthetic_tuple, OrdersModel orders_model) : base(synthetic_tuple.security) {
_bus = bus;
this.strategy = strategy;
this.synthetic_tuple = synthetic_tuple;
_n_working_orders = backing(nameof(n_working_orders),
orders_model.on_security_orders(security_key)
.Select(t => (uint)(t.state
@@ -133,25 +135,23 @@ namespace mbts.spark {
show_order_book = new DelegateCommand(_show_order_book);
}
public event Action invalidated;
public DateTime create_time => DateTime.MinValue; //TODO
public string name { get; }
public string user_name => synthetic_tuple.user_name;
public UserTuple user_tuple => new UserTuple(synthetic_tuple.security.Synthetic.UserId, user_name);
public int n_legs { get; }
public string description { get; }
public ExecutionStrategyImmutable? strategy => synthetic_tuple.strategy;
public bool strategy_present => strategy.HasValue;
public uint n_working_orders => _n_working_orders.Value;
public ICommand show_ladder { get; }
public ICommand show_order_book { get; }
public ICommand default_command => show_ladder;
public ObservableCollection<RowAnimation> row_animations => new ObservableCollection<RowAnimation>();
public IReadOnlyList<IGridCellStore> cell_stores => new IGridCellStore[0];
public event Action invalidated;
public void raise_invalidated() => invalidated?.Invoke();
public void raise_invalidated() =>
invalidated?.Invoke();
public bool Equals(Row other) =>
other != null &&
@@ -163,10 +163,8 @@ namespace mbts.spark {
public override int GetHashCode() =>
security_key.GetHashCode();
void _show_ladder() =>
_bus.post(SparkTags.ShowLadderTag, md);
_bus.post(SparkTags.ShowLadderAutoLookupTag, ImmutableHashSet<uint>.Empty.Add(security.Id));
void _show_order_book() {
var ob_settings = bts.shell.orderbook.OrderBookStartupData.Default;
@@ -177,4 +175,4 @@ namespace mbts.spark {
}
}
}
}
}
@@ -27,7 +27,7 @@ namespace mbts.spark {
_error_reporter = error_reporter;
definitions =
service.subscribei_algo_definitions()
.Filter(r => r.Metadata.IsActive && r.Metadata.CreatorUserId == _admin_model.user.id)
.Filter(r => r.Metadata.IsActive && _admin_model.user.can_access_user_data(r.Metadata.CreatorUserId))
.SelectKeyValue(_definition_data, d => d.key)
.Table()
.Cache();
@@ -118,13 +118,14 @@ namespace mbts.spark {
add_col_expl(Columns.Side, new SideColumn<Row, Columns>(Columns.Side, r => r.side, side_filter) { id = col_id(Columns.Side) }, side_filter);
// all others (easily identified by the enum 'Columns.Foo')
add_col(Columns.FillTime, DefaultColumnHeaders.FillTime, r => r.fill_time.ToString("M/d h:mm:ss tt"), new TimeFilterVM<FillTuple>(r => r.fill.Timestamp.ToDateTimeOffset().LocalDateTime), DataGridFilterKnownTemplates.TimeFilter, DefaultColumnWidths.Time);
add_col(Columns.User, DefaultColumnHeaders.User, r => r.user, dv_filter_rx(_model.factory.subscribe_users().Select(d => d.Values), r => r.order?.user() ?? string.Empty), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.User);
add_col(Columns.Account, DefaultColumnHeaders.Account, r => r.account, dv_filter_rx(_model.factory.subscribe_accounts().Select(d => d.Values), r => r.account), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.Account);
add_col(Columns.User, DefaultColumnHeaders.User, r => r.user, dv_filter_rx(_model.factory.subscribe_users().Select(d => d.Values.Ordered()), r => r.order?.user() ?? string.Empty), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.User);
add_col(Columns.Account, DefaultColumnHeaders.Account, r => r.account, dv_filter_rx(_model.factory.subscribe_accounts().Select(d => d.Values.Ordered()), r => r.account), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.Account);
add_col(Columns.Exchange, DefaultColumnHeaders.Exchange, r => r.exchange.ToString(), dv_filter(EnumHelper.get_values<Venue>().ToArray(), r => r.security.exchange_or_default()), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.Exchange);
add_col(Columns.TimeInForce, DefaultColumnHeaders.TimeInForce, r => r.time_in_force.ToString(), dv_filter(EnumHelper.get_values<TimeInForce>().ToArray(), r => r.order?.time_in_force() ?? TimeInForce.Undefined), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.TimeInForce);
add_col(Columns.Size, DefaultColumnHeaders.Size, r => r.size.ToString(), new DoubleMinMax<FillTuple>(r => r.fill.LastShares), DataGridFilterKnownTemplates.UIntMinMax, DefaultColumnWidths.Size);
add_col(Columns.Price, DefaultColumnHeaders.Price, r => r.format_price(r.price), new DoubleMinMax<FillTuple>(r => r.fill.LastPrice), DataGridFilterKnownTemplates.DoubleMinMax, DefaultColumnWidths.Price);
add_col(Columns.FillKind, DefaultColumnHeaders.FillKind, r => r.fill_kind.ToString(), dv_filter(EnumHelper.get_values<FillKind>().ToArray(), r => r.fill.FillKind), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.FillKind);
add_col(Columns.FillStatus, DefaultColumnHeaders.FillStatus, r => r.fill_status.ToString(), dv_filter(EnumHelper.get_values<FillStatus>().ToArray(), r => r.fill.FillStatus), DataGridFilterKnownTemplates.DiscreteValues, DefaultColumnWidths.FillKind);
add_col(Columns.FillKey, DefaultColumnHeaders.FillKey, r => r.fill_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.FillKey), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.FillKey);
add_col(Columns.OrderKey, DefaultColumnHeaders.OrderKey, r => r.order_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.OrderKey.ToString()), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.OrderKey);
add_col(Columns.SecurityKey, DefaultColumnHeaders.SecurityKey, r => r.security_key.ToString(), new RegexFilterVM<FillTuple>(r => r.fill.SecurityKey.ToString()), DataGridFilterKnownTemplates.Regex, DefaultColumnWidths.SecurityKey);
@@ -146,6 +147,7 @@ namespace mbts.spark {
});
_dispose = new CompositeDisposable(
ObservableAutoWrapper.connect(col_tups, columns, ct => ct.col),
ObservableAutoWrapper.connect_item_hooks(col_tups, ct => ct.filter as IDisposable),
RXCollection.connect(rows, fills_buffer.Filter(filter_src, FillTuple.key_fn), comp_src, ft => new Row(ft, model), r => r.fill_tuple),
fills_source.OnDispatcher().Subscribe(t => {
last_unfiltered_fills = t;
@@ -227,6 +229,7 @@ namespace mbts.spark {
case Columns.Exchange: return wrap_default(ft => ft.security.exchange_or_default());
case Columns.FillKey: return wrap(ft => ft.fill.FillKey);
case Columns.FillKind: return wrap_default(ft => ft.fill.FillKind);
case Columns.FillStatus: return wrap_default(ft => ft.fill.FillStatus);
case Columns.FillTime: return wrap(ft => ft.fill.Timestamp.to_local_time());
case Columns.OrderKey: return wrap(ft => ft.fill.OrderKey);
case Columns.OrderType: return wrap_default(ft => ft.order?.order_type() ?? OrderType.None);
@@ -293,6 +296,7 @@ namespace mbts.spark {
public double price => _fill.LastPrice;
public double size => _fill.LastShares;
public FillKind fill_kind => _fill.FillKind;
public FillStatus fill_status => _fill.FillStatus;
public string fill_key => _fill.FillKey;
public string order_key => _order.Key.ToString();
@@ -21,6 +21,7 @@ namespace mbts.ui.spark {
Price,
Size,
FillKind,
FillStatus,
FillKey,
OrderKey,
SecurityKey
@@ -37,7 +37,8 @@ namespace bts.shell {
{ nameof(FillsVM.Row.side), Columns.Side },
{ nameof(FillsVM.Row.size), Columns.Size },
{ nameof(FillsVM.Row.time_in_force), Columns.TimeInForce },
{ nameof(FillsVM.Row.user), Columns.User }
{ nameof(FillsVM.Row.user), Columns.User },
{ nameof(FillsVM.Row.fill_status ), Columns.FillStatus },
};
public FillsWindowFactory(TradingShellModule module, IBus bus, UserSettingsHub settings_hub, OrdersModel orders_model)
@@ -74,6 +74,10 @@ namespace bts.shell.fills {
[ProtoMember(15)]
[DIYGridColumnID(nameof(Columns.Symbol))]
public string[] symbol { get; set; }
[ProtoMember(17)]
[DIYGridColumnID(nameof(Columns.FillStatus))]
public Fill.Types.FillStatus[] fill_status { get; set; }
}
static class FillsFilterStatesExtensions {
@@ -96,6 +100,7 @@ namespace bts.shell.fills {
pb.add_discrete_values(fs.side, ft => ft.fill.Side);
pb.add_discrete_values(fs.fill_kind, ft => ft.fill.FillKind);
pb.add_discrete_values(fs.symbol, ft => ft.security?.Symbol ?? string.Empty);
pb.add_discrete_values(fs.fill_status, ft => ft.fill.FillStatus);
// numeric
pb.add_numeric(fs.size, ft => ft.fill.LastShares);
pb.add_numeric(fs.price, ft => ft.fill.LastPrice);
@@ -1,4 +1,5 @@
using bts.api;
using bts.collections;
using bts.md;
using mbts;
using mbts.config;
@@ -50,6 +51,7 @@ namespace bts.shell {
_mbo = mbo;
_dispose = Disposable.Create(
bus.subscribe(SparkTags.SecuritiesTag).Subscribe(s => _securities = s),
bus.subscribe(SparkTags.ShowLadderAutoLookupTag).Subscribe(_show_windows),
bus.subscribe(SparkTags.ShowLadderTag).OnDispatcher().Subscribe(s => show_windows(new[] { s })),
bus.subscribe(SparkTags.ShowLaddersTag).OnDispatcher().Subscribe(show_windows)
);
@@ -273,7 +275,21 @@ namespace bts.shell {
});
}
void show_windows(IReadOnlyCollection<SecurityMD> securities) {
async void _show_windows(IImmutableSet<uint> securities) {
if (securities == null)
return;
var start_time = DateTime.Now;
do {
var found = securities.KeyJoin(_securities).ToList();
securities = securities.RemoveRange(found.Select(SecurityMD.key_fn));
show_windows(found);
if (securities.Count == 0)
break;
await Task.Delay(500);
} while ((DateTime.Now - start_time) < _ladder_conf.security_timeout);
}
void show_windows(IEnumerable<SecurityMD> securities) {
int n_allowed = (int)_ladder_conf.max_open_ladders - _wm.list_windows().Where(w => w.window_type == _window_type).Count();
int n_opened = 0;
foreach (var s in securities) {
@@ -70,7 +70,7 @@ namespace bts.shell.manual_fills {
mfd => new ManualFillRow(mfd),
mfr => mfr.data),
_bus.subscribe(SparkTags.SecuritiesTag).OnDispatcher().Subscribe(m => {
security_map = m;
security_map = new FilteredDictionary<uint, SecurityMD>(m, smd => smd.security.ContractCase == Security.ContractOneofCase.Future);
RaisePropertyChanged(nameof(security_map));
}),
ObservableAutoWrapper.connect_item_hooks(_persisted_rows, r => Disposable.Create(dirty_mon.join(r), selection_mon.join(r))),
@@ -121,7 +121,7 @@ namespace mbts.spark {
r => r.user,
DefaultColumnWidths.User,
DiscreteValuesFilterVM.Create<OrderSecurityRootPair, string>(
model.factory.subscribe_users().Select(d => d.Values),
model.factory.subscribe_users().Select(d => d.Values.Ordered()),
ort => ort.order.order.user(),
nameof(OrderBookRowVM.user)),
DataGridFilterKnownTemplates.DiscreteValues,
@@ -133,7 +133,7 @@ namespace mbts.spark {
r => r.account,
DefaultColumnWidths.Account,
DiscreteValuesFilterVM.Create<OrderSecurityRootPair, string, string[]>(
model.factory.subscribe_accounts().Select(d => d.Values),
model.factory.subscribe_accounts().Select(d => d.Values.Ordered()),
ort => ort.order.order.account(),
vals => vals.ToArray(),
vals => Observable.Return(vals),
@@ -239,7 +239,7 @@ namespace mbts.spark {
grid_settings_manager,
order_mod_vm.algo_vm.connect_data(Observable.Return(model)),
order_mod_vm.algo_vm.connect_data(_selected_params_mon.subscribe_spreader_security()),
order_mod_vm.algo_vm,
order_mod_vm,
attach_vm,
_show_fills.observe_current(true)
.Subscribe(is_visible => {
@@ -735,17 +735,13 @@ namespace mbts.spark {
_size_permissions = AlgoParamPermissions.ReadOnly | AlgoParamPermissions.Write;
SecurityMD? _security_md;
public OrderParamsVM(OrderBookVM owner, AlgoFormats init_format, AlgoEditingPermissions init_permissions)
: this(owner,
AlgoDefinitionVM.create(
owner._model,
AlgoData.create_unpersisted(OrderDataHelper.Defaults.CustomOrderDefinitionImmutable(CustomOrderDefinition.CustomOneofCase.Iceberg), CustomOrderDefinition.CustomOneofCase.Iceberg.display_name()),
init_format: init_format,
editing_permissions: init_permissions)) { }
OrderParamsVM(OrderBookVM owner, AlgoDefinitionVM algo_vm) {
public OrderParamsVM(OrderBookVM owner, AlgoFormats init_format, AlgoEditingPermissions init_permissions) {
_owner = owner;
this.algo_vm = algo_vm;
algo_vm = AlgoDefinitionVM.create(
owner._model,
AlgoData.create_unpersisted(OrderDataHelper.Defaults.CustomOrderDefinitionImmutable(CustomOrderDefinition.CustomOneofCase.Iceberg), CustomOrderDefinition.CustomOneofCase.Iceberg.display_name()),
init_format: init_format,
editing_permissions: init_permissions);
_accounts = backing(
nameof(selected_account),
_model.factory.subscribe_account_tuples(),
@@ -784,7 +780,8 @@ namespace mbts.spark {
appended_param_rows.insert_front(new AlgoParamRowVM(root, _price_param, null, AlgoParamTemplateKeys.Price));
}
}),
ObservableAutoWrapper.connect_item_hooks(param_rows, dirty_params_mon.join));
ObservableAutoWrapper.connect_item_hooks(param_rows, dirty_params_mon.join),
algo_vm);
// payup methods
void payup_bid(int ticks) => payup(bbo.bid, -ticks);
void payup_ask(int ticks) => payup(bbo.ask, ticks);
@@ -501,6 +501,12 @@ namespace bts.shell.pnl {
account_name == other.account_name &&
sod == other.sod &&
day == other.day &&
bid_price.Equals(other.bid_price) &&
ask_price.Equals(other.ask_price) &&
last_price.Equals(other.last_price) &&
mid_price.Equals(other.mid_price) &&
settlement_price.Equals(other.settlement_price) &&
calc_type.Equals(other.calc_type) &&
raw_day == other.raw_day &&
working.summary == other.working.summary;
@@ -97,22 +97,22 @@ namespace bts.shell.pnl {
if (security.HasValue && security.Value.ContractCase != Security.ContractOneofCase.Future) {
day_long = day_short = sod_long = sod_short = 0;
} else {
day_long = (decimal)DoubleUtil.nan_to_zero(data.day.long_pos);
day_short = (decimal)DoubleUtil.nan_to_zero(data.day.short_pos);
sod_long = (decimal)DoubleUtil.nan_to_zero(data.sod.long_pos);
sod_short = (decimal)DoubleUtil.nan_to_zero(data.sod.short_pos);
day_long = DoubleUtil.round_to_decimal(data.day.long_pos);
day_short = DoubleUtil.round_to_decimal(data.day.short_pos);
sod_long = DoubleUtil.round_to_decimal(data.sod.long_pos);
sod_short = DoubleUtil.round_to_decimal(data.sod.short_pos);
}
var nd = new PNLNormalizedData(
(decimal)DoubleUtil.nan_to_zero(day_pnl.value),
DoubleUtil.round_to_decimal(day_pnl.value),
day_long,
day_short,
(decimal)DoubleUtil.nan_to_zero(data.raw_day.long_pos),
(decimal)DoubleUtil.nan_to_zero(data.raw_day.short_pos),
(decimal)DoubleUtil.nan_to_zero(sod_pnl.value),
DoubleUtil.round_to_decimal(data.raw_day.long_pos),
DoubleUtil.round_to_decimal(data.raw_day.short_pos),
DoubleUtil.round_to_decimal(sod_pnl.value),
sod_long,
sod_short,
(decimal)DoubleUtil.nan_to_zero(data.working_long_pos),
(decimal)DoubleUtil.nan_to_zero(data.working_short_pos));
DoubleUtil.round_to_decimal(data.working_long_pos),
DoubleUtil.round_to_decimal(data.working_short_pos));
if (_normalized_data != nd) {
_normalized_data = nd;
updated?.Invoke(nd);
@@ -103,7 +103,7 @@ namespace bts.shell.pnl {
load_from(settings);
_dispose = Disposable.Create(
pnl_source.Operate(
_calculation_type.observe_current(),
_calculation_type.observe_current(true),
(data, calc) => data.with(calc_type: calc)
).FilterWithRaw(filter_src, PNLRowData.key_fn, null)
.OnDispatcher()
@@ -67,7 +67,6 @@ namespace mbts.spark.utilities {
public IObservable<IReadOnlyDictionary<uint, string>> subscribe_accounts() => _admin_model.on_accounts;
public IObservable<IReadOnlyDictionary<uint, string>> subscribe_users() => _admin_model.on_users;
public IObservable<IReadOnlyList<UserTuple>> subscribe_user_tuples() => _admin_model.on_user_tuples;
public IObservable<IReadOnlyList<AccountTuple>> subscribe_account_tuples() => _admin_model.on_account_tuples;
#region Defaults
+22 -15
View File
@@ -59,23 +59,30 @@ namespace mbts.spark {
this.md_auxiliary_model = md_auxiliary_model;
var scheduler = ThreadPoolScheduler.Instance;
var interval = TimeSpan.FromMilliseconds(100);
on_orders =
_service
.subscribei_orders()
.Naggle(interval, scheduler)
.PermissionFilter(admin_model.on_admin_data)
.join(sstore, order => order.security_key())
on_orders = admin_model
.permission_filter(
_service.subscribei_orders()
.Naggle(interval, scheduler),
o => o.account_id()
).join(sstore, order => order.security_key())
.Table()
.Cache();
on_positions = _position_service.subscribei_position_data().Naggle(interval, scheduler).PermissionFilter(admin_model.on_admin_data).join(sstore, pos => pos.SecurityId).Table().Cache();
on_pnl = _position_service.subscribei_pnl_data()
.Naggle(interval, scheduler)
on_positions = admin_model
.permission_filter(
_position_service.subscribei_position_data().Naggle(interval, scheduler),
p => p.AccountId)
.join(sstore, pos => pos.SecurityId)
.Table()
.Cache();
on_pnl = admin_model
.permission_filter(
_position_service.subscribei_pnl_data().Naggle(interval, scheduler),
p => p.Pos.AccountId)
.join(sstore, p => p.Pos.SecurityId)
.TableCheckedAutoCorrect(EqualityComparer<(SecurityImmutable? sec, PNLUnitImmutable data)>.Default)
.Where(t => t.has_changes())
.Cache();
on_account_pnl = _position_service.subscribei_pnl_account_data().Naggle(interval, scheduler).Table().Cache();
var working_orders = on_orders.Filter(tup => tup.order.is_active());
this.working_orders =
on_orders.Scan(
@@ -174,10 +181,11 @@ namespace mbts.spark {
.Where(t => t.has_changes())
.Cache();
// fill tuples
var on_fills =
_service.subscribei_fills()
.Naggle(interval, scheduler)
.PermissionFilter(admin_model.on_admin_data)
var on_fills = admin_model
.permission_filter(
_service.subscribei_fills()
.Naggle(interval, scheduler),
f => f.Account)
.join(sstore, f => f.SecurityKey)
.Table().Cache();
var fill_order_tuples_join = on_fills.LeftJoin(
@@ -265,7 +273,6 @@ namespace mbts.spark {
public IObservable<IReadOnlyDictionary<uint, OrderSecurity>> working_orders { get; }
public IObservable<TableUpdate<(SecurityImmutable?, PNLUnitImmutable), int>> on_pnl { get; }
public IObservable<TableUpdate<PNLRowData, PNLKey>> security_account_pnl { get; }
public IObservable<TableUpdate<AccountPNLImmutable, uint>> on_account_pnl { get; }
public IObservable<TableUpdate<(SecurityImmutable?, PositionUnitImmutable), int>> on_positions { get; }
public IObservable<TableUpdate<(AlgoData algo, AlgoDefinitionMetadata? meta), AlgoKey>> studio_algos_with_meta { get; }
public IObservable<TableUpdate<(SecurityImmutable?, ManualFillImmutable), int>> on_manual_fills_securities { get; }
@@ -8,6 +8,7 @@ using mbts.spark;
using mbts.ui;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Windows.Input;
namespace bts.spark {
@@ -41,6 +42,9 @@ namespace bts.spark {
SparkCommand.create("P&L (2.0)", Icons.Accounting, SparkTags.ShowPNLTag);
// Ladder
public static PartialCommand<IImmutableSet<uint>> ShowLadderAutoLookup(KeyGesture key_gesture = null) =>
SparkCommand.create("Ladder", Icons.Ladder, SparkTags.ShowLadderAutoLookupTag, key_gesture);
public static PartialCommand<SecurityMD> ShowLadder(KeyGesture key_gesture = null) =>
SparkCommand.create("Ladder", Icons.Ladder, SparkTags.ShowLadderTag, key_gesture);
+3
View File
@@ -7,6 +7,7 @@ using bts.spark;
using mbts.ui;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
namespace mbts.spark {
@@ -55,6 +56,8 @@ namespace mbts.spark {
// The owners of the various SparkWindows may remove dependencies on the former at their leasure.
// For now, both tags go through the same logic in the LadderWindowFactory anyways.
public static ITag<SecurityMD> ShowLadderTag { get; } = new SparkTag<SecurityMD>("Show Ladder");
// TODO: get rid of the SecurityMD ShowLadderTag. This has created burdensome dependency issues.
public static ITag<IImmutableSet<uint>> ShowLadderAutoLookupTag { get; } = new SparkTag<IImmutableSet<uint>>("Show Ladder Auto Lookup");
public static ITag<IReadOnlyList<SecurityMD>> ShowLaddersTag { get; } = new SparkTag<IReadOnlyList<SecurityMD>>(nameof(ShowLaddersTag));
public static ITag<IObservable<SecurityMD>> ShowLinkedLadder { get; } = new SparkTag<IObservable<SecurityMD>>("Linked Ladder");
public static ITag<SecurityCriteria> ShowMarketViewTag { get; } = new SparkTag<SecurityCriteria>("Show MarketView");
@@ -11,6 +11,7 @@ using bts.api.persistence;
using System.Text.RegularExpressions;
using System.Reactive.Linq;
using bts.spark;
using bts;
namespace mbts.persist
{
@@ -146,16 +147,18 @@ namespace mbts.persist
}
[Export(typeof(IUserPersist))]
public class UserUISettings : UISettingsBase
{
public class UserUISettings : UISettingsBase {
string _user;
[ImportingConstructor]
public UserUISettings([Import("userid")]uint user, [Import("settings")]PersistenceService persist, ErrorReporter err)
public UserUISettings(uint user_id, [Import("settings")]PersistenceService persist, ErrorReporter err)
: base(persist,err) {
_user = $"User {user}";
_user = $"User {user_id}";
}
[ImportingConstructor]
UserUISettings(UserTuple user, [Import("settings")]PersistenceService persist, ErrorReporter err)
: this(user.id, persist, err) { }
protected override string user() { return _user; }
}
}
@@ -17,6 +17,7 @@ namespace bts.settings {
interface IMarketViewGridSettingsMigrationRule : ISettingsMigrationRule<GridSettings> { }
interface IPAndLGridSettingsMigrationRule : ISettingsMigrationRule<GridSettings> { }
interface IPNLSettingsMigrationRule : ISettingsMigrationRule<PNLSettings> { }
interface ISyntheticManagementMigrationRule : ISettingsMigrationRule<GridSettings> { }
static class SettingsMigrationHelper {
public static bool apply<T>(T settings, IEnumerable<ISettingsMigrationRule<T>> migration_rules, out T new_settings) {
@@ -25,7 +25,8 @@ namespace mbts.persist {
static readonly IImmutableProperty<UserSettings, GridSettings>
_fills_propi = ImmutableProperty.create<UserSettings, GridSettings>(us => us.fills_grid, (us, gs) => us.with(provided_fills_gridsettings: gs)),
_mview_propi = ImmutableProperty.create<UserSettings, GridSettings>(us => us.market_view_grid, (us, gs) => us.with(provided_market_view_gridsettings: gs)),
_pandl_propi = ImmutableProperty.create<UserSettings, GridSettings>(us => us.pnl_grid, (us, gs) => us.with(provided_pnl_gridsettings: gs));
_pandl_propi = ImmutableProperty.create<UserSettings, GridSettings>(us => us.pnl_grid, (us, gs) => us.with(provided_pnl_gridsettings: gs)),
_synth_propi = ImmutableProperty.create<UserSettings, GridSettings>(us => us.synthetic_management_grid, (us, gs) => us.with(provided_synthetic_management_gridsettings: gs));
static readonly IImmutableProperty<UserSettings, PNLSettings>
_pnl_propi = ImmutableProperty.create<UserSettings, PNLSettings>(us => us.pnl, (us, pnl) => us.with(pnl: pnl));
@@ -36,6 +37,7 @@ namespace mbts.persist {
readonly IEnumerable<IMarketViewGridSettingsMigrationRule> _mview_migration_rules;
readonly IEnumerable<IPAndLGridSettingsMigrationRule> _pandl_migration_rules;
readonly IEnumerable<IPNLSettingsMigrationRule> _pnl_migration_rules;
readonly IEnumerable<ISyntheticManagementMigrationRule> _synth_migration_rules;
readonly IUserPersist _persist;
UserSettings _default_settings;
@@ -46,13 +48,15 @@ namespace mbts.persist {
[ImportMany]IEnumerable<IFillsGridSettingsMigrationRule> fills_migration_rules,
[ImportMany]IEnumerable<IMarketViewGridSettingsMigrationRule> mview_migration_rules,
[ImportMany]IEnumerable<IPAndLGridSettingsMigrationRule> pandl_migration_rules,
[ImportMany]IEnumerable<IPNLSettingsMigrationRule> pnl_migration_rules) {
[ImportMany]IEnumerable<IPNLSettingsMigrationRule> pnl_migration_rules,
[ImportMany]IEnumerable<ISyntheticManagementMigrationRule> synth_migration_rules) {
//
_persist = persist;
_fills_migration_rules = fills_migration_rules ?? Enumerable.Empty<IFillsGridSettingsMigrationRule>();
_mview_migration_rules = mview_migration_rules ?? Enumerable.Empty<IMarketViewGridSettingsMigrationRule>();
_pandl_migration_rules = pandl_migration_rules ?? Enumerable.Empty<IPAndLGridSettingsMigrationRule>();
_pnl_migration_rules = pnl_migration_rules ?? Enumerable.Empty<IPNLSettingsMigrationRule>();
_synth_migration_rules = synth_migration_rules ?? Enumerable.Empty<ISyntheticManagementMigrationRule>();
init();
async void init() {
UserSettings s;
@@ -62,7 +66,9 @@ namespace mbts.persist {
var wrapped_rules = new[] {
_fills_migration_rules.merge().wrap(_fills_propi),
_mview_migration_rules.merge().wrap(_mview_propi),
_pandl_migration_rules.merge().wrap(_pandl_propi)
_pandl_migration_rules.merge().wrap(_pandl_propi),
_pnl_migration_rules.merge().wrap(_pnl_propi),
_synth_migration_rules.merge().wrap(_synth_propi)
};
SettingsMigrationHelper.apply_quiet(ref s, wrapped_rules);
// TODO: move ladder sanitization logic into ISettingsMigrationRule
@@ -136,6 +142,12 @@ namespace mbts.persist {
_pnl_migration_rules,
_pnl_propi);
public IWindowSettingsManager<GridSettings> create_synth_settings_manager(GridSettings instance_settings) =>
_create_settings_manager(
instance_settings,
_synth_migration_rules,
_synth_propi);
public async Task save_default(UserSettings value) {
// notify observers before persisting so the changes are reflected immediately in the ui
lock (_default_settings_lock) {
@@ -15,12 +15,8 @@ namespace bts.utils {
}
static class ObjectSnapshot {
public static IEnumerable<Func<TSource, TValue>> property_delegates_of_type<TSource, TValue>() where TSource : class where TValue : class {
var tval = typeof(TValue);
return typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => tval.IsAssignableFrom(p.PropertyType))
.Select(_prop_getter<TSource, TValue>);
}
public static IReadOnlyList<Func<TSource, TValue>> property_delegates_of_type<TSource, TValue>() =>
PropertyGetterStore<TSource, TValue>.value;
public static IObservable<TableUpdate<(string name, object current, object original), string>> property_table<T>(T instance, params string[] prop_names) where T : INotifyPropertyChanged =>
_property_table(instance, Array.ConvertAll(prop_names, PropertyInfoStore<T>.type.GetProperty));
@@ -162,6 +158,18 @@ namespace bts.utils {
}
}
static class PropertyGetterStore<TSource, TValue> {
public static readonly IReadOnlyList<Func<TSource, TValue>> value;
static PropertyGetterStore() {
var tval = typeof(TValue);
value = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => tval.IsAssignableFrom(p.PropertyType))
.Select(_prop_getter<TSource, TValue>)
.ToReadOnlyList();
}
}
class PropNode {
public readonly PropertyInfo prop;
@@ -0,0 +1,46 @@
using bts.api;
using bts.spark;
using bts.utils;
using System;
namespace bts {
struct SyntheticTuple : IEquatable<SyntheticTuple>, IComparable<SyntheticTuple>, IComparable {
public static readonly Func<SyntheticTuple, uint> key_fn = a => a.security.Id;
public static readonly Func<SyntheticTuple?, uint> nullable_key_fn = a => a.HasValue ? a.Value.security.Id : 0u;
public readonly SecurityImmutable security;
public readonly string user_name;
public readonly ExecutionStrategyImmutable? strategy;
public readonly int? num_working_orders;
public SyntheticTuple(SecurityImmutable security, string user_name, ExecutionStrategyImmutable? strategy, int? num_working_orders = null) {
this.security = security;
this.user_name = user_name;
this.strategy = strategy;
this.num_working_orders = num_working_orders;
}
public int CompareTo(SyntheticTuple other) =>
SecurityHelper.Comparer.Compare(security, other.security);
int IComparable.CompareTo(object obj) =>
obj is SyntheticTuple other ? CompareTo(other) : 1;
public bool Equals(SyntheticTuple other) =>
security == other.security &&
user_name == other.user_name &&
EqualityComparer.nullable_equals(strategy, other.strategy);
public override bool Equals(object obj) =>
EqualityComparer.equals_obj(this, obj);
public override int GetHashCode() =>
security.Id.GetHashCode();
public override string ToString() =>
user_name == null ? security.ToString() : $"{user_name}:{security}";
public static bool operator ==(SyntheticTuple a, SyntheticTuple b) => a.Equals(b);
public static bool operator !=(SyntheticTuple a, SyntheticTuple b) => !a.Equals(b);
}
}
@@ -114,6 +114,7 @@ namespace mbts.ui.controls {
Aggressor = "Aggressor",
Volume = "Volume",
Last = "Last",
S = "S",
Pos = "Pos",
Working = "Working",
Bid = "Bid",
@@ -124,6 +125,7 @@ namespace mbts.ui.controls {
SessionLow = "Low",
SessionHigh = "High",
FillKind = "Fill Kind",
FillStatus = "Fill Status",
Name = "Name",
Description = "Description",
N_Legs = "# Legs",
@@ -1,10 +1,9 @@
using System;
using System.Linq;
namespace mbts.ui.controls
{
internal class DoubleUtil
{
namespace mbts.ui.controls {
static class DoubleUtil {
public const int API_DECIMAL_PRECISION = 9;
/* smallest such that 1.0+DBL_EPSILON != 1.0 */
private const double EPSILON = 2.2204460492503131e-016;
private const double BIG_EPSILON = EPSILON * 10;
@@ -36,6 +35,9 @@ namespace mbts.ui.controls
(double.IsNaN(right) ? double.NaN : -right) :
(double.IsNaN(right) ? left : left - right);
public static decimal round_to_decimal(double value, int decimals = API_DECIMAL_PRECISION) =>
double.IsNaN(value) ? 0 : (decimal)Math.Round(value, decimals, MidpointRounding.AwayFromZero);
internal static bool AreClose(double v1, double v2) {
if (v1 == v2) return true;
double delta = Math.Abs(v1 - v2);
@@ -1,11 +1,22 @@
using System;
using bts.utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace mbts.spark.filters {
static class DataGridFilterHelper {
public static IDisposable hook_filters<TRow>(ICollectionView rows, params IDataGridColumnFilter<TRow>[] filters) {
public static IDisposable hook_all<TSource, TRow>(TSource source, ICollectionView rows) =>
hook_filters(rows,
ObjectSnapshot.property_delegates_of_type<TSource, IDataGridColumnFilter<TRow>>()
.Select(f => f(source))
.ExceptNull()
.ToList());
public static IDisposable hook_filters<TRow>(ICollectionView rows, params IDataGridColumnFilter<TRow>[] filters) =>
hook_filters(rows, filters.AsEnumerable());
public static IDisposable hook_filters<TRow>(ICollectionView rows, IEnumerable<IDataGridColumnFilter<TRow>> filters) {
var icvls = (ICollectionViewLiveShaping)rows;
icvls.IsLiveFiltering = true;
return _hook_filters(set_filter, filters);
@@ -22,7 +33,7 @@ namespace mbts.spark.filters {
}
}
static IDisposable _hook_filters<TRow>(Action set_filter, params IDataGridColumnFilter<TRow>[] filters) {
static IDisposable _hook_filters<TRow>(Action set_filter, IEnumerable<IDataGridColumnFilter<TRow>> filters) {
foreach (var f in filters)
f.filter_changed += set_filter;
set_filter();
@@ -34,7 +45,7 @@ namespace mbts.spark.filters {
});
}
static List<IDataGridColumnFilter<TRow>> _get_active_filters<TRow>(IDataGridColumnFilter<TRow>[] filters) =>
static List<IDataGridColumnFilter<TRow>> _get_active_filters<TRow>(IEnumerable<IDataGridColumnFilter<TRow>> filters) =>
filters.Where(f => f.active.HasValue && f.active.Value).ToList();
}
@@ -68,10 +68,11 @@ namespace mbts.spark.filters {
Func<TRow, TValue> factory,
Func<TValue, TKey> key,
out IObserver<TableUpdate<TValue, TKey>> items_observer,
out ListCollectionView<TValue> items_view)
out ListCollectionView<TValue> items_view,
string prop_name = null)
where TKey : struct, IEquatable<TKey> =>
//
CreateTableUpdate(factory, key, keys => keys, keys => keys.ToArray(), out items_observer, out items_view);
CreateTableUpdate(factory, key, keys => keys, keys => keys.ToArray(), out items_observer, out items_view, prop_name);
public static IDataGridColumnPersistentFilter<TRow, TState> CreateTableUpdate<TRow, TValue, TKey, TState>(
Func<TRow, TValue> factory,
@@ -79,10 +80,11 @@ namespace mbts.spark.filters {
Func<TState, IEnumerable<TKey>> load_state,
Func<IEnumerable<TKey>, TState> get_state,
out IObserver<TableUpdate<TValue, TKey>> items_observer,
out ListCollectionView<TValue> items_view)
out ListCollectionView<TValue> items_view,
string prop_name = null)
where TKey : struct, IEquatable<TKey> {
//
var filter = new TableUpdateItemsFilter<TRow, TValue, TKey, TState>(factory, key, load_state, get_state);
var filter = new TableUpdateItemsFilter<TRow, TValue, TKey, TState>(factory, key, load_state, get_state, prop_name);
items_observer = filter;
items_view = filter.items_view;
return filter;
@@ -291,8 +293,8 @@ namespace mbts.spark.filters {
readonly HashSet<TKey> _selected_keys = new HashSet<TKey>(), _desired_keys = new HashSet<TKey>();
ListCollectionView<TValue> _items_view;
public TableUpdateItemsFilter(Func<TRow, TValue> factory, Func<TValue, TKey> key, Func<TState, IEnumerable<TKey>> load_state, Func<IEnumerable<TKey>, TState> get_state)
: base(factory, null) {
public TableUpdateItemsFilter(Func<TRow, TValue> factory, Func<TValue, TKey> key, Func<TState, IEnumerable<TKey>> load_state, Func<IEnumerable<TKey>, TState> get_state, string prop_name)
: base(factory, prop_name) {
_factory = factory;
_key = key;
_load_state = load_state;
@@ -24,6 +24,7 @@ namespace mbts.ui {
public TimeTextTuple end => _end;
public bool is_active =>
_mode == TimeFilterMode.Today ||
_mode == TimeFilterMode.CMEOpen ||
(_mode == TimeFilterMode.Period && (_begin.result.HasValue || _end.result.HasValue));
@@ -1,10 +1,4 @@
using bts.support;
using Google.Protobuf;
using mbts;
using mbts.ui;
using mbts.ui.shell;
using mbts.ui.utility;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -18,6 +12,13 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using bts.support;
using Google.Protobuf;
using mbts;
using mbts.ui;
using mbts.ui.controls;
using mbts.ui.shell;
using mbts.ui.utility;
namespace bts.view.controls {
partial class SupportRequestWindow : Window {
@@ -50,28 +51,40 @@ namespace bts.view.controls {
_base = report_base;
send_command = new DelegateCommand(send_report, _ => !string.IsNullOrWhiteSpace(_text.Value));
_text = backing(nameof(user_text), "");
_text.Changed += (_,__) => send_command.TryRaiseCanExecuteChanged();
_text.Changed += (_, __) => send_command.TryRaiseCanExecuteChanged();
_contact = backing(nameof(user_contact), "");
_contact.Changed += (_,__) => send_command.TryRaiseCanExecuteChanged();
_contact.Changed += (_, __) => send_command.TryRaiseCanExecuteChanged();
}
async void send_report(object _) {
ByteString screenshot = null;
if (include_screenshot) {
var stream = ScreenCapture.capture_encoded("jpeg");
screenshot = await ByteString.FromStreamAsync(stream);
}
var reply = await _service.send_report_async(_base.with(
user_description: _text.Value,
contact: user_contact,
log: include_logs ? LogUtil.read_logs() : "",
image: screenshot
));
if (reply.success) {
BTSMessageBox.Show("Your message has been received.", "Thank You", BTSMessageBoxButtons.OK, MessageBoxImage.Information, is_modal: false, top_most:true);
}
else {
BTSMessageBox.Show($"There was an error submitting your message. '{reply.error_message}'", "Error", BTSMessageBoxButtons.OK, MessageBoxImage.Error, is_modal: false, top_most: true);
using (var d = new BusyDialog { Text = "Sending your error report...", Topmost = true }) {
d.Show();
ByteString screenshot = null;
if (include_screenshot) {
var stream = ScreenCapture.capture_encoded("jpeg");
screenshot = await ByteString.FromStreamAsync(stream);
}
var request = await Task.Run(() => {
var result = _base.with(
user_description: _text.Value,
contact: user_contact,
image: screenshot);
if (include_logs) {
result = spark.ErrorReporter.append_logs(result);
}
return result;
});
var reply = await _service.send_report_async(request);
if (reply.success) {
Log.Ui.info("Support request message has been received.");
BTSMessageBox.Show("Your message has been received.", "Thank You", BTSMessageBoxButtons.OK, MessageBoxImage.Information, is_modal: false, top_most: true);
}
else {
var errmsg = $"There was an error submitting your message. '{reply.error_message}'";
Log.Ui.error(errmsg);
BTSMessageBox.Show(errmsg, "Error", BTSMessageBoxButtons.OK, MessageBoxImage.Error, is_modal: false, top_most: true);
}
}
}
@@ -457,15 +457,15 @@
Name="PART_TextBox"
u:TextBoxBehavior.EnableArrowKeyTraverse="True"
BorderThickness="0">
<TextBox.Style>
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding RelativeSource={RelativeSource Self}}"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</Style>
</TextBox.Style>
</TextBox>
</c:TickUpDown>
</ControlTemplate>
@@ -93,7 +93,6 @@
u:TextBoxBehavior.EnableArrowKeyTraverse="True"
u:Behavior.DisablePaste="True"
Height="20"
BorderThickness="0"
>
<TextBox.InputBindings>
<KeyBinding Key="Up" Command="{x:Static c:DateTimePicker.TickTimeComponentCommand}" CommandParameter="{u:Int 1}"/>
@@ -15,8 +15,7 @@ namespace mbts.ui.shell {
// The LoginContainer participates in the startup Import/Export dependency system
// Since the login form should not depend on *anything* it will be shown before this is created
// Once this is created it access the global LoginModel and retrieves the username
internal class LoginContainer
{
class LoginContainer {
[ImportingConstructor]
public LoginContainer(ServiceContext context) {
var model = LoginModel.instance;
@@ -28,10 +27,8 @@ namespace mbts.ui.shell {
model.Dispose();
}
[Export(Exports.UserName)]
public string UserName { get; private set; }
[Export(Exports.UserID)]
public uint UserId { get; private set; }
[Export]
@@ -42,13 +39,6 @@ namespace mbts.ui.shell {
[Export("workspace")]
public string Workspace { get; private set; }
public static class Exports {
public const string
UserName = "username",
UserID = "userid",
UserTuple = "usertuple";
}
}
public struct User {
+7 -1
View File
@@ -114,10 +114,16 @@ namespace mbts.ui
}
public void Dispose() {
foreach (IShellModule module in _modules.OrderBy(m => m.priority).Reverse()) {
foreach (var module in _modules.OrderBy(m => m.priority).Reverse()) {
module.Dispose();
}
_modules.Clear();
foreach (var daemon in _services) {
if (daemon is IDisposable d) {
d.Dispose();
}
}
_services.Clear();
}
}
}
@@ -12,8 +12,7 @@ using System.Windows.Input;
namespace mbts.ui.shell {
[Export(typeof(ILauncher))]
public class LauncherVM : ViewModelBase, ILauncher
{
public class LauncherVM : ViewModelBase, ILauncher {
Window _window;
string _user;
readonly IBus _bus;
@@ -23,9 +22,9 @@ namespace mbts.ui.shell {
[ImportingConstructor]
public LauncherVM(
ObservableCollection<IShellModule> modules,
[Import(LoginContainer.Exports.UserName)]string username,
UserTuple user,
ErrorReporter errors, IBus bus) {
_user = username;
_user = user.name;
_modules = new ObservableAutoWrapper<ShellModuleVM, IShellModule>(modules, m => new ShellModuleVM(m, bus));
_error_service = errors;
_bus = bus;
@@ -123,7 +122,7 @@ namespace mbts.ui.shell {
_shown = true;
if (_window != null) {
Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
if (shown != null) shown();
shown?.Invoke();
_window.Show();
}
}
@@ -140,4 +139,4 @@ namespace mbts.ui.shell {
#endregion
}
}
}
@@ -42,8 +42,8 @@ namespace mbts.ui.shell
try {
Dispatcher.Run();
}
catch (Exception e) {
Log.assert(false, e.ToString());
catch (Exception ex) {
Log.assert(false, $"Exception on dispatcher thread '{name}': {ex}.");
}
finally {
Log.Ui.info("Disposing slow {0} and cleaning up background thread.".fmt(name));
+8 -1
View File
@@ -133,6 +133,12 @@ namespace mbts.co2 {
total_volume = _cold->total_volume;
return (_cold->last_trade.load_if_new(ref time, out ps));
}
public bool get_last_trade(ref ulong time, out NativePriceSize ps, out DateTime timestamp, out ulong total_volume, out bool from_spread) {
timestamp = _cold->last_trade_time;
total_volume = _cold->total_volume;
from_spread = (_cold->from_spread != 0);
return (_cold->last_trade.load_if_new(ref time, out ps));
}
public ulong misc_timestamp { get { return _cold->misc_timestamp; } }
public ulong total_volume { get { return _cold->total_volume; } }
@@ -259,7 +265,7 @@ namespace mbts.co2 {
// Last trade
public AtomicPriceSize last_trade;
public ulong total_volume;
public utils.LLDateTime last_trade_time;
public utils.LLDateTime last_trade_time;
//// Settlement
public UInt64 misc_timestamp;
@@ -280,6 +286,7 @@ namespace mbts.co2 {
public double session_low_offer;
public double fixing_price;
public int from_spread;
public int deleted;
// FixedSecurity will not be directly addressable. Instead the security is available through the callback
public Int64 security_size;
+64 -49
View File
@@ -8,7 +8,6 @@ using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
namespace bts.api.core {
@@ -94,38 +93,38 @@ namespace bts.api.core {
new Update<T, TKey>(new T[0], new T[0], new Change<T>[0], new T[0], key_extractor);
public Update<T,TKey> merge(Update<T, TKey> next) {
var comp = new RowEqualityComparer<T, TKey>(_key);
var added = this.added as HashSet<T> ?? new HashSet<T>(this.added, comp);
var added = this.added as KeyedValueSet<TKey, T> ?? new KeyedValueSet<TKey, T>(this.added, _key);
var changes = this.changed as ChangeDict<T,TKey> ?? new ChangeDict<T,TKey>(this.changes, _key);
var removed = this.removed as HashSet<T> ?? new HashSet<T>(this.removed, comp);
var removed = this.removed as KeyedValueSet<TKey, T> ?? new KeyedValueSet<TKey, T>(this.removed, _key);
// Add
added.UnionWith(next.added);
foreach (var v in next.added) {
var k = _key(v);
if (removed.Remove(k, out var oldval)) {
changes.AddOrMerge(new Change<T>(oldval, v));
} else {
added[k] = v;
}
}
// Change
foreach (var c in next.changes) {
if (added.Contains(c.Old)) {
added.Remove(c.Old);
added.Add(c.New);
}
else {
var k = _key(c.Old);
if (!added.Replace(k, c.New))
changes.AddOrMerge(c);
}
}
// Remove
foreach (var r in next.removed) {
if (!added.Remove(r)) {
removed.Add(r);
}
changes.Remove(_key(r));
var k = _key(r);
if (!added.Remove(k))
removed[k] = changes.TryRemove(k, out var ch) ? ch.Old : r;
}
return new Update<T, TKey>(
next.all,
added, changes, removed,
_key
);
_key);
}
public IEnumerable<T> all { get; }
@@ -148,6 +147,39 @@ namespace bts.api.core {
#endif
}
class KeyedValueSet<TKey, TValue> : IEnumerable<TValue> {
readonly Dictionary<TKey, TValue> _cache = new Dictionary<TKey, TValue>();
public KeyedValueSet(IEnumerable<TValue> value, Func<TValue, TKey> key) {
foreach (var v in value)
_cache[key(v)] = v;
}
public TValue this[TKey key] {
set => _cache[key] = value;
}
public bool Remove(TKey key) =>
_cache.Remove(key);
public bool Remove(TKey key, out TValue value) =>
_cache.TryGetValue(key, out value) && _cache.Remove(key);
public bool Replace(TKey key, TValue value) {
if (_cache.ContainsKey(key)) {
_cache[key] = value;
return true;
}
return false;
}
public IEnumerator<TValue> GetEnumerator() =>
_cache.Values.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() =>
GetEnumerator();
}
class ChangeDict<T, TKey> : IEnumerable<Change<T>> {
Dictionary<TKey, Change<T>> _changes;
Func<Change<T>, TKey> _key;
@@ -167,9 +199,11 @@ namespace bts.api.core {
return null;
}
public void Remove(TKey key) {
public bool Remove(TKey key) =>
_changes.Remove(key);
}
public bool TryRemove(TKey key, out Change<T> result) =>
_changes.TryGetValue(key, out result) && _changes.Remove(key);
#region IEnumerable
public IEnumerator<Change<T>> GetEnumerator() {
@@ -181,31 +215,6 @@ namespace bts.api.core {
#endregion
}
struct RowEqualityComparer<T,TKey> : IEqualityComparer<T>, IEqualityComparer<Change<T>>
where TKey : IEquatable<TKey> {
readonly Func<T,TKey> _key;
public RowEqualityComparer(Func<T,TKey> key) {
_key = key;
}
public bool Equals(T x, T y) {
return _key(x).Equals(_key(y));
}
public bool Equals(Change<T> x, Change<T> y) {
return Equals(x.New, y.New);
}
public int GetHashCode(T obj) {
return _key(obj).GetHashCode();
}
public int GetHashCode(Change<T> c) {
return GetHashCode(c.New);
}
}
public class TableUpdate<T, TKey> where TKey : IEquatable<TKey> {
// warning: this does not have a key_extractor
public static readonly TableUpdate<T, TKey> empty = new TableUpdate<T, TKey>(ImmutableDictionary<TKey, T>.Empty, Array.Empty<T>(), Array.Empty<Change<T>>(), Array.Empty<T>(), null);
@@ -736,13 +745,19 @@ namespace bts.api.core {
return new CompositeDisposable(source.Subscribe(aggregator.on_left), right.Subscribe(aggregator.on_right));
});
public static IObservable<TResult> AggregateLatest<TLeft, TRight, TAggregate, TResult>(this IObservable<TLeft> source, IObservable<TRight> right,
Func<TAggregate, Change<TLeft>, TRight, TAggregate> update_left, Func<TAggregate, TLeft, Change<TRight>, TAggregate> update_right, TAggregate seed,
public static IObservable<TResult> AggregateLatest<TLeft, TRight, TAggregate, TResult>(
this IObservable<TLeft> source,
IObservable<TRight> right,
Func<TAggregate, Change<TLeft>, TRight, TAggregate> update_left,
Func<TAggregate, TLeft, Change<TRight>, TAggregate> update_right,
Func<TAggregate> seed_factory,
Func<TAggregate, TResult> result_selector,
TLeft init_left = default, TRight init_right = default) =>
TLeft init_left = default,
TRight init_right = default) =>
//
Observable.Create<TResult>(o => {
Log.DataFlow.diag($"Create AggregateLatest (Left: {typeof(TLeft)}, Right: {typeof(TRight)}).");
var aggregator = new ConcurrentAggregator<TLeft, TRight, TAggregate>(update_left, update_right, agg => o.OnNext(result_selector(agg)), seed, init_left, init_right);
var aggregator = new ConcurrentAggregator<TLeft, TRight, TAggregate>(update_left, update_right, agg => o.OnNext(result_selector(agg)), seed_factory(), init_left, init_right);
return new CompositeDisposable(source.Subscribe(aggregator.on_left), right.Subscribe(aggregator.on_right));
});
@@ -922,4 +937,4 @@ namespace bts.api.core {
$"T is '{typeof(T)}', TKey is '{typeof(TKey)}'";
}
}
}
}
@@ -18,7 +18,7 @@ namespace bts.api.core {
return left_source.AggregateLatest<TableUpdate<TLeft, TKey>, TableUpdate<TRight, TKey>, (TableUpdate<TResult, TKey> result, IReadOnlyDictionary<TKey, TLeft> left_state, IReadOnlyDictionary<TKey, TRight> right_state), TableUpdate<TResult, TKey>>(right_source,
process_left,
process_right,
(TableUpdate<TResult, TKey>.mk_empty(result_key), new Dictionary<TKey, TLeft>(0), new Dictionary<TKey, TRight>(0)),
() => (TableUpdate<TResult, TKey>.mk_empty(result_key), new Dictionary<TKey, TLeft>(0), new Dictionary<TKey, TRight>(0)),
t => t.result,
TableUpdate<TLeft, TKey>.mk_empty(left_key), TableUpdate<TRight, TKey>.mk_empty(right_key));
// left
@@ -20,7 +20,7 @@ namespace bts.api.core {
right_source,
process_left,
process_right,
(TableUpdate<TResult, TLeftKey>.mk_empty(result_key), new Dictionary<TRightKey, HashSet<TLeftKey>>()),
() => (TableUpdate<TResult, TLeftKey>.mk_empty(result_key), new Dictionary<TRightKey, HashSet<TLeftKey>>()),
state => state.result,
TableUpdate<TLeft, TLeftKey>.mk_empty(left_key),
TableUpdate<TRight, TRightKey>.mk_empty(right_key));
@@ -1,15 +1,28 @@
using System;
namespace bts {
struct UserTuple : IEquatable<UserTuple>, IComparable<UserTuple>, IComparable {
public readonly struct UserTuple : IEquatable<UserTuple>, IComparable<UserTuple>, IComparable {
const string _admin_name = "bts";
public static readonly Func<UserTuple, uint> key_fn = u => u.id;
public static UserTuple admin => new UserTuple(0, _admin_name, Permissions.Admin);
public readonly uint id;
public readonly string name;
public readonly Permissions permissions;
public UserTuple(uint id, string name) {
public UserTuple(uint id, string name)
: this(id, name, name == _admin_name ? Permissions.Admin : Permissions.Regular) { }
public UserTuple(uint id, string name, Permissions permissions) {
this.id = id;
this.name = name;
this.permissions = permissions;
}
public enum Permissions {
Regular,
Admin
}
public int CompareTo(UserTuple other) {
@@ -28,4 +41,9 @@ namespace bts {
public static bool operator ==(UserTuple a, UserTuple b) => a.Equals(b);
public static bool operator !=(UserTuple a, UserTuple b) => !a.Equals(b);
}
}
public static class UserTupleExtensions {
public static bool can_access_user_data(this UserTuple user, uint user_id) =>
user.id == user_id || user.permissions == UserTuple.Permissions.Admin;
}
}
+33 -39
View File
@@ -13,84 +13,78 @@ namespace bts.md {
enum MDSourceOptions {
DeferInit = 1,
}
class MDSource : IObserver<List<SecurityAndHandle>>, IDisposable
{
class MDSource : IObserver<List<SecurityAndHandle>>, IDisposable {
const uint _no_user_id = 0;
protected readonly MDConsumer _consumer = new MDConsumer();
protected readonly Co2RelayControl _relay;
protected DateTime _version = DateTime.MinValue;
protected readonly ConcurrentDictionary<SecurityKey, SecurityMD> _exchange_sec_map = new ConcurrentDictionary<SecurityKey, SecurityMD>();
protected List<IDisposable> _dispose = new List<IDisposable>();
protected readonly MDSourceOptions _options;
readonly uint _user_id;
protected DateTime _version = DateTime.MinValue;
protected List<IDisposable> _dispose = new List<IDisposable>();
public MDSource(uint naggle_ms, MDSourceOptions options = 0, uint user_id = _no_user_id)
{
readonly UserTuple _user;
readonly BehaviorSubject<ConcurrentDictionary<SecurityKey, SecurityMD>> _on_securities =
new BehaviorSubject<ConcurrentDictionary<SecurityKey, SecurityMD>>(new ConcurrentDictionary<SecurityKey, SecurityMD>());
public MDSource(uint naggle_ms, MDSourceOptions options = 0)
: this(naggle_ms, options, UserTuple.admin) { }
public MDSource(uint naggle_ms, MDSourceOptions options, UserTuple user) {
_options = options;
_user_id = user_id;
_user = user;
_relay = new Co2RelayControl(_consumer, naggle_ms);
_relay.preload_securities((co2.MDRequest.Types.Flags)0xff).ignore();
_dispose.Add(_consumer.on_security.Subscribe(this));
if(!options.HasFlag(MDSourceOptions.DeferInit))
if (!options.HasFlag(MDSourceOptions.DeferInit))
initialize();
}
readonly BehaviorSubject<ConcurrentDictionary<SecurityKey, SecurityMD>> _on_securities =
new BehaviorSubject<ConcurrentDictionary<SecurityKey, SecurityMD>>( new ConcurrentDictionary<SecurityKey, SecurityMD>() );
public IObservable<ConcurrentDictionary<SecurityKey, SecurityMD>> on_securities => _on_securities;
virtual public void initialize()
{
public virtual void initialize() =>
Task.Run(run);
}
public void set_token(AuthTokenImmutable token)
{
public void set_token(AuthTokenImmutable token) =>
_relay.set_token(token);
}
public void OnCompleted() { }
public void OnError(Exception error) => Log.Md.error(error.ToString());
public void OnError(Exception error) =>
Log.Md.error(error.ToString());
public void OnNext(List<SecurityAndHandle> values) {
if (values.Count > 0) {
foreach (var v in values) {
if (_user_id != _no_user_id &&
v.security.ContractCase == Security.ContractOneofCase.Synthetic &&
v.security.Synthetic.UserId != _user_id &&
v.security.Synthetic.UserId != _no_user_id) {
continue;
if (v.security.ContractCase != Security.ContractOneofCase.Synthetic || _user.can_access_user_data(v.security.Synthetic.UserId)) {
var smd = new SecurityMD(new SecurityImmutable(v.security), v.handle);
_exchange_sec_map.AddOrUpdate(smd.security.Id, smd, (_, __) => smd);
}
var smd = new SecurityMD(new SecurityImmutable(v.security), v.handle);
_exchange_sec_map.AddOrUpdate(smd.security.Id, smd, (_, __) => smd);
}
_version = DateTime.UtcNow;
}
}
public void Dispose() => Disposable.dispose(_dispose);
async protected Task run()
{
public void Dispose() =>
Disposable.dispose(_dispose);
protected async Task run() {
DateTime run_version = DateTime.MinValue;
while (true)
{
while (true) {
var exch = _exchange_sec_map;
var current_version = _version;
if (current_version > run_version)
{
if (current_version > run_version) {
run_version = current_version;
try
{
try {
Log.Md.info($"MDSource publishing {exch.Count} securities");
_on_securities.OnNext(exch);
}
catch (Exception e)
{
} catch (Exception e) {
Log.Md.error($"Error in publish_securities: {e}");
}
}
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
}
}
}
+4 -6
View File
@@ -1,13 +1,11 @@
using bts.api;
using mbts.co2;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mbts {
struct SecurityMD : IEquatable<SecurityMD> {
readonly struct SecurityMD : IEquatable<SecurityMD> {
public static readonly Func<SecurityMD, uint> key_fn = smd => smd.security.Id;
public SecurityImmutable security { get; }
public MDConsumerHandle md { get; }
@@ -36,4 +34,4 @@ namespace mbts {
return !(left == right);
}
}
}
}
@@ -278,6 +278,9 @@ namespace System.Collections.Generic {
public static IComparer<KeyValuePair<TKey, TValue>> key_comparer<TKey, TValue>() =>
Impl<TKey, TValue>.key_comparer;
public static IReadOnlyDictionary<TKey, TValue> wrap_value<TKey, TValue>(TKey key, TValue value) =>
new Impl<TKey, TValue>.ValueWrapper(key, value);
static class Impl<TKey, TValue> {
public static readonly IReadOnlyDictionary<TKey, TValue> empty =
new ReadOnlyDictionary<TKey, TValue>(new Dictionary<TKey, TValue>(0));
@@ -297,6 +300,57 @@ namespace System.Collections.Generic {
public int Compare(object x, object y) =>
x is KeyValuePair<TKey, TValue> xkv ? (y is KeyValuePair<TKey, TValue> ykv ? Compare(xkv, ykv) : 1) : -1;
}
public class ValueWrapper : IReadOnlyDictionary<TKey, TValue> {
readonly TKey _key;
readonly TValue _value;
readonly IEqualityComparer<TKey> _key_comparer;
public ValueWrapper(TKey key, TValue value)
: this(key, value, EqualityComparer<TKey>.Default) { }
public ValueWrapper(TKey key, TValue value, IEqualityComparer<TKey> key_comparer) {
_key = key;
_value = value;
_key_comparer = key_comparer;
}
public TValue this[TKey key] =>
_key_comparer.Equals(key, _key) ? _value : throw new KeyNotFoundException();
public int Count => 1;
public IEnumerable<TKey> Keys {
get {
yield return _key;
}
}
public IEnumerable<TValue> Values {
get {
yield return _value;
}
}
public bool ContainsKey(TKey key) => _key_comparer.Equals(key, _key);
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
yield return new KeyValuePair<TKey, TValue>(_key, _value);
}
IEnumerator IEnumerable.GetEnumerator() {
yield return new KeyValuePair<TKey, TValue>(_key, _value);
}
public bool TryGetValue(TKey key, out TValue value) {
if (_key_comparer.Equals(key, _key)) {
value = _value;
return true;
}
value = default;
return false;
}
}
}
}
}
@@ -343,6 +343,18 @@ namespace System.Collections.Generic {
return false;
}
public static List<T> ToListSorted<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> key_selector) =>
enumerable.ToListSorted(key_selector, Comparer<TKey>.Default);
public static List<T> ToListSorted<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> key_selector, IComparer<TKey> key_comparer) =>
enumerable.ToListSorted(key_comparer.wrap(key_selector));
public static List<T> ToListSorted<T>(this IEnumerable<T> enumerable, IComparer<T> comparer) {
var list = new List<T>(enumerable);
list.Sort(comparer);
return list;
}
/// <summary>
/// Simply returns enumerable.ToList(), under the guise ofo IReadOnlyList&lt;&gt;
/// </summary>
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
namespace bts.collections {
public static class ImmutableSetExtensions {
public static IImmutableSet<T> RemoveRange<T>(this IImmutableSet<T> source, IEnumerable<T> values) {
/// Prefer the <see cref="ImmutableHashSet{T}"/> implementation.
/// It uses an <see cref="ImmutableHashSet{T}.Builder"/> to remove values, which is optimized for bulk changes (less memory allocations, etc.).
if (source is ImmutableHashSet<T> ihs) {
return ihs.RemoveRange(values);
}
if (source == null) throw new ArgumentNullException(nameof(source));
if (values == null) throw new ArgumentNullException(nameof(values));
foreach (var v in values)
source = source.Remove(v);
return source;
}
public static ImmutableHashSet<T> RemoveRange<T>(this ImmutableHashSet<T> source, IEnumerable<T> values) {
if (source == null) throw new ArgumentNullException(nameof(source));
if (values == null) throw new ArgumentNullException(nameof(values));
var bd = source.ToBuilder();
foreach (var v in values)
bd.Remove(v);
return bd.ToImmutable();
}
}
}
@@ -10,9 +10,9 @@ using System.Diagnostics;
namespace bts.test {
public static class InProcessTestRunner {
public static void run_test_synchronously(string v, TestEnumerator enumerator, Action<TestResult> report) {
foreach (var t in enumerator.find(v)) {
run_test_synchronously(t, report);
public static void run_test_synchronously(string v, TestType type, TestEnumerator enumerator, Action<TestResult> report) {
foreach (var t in enumerator.find(v,type)) {
run_test_synchronously(t, report);
}
}
public static void run_test_synchronously(TestMethod test, Action<TestResult> report) {
@@ -36,18 +36,19 @@ namespace bts.test {
}
public IEnumerable<TestMethod> find(string name) {
public IEnumerable<TestMethod> find(string name, TestType type) {
foreach (var g in TestGroups) {
foreach (var t in g.methods) {
if (g.name == name || t.name == name || t.full_name == name) {
if (g.test_type == type &&
(g.name == name || t.name == name || t.full_name == name)) {
yield return t;
}
}
}
}
public IEnumerable<TestMethod> match(IEnumerable<string> names) {
return names.SelectMany(find).Distinct();
public IEnumerable<TestMethod> match(TestType type, IEnumerable<string> names) {
return names.SelectMany(name => find(name,type)).Distinct();
}
}
@@ -1,64 +0,0 @@
using bts;
using bts.api.admin;
using System;
using System.Collections.Generic;
using System.Linq;
namespace bts.api.core
{
public class AdminModelWrapper
{
readonly AdminDataImmutable? _admin_data;
public AdminDataImmutable? admin_data => _admin_data;
readonly string _user_name;
readonly List<BTSAccountImmutable> _allowed_accounts;
readonly Dictionary<string, string> _allowed_account_dict = new Dictionary<string, string>();
public AdminModelWrapper(AdminDataImmutable? admin_data = null, string user_name = null)
{
_admin_data = admin_data;
_user_name = user_name ?? string.Empty;
_allowed_accounts = search_admin(u => u.Name == _user_name).Where(x =>
{
return (x.Item2 != null && x.Item2.HasPermissions) || (x.Item3 != null && x.Item3.HasPermissions);
}).Select(xx => xx.Item1).ToList();
foreach (var val in _allowed_accounts)
_allowed_account_dict[val.Name] = val.Name;
}
public IEnumerable<BTSAccountImmutable> viewable_accounts()
{
return _allowed_accounts;
}
public bool can_view_account(string account)
{
return _allowed_account_dict.ContainsKey(account) || _user_name.ToLower().Equals("bts");
}
IEnumerable<Tuple<BTSAccountImmutable, TradingPermissionUnit, AdminPermissionUnit>>
search_admin(Func<BTSUserImmutable, bool> predicate)
{
var rv = new List<Tuple<BTSAccountImmutable, TradingPermissionUnit, AdminPermissionUnit>>();
if (_admin_data.HasValue)
{
var users = _admin_data.Value.Users.Where(predicate);
if (users != null && users.Count() == 1)
{
var user = users.ElementAt(0);
if (user.HasUserData && user.UserData.HasAccountPermissions)
{
foreach (var kv in user.UserData.AccountPermissions.AccountPermissions)
{
var account_id = kv.Key;
var accounts = _admin_data.Value.Accounts.Where(a => a.Id == account_id);
if (accounts != null && accounts.Count() == 1)
{
var account = accounts.ElementAt(0);
rv.Add(Tuple.Create(account, kv.Value.TradingPermission, kv.Value.AdminPermission));
}
}
}
}
}
return rv;
}
}
}
@@ -1,64 +0,0 @@
using bts;
using bts.api;
using bts.api.core;
using bts.api.orderman;
using bts.api.position;
using bts.spark;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.Specialized;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
namespace bts.api.core
{
public static class PermissionFilters
{
public static IObservable<Update<PositionUnitImmutable, int>>
PermissionFilter(this IObservable<Update<PositionUnitImmutable, int>> source, IObservable<AdminModelWrapper> am)
{
var pred = Observable.Create<Func<PositionUnitImmutable, bool>>( observer =>
{
return am.Subscribe(x =>
{
Func<PositionUnitImmutable, bool> filter = (z => x.can_view_account(z.Account));
observer.OnNext(filter);
});
});
return source.Filter(pred);
}
public static IObservable<Update<OrderRecordImmutable, uint>>
PermissionFilter(this IObservable<Update<OrderRecordImmutable, uint>> source, IObservable<AdminModelWrapper> am)
{
var pred = Observable.Create<Func<OrderRecordImmutable, bool>>(observer =>
{
return am.Subscribe(x =>
{
Func<OrderRecordImmutable, bool> filter = (z => x.can_view_account(z.Def.Account ?? string.Empty));
observer.OnNext(filter);
});
});
return source.Filter(pred);
}
public static IObservable<Update<FillImmutable, string>>
PermissionFilter(this IObservable<Update<FillImmutable, string>> source, IObservable<AdminModelWrapper> am)
{
var pred = Observable.Create<Func<FillImmutable, bool>>(observer =>
{
return am.Subscribe(x =>
{
Func<FillImmutable, bool> filter = (z => x.can_view_account(z.Account));
observer.OnNext(filter);
});
});
return source.Filter(pred);
}
}
}
+96
View File
@@ -0,0 +1,96 @@
using System;
using System.IO;
using mbts.config;
using System.IO.Compression;
using System.Runtime.InteropServices;
using Google.Protobuf;
using bts;
using System.Linq;
using bts.support;
namespace mbts
{
public static class LogUtil {
private static string log_path = Path.Combine(Configuration.get<bts.config.System>().data_path, "logging", "log");
public static ByteString read_logs_compressed() {
return FileUtils.read_and_gzip(log_path);
}
public static (ByteString,DateTime) read_latest_crash_dump() {
// Find the latest crash dump
// If it is < 5 days old
// gzip it in place (delete original)
// upload the gziped dump
var crash_dump_folder = "c:\\programdata\\bts\\crash_dumps";
FileUtils.keep_n_matching_files(crash_dump_folder, "*.gz", 4);
try {
if (Directory.Exists(crash_dump_folder)) {
var latest =
Directory.GetFiles(crash_dump_folder, "*.dmp")
.Select(f => new { name = f, modified = File.GetLastWriteTimeUtc(f) })
.OrderBy(f => f.modified)
.Reverse()
.FirstOrDefault();
if (latest != null) {
if (DateTime.Now - latest.modified <= TimeSpan.FromDays(5)) {
var newname = FileUtils.gzip_file_in_place(latest.name);
if (!string.IsNullOrEmpty(newname)) {
return (ByteString.FromStream(File.OpenRead(newname)), latest.modified);
}
}
}
}
}
catch (Exception e) {
Log.Gen.error($"Failed to read crash dumps. Exception: {e.Message}");
}
return (ByteString.Empty, DateTime.MinValue);
}
public static ByteString read_windows_event_log() {
// try to export the events to temp
var temp = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".evtx");
bool success = NativeMethods.EvtExportLog(
IntPtr.Zero,
"Application",
"*",
temp,
NativeMethods.EventExportLogFlags.ChannelPath);
if (success) {
var result = FileUtils.read_and_gzip(temp);
FileUtils.try_delete(temp);
return result;
}
else {
string msg = new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()).Message;
Log.Gen.error($"Error exporting windows event log. {msg}");
}
return ByteString.Empty;
}
static class NativeMethods {
[Flags]
public enum EventExportLogFlags {
ChannelPath = 1,
LogfilePath = 2,
TolerateQueryErrors = 0x1000
}
[DllImport("wevtapi.dll", CallingConvention=CallingConvention.Winapi, CharSet = CharSet.Auto, SetLastError =true)]
public static extern bool EvtExportLog(
IntPtr session,
string path,
string query,
string targetPath,
[MarshalAs(UnmanagedType.I4)]
EventExportLogFlags flags);
}
}
}
-32
View File
@@ -1,32 +0,0 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net.Mail;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using mbts.config;
using System.Collections.Generic;
namespace mbts
{
public static class LogUtil {
public static string read_logs() {
var log_path = Path.Combine(Configuration.get<bts.config.System>().data_path, "logging", "log");
if (File.Exists(log_path)) {
try {
using (var f = File.Open(log_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
var reader = new StreamReader(f);
return reader.ReadToEnd();
}
}
catch (Exception e) {
return e.ToString();
}
}
return "Log file does not exist";
}
}
}
+76
View File
@@ -0,0 +1,76 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using Google.Protobuf;
namespace bts.support {
static class FileUtils {
public static bool try_delete(string path) {
try {
if (File.Exists(path)) {
File.Delete(path);
}
else if (Directory.Exists(path)) {
Directory.Delete(path, true);
}
}
catch {
return false;
}
return true;
}
public static ByteString read_and_gzip(string path) {
if (File.Exists(path)) {
try {
using (var fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite /*Note: ReadWrite is more permissive than Read*/))
using (var ms = new MemoryStream())
using (var gz = new GZipStream(ms, CompressionMode.Compress, true)) {
fs.CopyTo(gz);
gz.Close();
return ByteString.CopyFrom(ms.GetBuffer(), 0, (int)ms.Length);
}
}
catch (Exception e) {
Log.Gen.error($"Failed to read file '{path}' -- {e.Message}");
return ByteString.Empty;
}
}
return ByteString.Empty;
}
// If input exists compress it and add a .gz extension
// original file is deleted
public static string gzip_file_in_place(string file) {
if (File.Exists(file)) {
string destination = file + ".gz";
using (var input = File.OpenRead(file)) {
using (var output = File.OpenWrite(destination)) {
using (var writer = new GZipStream(output, CompressionMode.Compress)) {
input.CopyTo(writer);
}
}
}
try_delete(file);
return destination;
}
return null;
}
// Delete the oldest files matching pattern (*.txt) keeping {count} files
public static void keep_n_matching_files(string directory, string pattern, int count) {
var to_delete =
Directory.GetFiles(directory, pattern)
.Select(f => new { name = f, modified = File.GetLastWriteTimeUtc(f) })
.OrderBy(f => f.modified)
.Reverse()
.Skip(count);
foreach (var f in to_delete) {
try_delete(f.name);
}
}
}
}
+2 -1
View File
@@ -142,7 +142,8 @@ namespace mbts.co2.tests
Assert.IsTrue(entry.session_low_offer == 5.5);
Assert.IsTrue(entry.fixing_price == 6.6);
Assert.IsTrue(entry.deleted == 1);
Assert.IsTrue(entry.from_spread == 0);
Assert.IsTrue(entry.deleted == 1);
}
[Test]
@@ -2,6 +2,7 @@
using bts.co2;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -39,8 +40,29 @@ namespace bts.tests {
return null;
}
public static async Task<IEnumerable<SecurityImmutable>> get_multiple_securities(MarketDataRelay relay, IEnumerable<Product> products, SecurityType security_type, MDRequest.Types.Flags flags = MDRequest.Types.Flags.Bbo, Venue v = Venue.Sim) {
var request = new MDRequest() { Host = _MD_HOST };
request.Channels.AddRange(products.Select(z =>
new SecurityChannel() {
Time = 0,
Flags = (uint)flags,
Type = security_type,
Exchange = v,
Symbol = z.Symbol,
TradeCursor = 0,
RfqCursor = 0
}));
var result = await relay.requestmd_async(request);
if (result.success) {
return result.value.Channels.Where(s => s.Updates.Count > 0).Select(x => (SecurityImmutable) x.Updates.First().Security);
}
return Enumerable.Empty<SecurityImmutable>();
}
public static async Task<IEnumerable<FutureContract>> get_expirations(MarketDataRelay relay, string symbol, SecurityType security_type, MDRequest.Types.Flags flags = MDRequest.Types.Flags.Bbo, Venue v = Venue.Sim) {
var request = new MDRequest() {
var request = new MDRequest() {
Host = _MD_HOST,
Channels = {
new SecurityChannel() {
+23 -6
View File
@@ -85,6 +85,8 @@ namespace bts.tests.utils {
if(timeout == null) {
timeout = TimeSpan.FromMinutes(2);
}
Console.WriteLine("Please Wait... this is going to take some time...");
await Task.Delay(180000);
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
@@ -131,6 +133,13 @@ namespace bts.tests.utils {
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
var prts = mbts.config.Configuration.get<bts.config.Ports>();
Console.WriteLine("\n\n\n\n\n\n\n\n\n\n");
Console.WriteLine("config_port: " + prts.config_port);
Console.WriteLine("qbus_port: " + prts.qbus_port);
Console.WriteLine("glbx_sim_fix_port: " + prts.glbx_sim_fix_port);
Console.WriteLine("\n\n\n\n\n\n\n\n\n\n");
var ctx = new ServiceContext();
var mdrelay = ctx.locate<bts.co2.MarketDataRelay>();
@@ -143,20 +152,28 @@ namespace bts.tests.utils {
products = tmpp.value;
break;
}
else {
Console.WriteLine("mdrelay.request_products_async Error: ");
Console.WriteLine(tmpp.error_message);
}
await Task.Delay(10000);
}
//UserSymbol.get_all() in MDConsumer.cs
bts.test.Assert.IsTrue(products != null, "No products found");
var filtered_products = products.Products.Where(z => z.Exchange == Venue.Sim && z.Type == SecurityType.Future);
bts.test.Assert.IsTrue(filtered_products.Count() > 0, "No suitable products found");
IEnumerable<Product> filtered_products = products.Products.Where(z => z.Exchange == Venue.Sim && z.Type == SecurityType.Future);
bts.test.Assert.IsTrue(filtered_products.Count() > 0, "No suitable products found"); //products are not guaranteed to have securities, so I need to get the product from the list of securities
uint? sec_id = null;
/* get securities if the list is not empty use the top one */
for(int i = 0; i < 10; i++) {
var test_security = await MarketDataUtilities.get_security(mdrelay, filtered_products.First().Symbol, SecurityType.Future, f => true);
if(test_security.HasValue) {
var test_security = await MarketDataUtilities.get_multiple_securities(mdrelay, filtered_products, SecurityType.Future);
if(test_security.Count() > 0) {
Console.Write("," + i);
sec_id = test_security.Value.Id;
sec_id = test_security.FirstOrDefault().Id;
break;
}
await Task.Delay(10000);
@@ -237,7 +254,7 @@ namespace bts.tests.utils {
Result<co2.MDReply>? md_result = await await_with_timeout(
md_relay.requestmd_async(md_request),
timeout);
Console.Write(md_result);
return md_result != null;
}
}
@@ -347,6 +347,12 @@ namespace mbts.api.Test {
var a3 = new Update<string, int>(new[] { "a3" }, empty, new[] { new Change<string>("a2", "a3") }, empty, key);
var merged = a2.merge(a3);
Assert.SequenceEqual(new[] { new Change<string>("a1", "a3") }, merged.changes);
// clear the state, then add a2 back
// (this validates the fix for the Update.naggle bug where interim changes were converted into added/removed).
var cleared = new Update<string, int>(empty, empty, Array.Empty<Change<string>>(), merged.all, key);
a2 = new Update<string, int>(new[] { "a2" }, new[] { "a2" }, Array.Empty<Change<string>>(), empty, key);
merged = merged.merge(cleared).merge(a2);
Assert.SequenceEqual(new[] { new Change<string>("a1", "a2") }, merged.changes);
}
T id<T>(T t) => t;
@@ -30,6 +30,8 @@ cat << EOF > $sparkdata_dir/conf/spark.conf
}
EOF
echo "Port"
./sparkd configcheck Ports
nohup ./sparkd run &
pid=$!
+9 -3
View File
@@ -48,7 +48,7 @@ namespace sparkcmd {
}
else Configuration.initialize();
Console.WriteLine(JsonConvert.SerializeObject(o));
ConsoleEx.WriteLine(JsonConvert.SerializeObject(o), ConsoleColor.DarkGray);
if (o.list) {
list_tests((o.type));
@@ -58,13 +58,19 @@ namespace sparkcmd {
if (o.timeout == 0 && o.tests.Count() == 1 && !o.self_contained) {
//System.Threading.Thread.Sleep(5000);
using (var trr = new TestResultReceiver(true)) {
InProcessTestRunner.run_test_synchronously(o.tests.First(), Enumerator, trr.get_reporter());
InProcessTestRunner.run_test_synchronously(o.tests.First(), o.type, Enumerator, trr.get_reporter());
trr.print_summary();
if (trr.ResultCount == 0) {
ConsoleEx.Write("No ", ConsoleColor.Red);
ConsoleEx.Write(o.type.ToString(), ConsoleColor.Yellow);
ConsoleEx.WriteLine($" tests matched filter '{o.tests.First()}'", ConsoleColor.Red);
return -1;
}
return trr.ErrorCount;
}
}
else if (o.tests.Count() > 0) {
return run_tests(o, Enumerator.match(o.tests));
return run_tests(o, Enumerator.match(o.type, o.tests));
}
else {
return run_tests(o, Enumerator.get_of_type(o.type));
+6 -1
View File
@@ -29,8 +29,13 @@ namespace sparkcmd {
// initialized from c++ instead of c#
BTSNativeMethods.provide_command_line(args, args.Length);
var parser = new Parser(ps => {
ps.CaseInsensitiveEnumValues = true;
ps.HelpWriter = Console.Out;
});
// note: this can be made to infer the options type list from the list of delegates
return Parser.Default
return parser
.ParseArguments<
ConfigcheckOptions,
ScriptClientOptions,
+1 -1
View File
@@ -22,7 +22,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.4.3" />
<PackageReference Include="CommandLineParser" Version="2.6.0" />
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
@@ -11,7 +11,6 @@
-->
<connectivityConfiguration>
<!-- TCP Connection Information -->
<tcp>
<server name="default">
<ip>63.247.113.163</ip>
@@ -19,7 +18,7 @@
<userName>bluetrd-ps</userName>
<password>Starts123</password>
<getStripInfoMessages>N</getStripInfoMessages>
<strategyPreference>Legacy</strategyPreference>
<strategyPreference>New</strategyPreference>
<localNetworkInterface></localNetworkInterface>
</server>
<server name="endex">
@@ -28,7 +27,7 @@
<userName>Value from ICE Support</userName>
<password>Value from ICE Support</password>
<getStripInfoMessages>N</getStripInfoMessages>
<strategyPreference>Legacy</strategyPreference>
<strategyPreference>New</strategyPreference>
<localNetworkInterface></localNetworkInterface>
</server>
<server name="liffe-eu">
@@ -37,7 +36,7 @@
<userName>bluetrdl-ps</userName>
<password>Starts123</password>
<getStripInfoMessages>N</getStripInfoMessages>
<strategyPreference>Legacy</strategyPreference>
<strategyPreference>New</strategyPreference>
<localNetworkInterface></localNetworkInterface>
</server>
<settings>
@@ -17,10 +17,10 @@
<server name="default">
<ip>63.247.113.214</ip>
<port>3000</port>
<userName>Value from ICE Support</userName>
<password>Value from ICE Support</password>
<userName>bt_ps</userName>
<password>Starts123</password>
<getStripInfoMessages>N</getStripInfoMessages>
<strategyPreference>Legacy</strategyPreference>
<strategyPreference>New</strategyPreference>
<localNetworkInterface></localNetworkInterface>
</server>
<settings>
+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/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/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/position_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/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/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;md/vendor/OnixsUtils.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/SecureLogoLine 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/service_helpers/PositionUtilities.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/BasePositionService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/position_cfg.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/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/position_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/sod.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/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;md/vendor/OnixsUtils.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/SecureLogoLine truncated
@@ -10,6 +10,7 @@ namespace {{package}} {
{{#each message_type}}
partial class {{name}} : bts.api.IImmutableMessage {
MessageDescriptor bts.api.IImmutableMessage.Descriptor => {{name}}.Descriptor;
public {{name}}Immutable immutable() => new {{name}}Immutable(this);
}
public readonly partial struct {{name}}Immutable : bts.api.IImmutableMessage {
readonly {{name}} _impl;
+314 -48
View File
@@ -46,12 +46,15 @@ bool AdminServiceUtils::has_exchange(const ExchangeConnection& conn,
break;
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
rv = conn.has_sim_connection();
break;
case api::Venue::VENUE_ICE:
rv = conn.has_ice_connection();
break;
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
rv = false;
@@ -89,6 +92,23 @@ const ExchangeConnection* AdminServiceUtils::resolve_cme_connection(
return nullptr;
}
const bts::api::admin::ExchangeConnection*
AdminServiceUtils::resolve_ice_connection(const bts::api::admin::AdminData& data,
const bts::api::admin::BTSAccount& account,
const bts::api::Security&)
{
if(account.has_connections())
{
for (const std::string& conn_name : account.connections().exchange_connection_names())
{
const bts::api::admin::ExchangeConnection* conn = find_connection(data, conn_name);
if (conn!=nullptr && conn->has_ice_connection())
return conn;
}
}
return nullptr;
}
const bts::api::admin::ExchangeConnection*
AdminServiceUtils::resolve_sim_connection(const bts::api::admin::AdminData& data,
const bts::api::admin::BTSAccount& account,
@@ -117,14 +137,22 @@ AdminServiceUtils::resolve_connection(const bts::api::admin::AdminData& data,
rv = resolve_sim_connection(data, account, sec);
break;
}
case api::Venue::VENUE_ICE:
{
rv = resolve_ice_connection(data, account, sec);
auto deployment_type = boost::to_lower_copy(config::get<config::DeploymentType>().type());
if (rv == nullptr && (deployment_type == "dev" || deployment_type == "demo"))
rv = resolve_sim_connection(data, account, sec);
break;
}
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
rv = resolve_sim_connection(data, account, sec);
break;
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
rv = nullptr;
@@ -161,9 +189,15 @@ void AdminServiceUtils::fill_connections_from_config(bts::api::admin::AdminData&
case config::JetFIX::Connection::CBOE:
break;
case config::JetFIX::Connection::SIM:
case config::JetFIX::Connection::SIMICE:
connection.mutable_sim_connection();
add_connection(admin_data,connection);
break;
case config::JetFIX::Connection::ICE:
connection.mutable_ice_connection()->set_sender_compid(c.sender_compid());
add_connection(admin_data,connection);
break;
}
}
for(int i=0;i<admin_data.accounts_size();i++)
@@ -350,13 +384,16 @@ std::string AdminServiceUtils::find_account_exchange_account (
rv = cme_account_data->clearing_account();
break;
}
case api::Venue::VENUE_ICE:{
case api::Venue::VENUE_ICE:
{
auto ice_account_data = get_account_ice_data(account, data);
if (ice_account_data != nullptr)
rv = ice_account_data->clearing_account_override();
break;
rv = ice_account_data->clearing_account();
break;
}
case api::Venue::VENUE_SIM: {
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
{
auto sim_account_data = get_account_sim_data(account, data);
if (sim_account_data != nullptr)
rv = sim_account_data->clearing_account();
@@ -466,6 +503,46 @@ bts::api::orderman::RoutingRecord AdminServiceUtils::get_routing_record(const bt
return rv;
}
switch (sec.exchange()) {
case api::Venue::VENUE_ICE:
{
const bts::api::admin::ICEUserData* ice_user_data = get_user_ice_data(*user_ptr, data);
if(ice_user_data==nullptr)
{
out_result.set_is_success(false);
out_result.set_error_text("Could not find ICE data for user");
return rv;
}
const bts::api::admin::ICEAccountData* ice_account_data = get_account_ice_data(*account_ptr, data);
if(ice_account_data==nullptr)
{
out_result.set_is_success(false);
out_result.set_error_text("Could not find ICE data for account");
return rv;
}
// check for data corectness
if (ice_user_data->operator_id().length() == 0)
{
out_result.set_is_success(false);
out_result.set_error_text("Operator ID is not set");
return rv;
}
rv.set_session(conn_ptr->name());
rv.set_sender_compid(conn_ptr->ice_connection().sender_compid());
rv.set_account(ice_account_data->clearing_account());
rv.set_operator_id(ice_user_data->operator_id());
rv.set_cti_code(ice_account_data->cti());
rv.set_customer_or_firm(ice_account_data->origin());
rv.set_clearing_firm(ice_account_data->clearing_firm());
rv.set_customer_account_ref_id(ice_account_data->customer_account_ref_id());
rv.set_account_code(ice_account_data->account_code());
rv.set_company_id(std::to_string(ice_user_data->company_id()));
rv.set_authorized_trader(ice_user_data->authorized_trader());
rv.set_authorized_group(ice_user_data->authorized_group());
rv.set_cust_order_handing_inst(ice_user_data->cust_order_handing_inst());
return rv;
}
case bts::api::Venue::VENUE_GLBX: {
const bts::api::admin::CMEUserData* cme_user_data = get_user_cme_data(*user_ptr, data);
if(cme_user_data==nullptr){
@@ -516,7 +593,9 @@ bts::api::orderman::RoutingRecord AdminServiceUtils::get_routing_record(const bt
rv.set_customer_or_firm(cme_account_data->origin());
return rv;
}
case api::Venue::VENUE_SIM: {
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
{
const bts::api::admin::SIMUserData* sim_user_data = get_user_sim_data(*user_ptr, data);
if(sim_user_data==nullptr){
out_result.set_is_success(false);
@@ -562,8 +641,7 @@ bts::api::orderman::RoutingRecord AdminServiceUtils::get_routing_record(const bt
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
out_result.set_is_success(false);
@@ -710,6 +788,18 @@ const bts::api::admin::CMEUserData* AdminServiceUtils::get_group_cme_data(const
return nullptr;
}
const bts::api::admin::ICEUserData* AdminServiceUtils::get_group_ice_data(const bts::api::admin::BTSUserGroup& group,
const bts::api::admin::AdminData& data){
if (group.has_user_data() && group.user_data().has_exchange_user_data() && group.user_data().exchange_user_data().has_ice_data())
return &(group.user_data().exchange_user_data().ice_data());
else if (has_id(group.parent_group_id())){
const bts::api::admin::BTSUserGroup* parent_group = find_group(data, group.parent_group_id());
if (parent_group != nullptr)
return get_group_ice_data(*parent_group, data);
}
return nullptr;
}
const bts::api::admin::SIMUserData* AdminServiceUtils::get_group_sim_data(const bts::api::admin::BTSUserGroup& group,
const bts::api::admin::AdminData& data){
if (group.has_user_data() && group.user_data().has_exchange_user_data() && group.user_data().exchange_user_data().has_sim_data())
@@ -840,6 +930,18 @@ const bts::api::admin::CMEUserData* AdminServiceUtils::get_user_cme_data(const b
return nullptr;
}
const bts::api::admin::ICEUserData* AdminServiceUtils::get_user_ice_data(const bts::api::admin::BTSUser& user,
const bts::api::admin::AdminData& data){
if (user.has_user_data() && user.user_data().has_exchange_user_data() && user.user_data().exchange_user_data().has_ice_data())
return &(user.user_data().exchange_user_data().ice_data());
else{
const bts::api::admin::BTSUserGroup* parent_group = find_group(data, user.parent_group_id());
if (parent_group != nullptr)
return get_group_ice_data(*parent_group, data);
}
return nullptr;
}
const bts::api::admin::SIMUserData* AdminServiceUtils::get_user_sim_data(const bts::api::admin::BTSUser& user,
const bts::api::admin::AdminData& data){
if (user.has_user_data() && user.user_data().has_exchange_user_data() && user.user_data().exchange_user_data().has_sim_data())
@@ -867,7 +969,16 @@ std::string AdminServiceUtils::find_user_exchange_id (const bts::api::admin::Adm
rv = cme_user_data->operator_id();
break;
}
case api::Venue::VENUE_SIM: {
case api::Venue::VENUE_ICE:
{
auto ice_user_data = get_user_ice_data(user, data);
if (ice_user_data != nullptr)
rv = ice_user_data->operator_id();
break;
}
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
{
auto sim_user_data = get_user_sim_data(user, data);
if (sim_user_data != nullptr)
rv = sim_user_data->operator_id();
@@ -877,8 +988,7 @@ std::string AdminServiceUtils::find_user_exchange_id (const bts::api::admin::Adm
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::VENUE_ICE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
out_result.set_is_success(false); out_result.set_error_text("Exchange not supported");
@@ -886,30 +996,92 @@ std::string AdminServiceUtils::find_user_exchange_id (const bts::api::admin::Adm
}
return rv;
}
std::pair<const bts::api::admin::BTSAccount*, const bts::api::admin::BTSUser*>
AdminServiceUtils::find_user_account_matches (const bts::api::admin::AdminData& admin_data,
const std::string& connection, const std::string& exchange_account,
std::string AdminServiceUtils::find_user_company_id (const bts::api::admin::AdminData& data,
const bts::api::admin::BTSUser& user,
api::Venue exchange,
bts::api::admin::AdminServiceOperationResult& out_result)
{
out_result.set_is_success(true);
std::string rv = "";
switch(exchange)
{
case api::Venue::VENUE_ICE:
{
auto ice_user_data = get_user_ice_data(user, data);
if (ice_user_data != nullptr)
rv = std::to_string(ice_user_data->company_id());
break;
}
case api::Venue::VENUE_SIM:
case api::Venue::VENUE_SIMICE:
case api::Venue::VENUE_GLBX:
case api::Venue::VENUE_UNSET:
case api::Venue::VENUE_BTS:
case api::Venue::VENUE_CBOE:
case api::Venue::VENUE_CBOECFE:
case api::Venue::Venue_INT_MIN_SENTINEL_DO_NOT_USE_:
case api::Venue::Venue_INT_MAX_SENTINEL_DO_NOT_USE_:
out_result.set_is_success(false); out_result.set_error_text("Exchange not supported");
break;
}
return rv;
}
std::pair<const BTSAccount*, const BTSUser*>
AdminServiceUtils::find_user_account_matches (const AdminData& admin_data,
const std::string& connection,
const std::string& exchange_account,
const std::string& exchange_user,
api::Venue exchange){
bts::api::admin::AdminServiceOperationResult find_account_result, find_user_result;
auto account_ptrs = accounts(admin_data, false);
auto user_ptrs = users(admin_data, false);
for(const bts::api::admin::BTSAccount* account_ptr : account_ptrs){
if (account_has_connection(*account_ptr, connection)){
if (boost::algorithm::iequals(exchange_account,
find_account_exchange_account(admin_data,*account_ptr,exchange,find_account_result)) &&
find_account_result.is_success()){
for(const bts::api::admin::BTSUser* user_ptr : user_ptrs){
if (boost::algorithm::iequals(exchange_user,
find_user_exchange_id(admin_data,*user_ptr,exchange,find_user_result)) &&
find_user_result.is_success())
return std::pair<const bts::api::admin::BTSAccount*, const bts::api::admin::BTSUser*>(account_ptr,user_ptr);
}
}
}
AdminServiceOperationResult find_account_result, find_user_result;
// i. uses the exchange and exchange_user to reverse lookup the user(s)
auto user_ptrs = users(admin_data, false);
std::vector<BTSUser const*> matching_users;
for (BTSUser const* u : user_ptrs){
auto exchange_u = find_user_exchange_id(admin_data, *u,
exchange, find_user_result);
if (find_user_result.is_success() && boost::algorithm::iequals (
exchange_u,
exchange_user))
matching_users.push_back(u);
}
return std::pair<const bts::api::admin::BTSAccount*, const bts::api::admin::BTSUser*>(nullptr, nullptr);
// i.5
//At the ice, they send back the login level tag50 in exec reports which doesn't match any user level tag50s in the exchange_user
//so instead we look for the CompanyID (or client_id, tag 109) field here. If this field matches we have a good bet that
//the user we find is enough to fulfill the routing record enough to cancel or modify orphaned orders, etc
for (BTSUser const* u : user_ptrs)
{
auto exchange_u = find_user_company_id(admin_data, *u, exchange, find_user_result);
if (find_user_result.is_success() && boost::algorithm::iequals ( exchange_u, exchange_user))
matching_users.push_back(u);
}
// ii. uses the exchange, connection and exchange_account to reverse lookup the account(s)
auto account_ptrs = accounts(admin_data, false);
std::vector<BTSAccount const*> matching_accounts;
for (BTSAccount const* a :account_ptrs)
if (account_has_connection(*a, connection)){
auto exchange_a = find_account_exchange_account(admin_data, *a,
exchange,
find_account_result);
if (find_account_result.is_success() && boost::algorithm::iequals (
exchange_a,
exchange_account))
matching_accounts.push_back(a);
}
// iii. finds the first account from ii that the user from i is authorized to trade
for (BTSUser const* u : matching_users){
std::vector<BTSAccount const*> user_auth_accounts;
find_user_trading_accounts (admin_data, u->id(), user_auth_accounts);
for (BTSAccount const* i : user_auth_accounts)
for (BTSAccount const* j : matching_accounts)
if(i->id() == j->id())
return std::pair<BTSAccount const*, BTSUser const*>(i,u);
}
return std::pair<const BTSAccount*, const BTSUser*>(nullptr, nullptr);
}
// for a given user finds the account permissions (if permissions are
// derived from the group, it traverses the group hierarcy to find the
// correct permissions.
@@ -995,16 +1167,26 @@ void AdminServiceUtils::validate_user_exchange_data (const bts::api::admin::BTSU
}
void AdminServiceUtils::get_md_entitlement_report(const AdminData& admin_data,
std::vector<MDEntitlementReportUnit>& entitlements){
for (const auto& user : admin_data.users()){
const CMEUserData* cme_data=AdminServiceUtils::get_user_cme_data(user,
admin_data);
if(cme_data!=nullptr){
for (const auto& cme_mic_data : cme_data->md_permissions()){
MDEntitlementReportUnit rv=get_cme_md_entitlement_unit(user,
cme_mic_data);
for (const auto& user : admin_data.users())
{
const CMEUserData* cme_data=AdminServiceUtils::get_user_cme_data(user, admin_data);
if(cme_data!=nullptr)
{
for (const auto& cme_mic_data : cme_data->md_permissions())
{
MDEntitlementReportUnit rv=get_cme_md_entitlement_unit(user, cme_mic_data);
entitlements.push_back(rv);
}
}
const ICEUserData* ice_data=AdminServiceUtils::get_user_ice_data(user, admin_data);
if(ice_data!=nullptr)
{
for (const auto& ice_mic_data : ice_data->md_permissions())
{
MDEntitlementReportUnit rv=get_ice_md_entitlement_unit(user, ice_mic_data);
entitlements.push_back(rv);
}
}
}
}
MDEntitlementReportUnit AdminServiceUtils::get_cme_md_entitlement_unit(
@@ -1052,6 +1234,22 @@ MDEntitlementReportUnit AdminServiceUtils::get_cme_md_entitlement_unit(
rv.set_record_id(key.str());
return rv;
}
MDEntitlementReportUnit AdminServiceUtils::get_ice_md_entitlement_unit(
const BTSUser& user,
const ICEMicData& ice_mic_data){
MDEntitlementReportUnit rv;
rv.set_user(user.name());
rv.set_user_id(user.id());
rv.set_exchange( bts::api::Venue_Name(bts::api::Venue::VENUE_ICE) );
rv.set_mic( bts::api::ICEMics_Name( ice_mic_data.mic()) );
rv.set_enabled(ice_mic_data.enabled());
std::ostringstream key;
key << rv.user() << rv.exchange() << rv.mic();
rv.set_record_id(key.str());
return rv;
}
void AdminServiceUtils::get_user_symbol_permissions(const AdminData& data,
const BTSUser& user,
std::vector<UserSymbolMDPermissionUnit>& rv){
@@ -1126,13 +1324,13 @@ void AdminServiceUtils::set_user_exchange_data(bts::api::admin::BTSUser* user,
if (!user->user_data().has_exchange_user_data())
user->mutable_user_data()->mutable_exchange_user_data()->CopyFrom(exchange_user_data);
}
void AdminServiceUtils::set_user_md_entitlement_data(bts::api::admin::BTSUser* user,
const bts::api::admin::ExchangeUserMarketDataEntitlementData& exchange_user_md_entitelemnt_data){
if (!user->has_user_data())
user->mutable_user_data();
if (!user->user_data().has_exchange_md_entitlement_data())
user->mutable_user_data()->mutable_exchange_md_entitlement_data()->CopyFrom(exchange_user_md_entitelemnt_data);
}
// void AdminServiceUtils::set_user_md_entitlement_data(bts::api::admin::BTSUser* user,
// const bts::api::admin::ExchangeUserMarketDataEntitlementData& exchange_user_md_entitelemnt_data){
// if (!user->has_user_data())
// user->mutable_user_data();
// if (!user->user_data().has_exchange_md_entitlement_data())
// user->mutable_user_data()->mutable_exchange_md_entitlement_data()->CopyFrom(exchange_user_md_entitelemnt_data);
// }
void AdminServiceUtils::clear_user_accounts (bts::api::admin::BTSUser* user){
if(user->has_user_data() && user->user_data().has_account_permissions())
user->mutable_user_data()->clear_account_permissions();
@@ -1377,6 +1575,7 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
auto account_1 = create_account(data, parent_account->id(), std::string("ACC A1"), std::string("description"), true, account_result); account_1->set_is_active(true);
auto account_2 = create_account(data, parent_account->id(), std::string("ACC A2"), std::string("description"), true, account_result); account_2->set_is_active(true);
auto account_3 = create_account(data, parent_account->id(), std::string("ACC A3"), std::string("description"), true, account_result); account_3->set_is_active(true);
auto account_4 = create_account(data, parent_account->id(), std::string("BLUETST"), std::string("description"), true, account_result); account_4->set_is_active(true);
create_account(data, parent_account->id(), std::string("ACC A4"), std::string("description"), true, account_result);
// add group
auto def_group = create_group(data, 0, std::string("default"), result);
@@ -1387,8 +1586,7 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
auto user_2 = create_user(data, def_group->id(), std::string("bts_2"), std::string("bts_2"), empty, empty, false, license_data, license_entitlements, user_result); user_2->set_is_active(true);
auto user_3 = create_user(data, def_group->id(), std::string("bts_3"), std::string("bts_3"), empty, empty, false, license_data, license_entitlements, user_result); user_3->set_is_active(true);
//associate users
bts::api::admin::UserAccountPermissionUnit permission_unit;
permission_unit.mutable_trading_permission()->set_submit_market_orders(true);
bts::api::admin::UserAccountPermissionUnit permission_unit;
permission_unit.mutable_trading_permission()->set_has_permissions(true);
permission_unit.mutable_admin_permission()->set_has_permissions(true);
bts::api::admin::UserAccountPermissions account_permissions;
@@ -1396,6 +1594,7 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
account_permissions.mutable_account_permissions()->insert(google::protobuf::MapPair<uint32_t, bts::api::admin::UserAccountPermissionUnit>(account_1->id(), permission_unit));
account_permissions.mutable_account_permissions()->insert(google::protobuf::MapPair<uint32_t, bts::api::admin::UserAccountPermissionUnit>(account_2->id(), permission_unit));
account_permissions.mutable_account_permissions()->insert(google::protobuf::MapPair<uint32_t, bts::api::admin::UserAccountPermissionUnit>(account_3->id(), permission_unit));
account_permissions.mutable_account_permissions()->insert(google::protobuf::MapPair<uint32_t, bts::api::admin::UserAccountPermissionUnit>(account_4->id(), permission_unit));
set_user_accounts(user_1, account_permissions);
set_user_accounts(user_2, account_permissions);
set_user_accounts(user_3, account_permissions);
@@ -1405,6 +1604,12 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
exchange_account_data.mutable_cme_account_data()->set_cti(bts::api::orderman::CTICode::CTI_CODE_CTI_CODE1);
exchange_account_data.mutable_cme_account_data()->set_origin(bts::api::orderman::CustomerOrFirm::CUSTOMER_OR_FIRM_FIRM);
exchange_account_data.mutable_cme_account_data()->set_clearing_account(parent_account->name());
exchange_account_data.mutable_ice_account_data()->set_cti(bts::api::orderman::CTICode::CTI_CODE_UNDEFINED);
exchange_account_data.mutable_ice_account_data()->set_origin(bts::api::orderman::CustomerOrFirm::CUSTOMER_OR_FIRM_FIRM);
exchange_account_data.mutable_ice_account_data()->set_clearing_account(parent_account->name());
exchange_account_data.mutable_ice_account_data()->set_clearing_firm("649");
exchange_account_data.mutable_sim_account_data()->set_cti(bts::api::orderman::CTICode::CTI_CODE_CTI_CODE1);
exchange_account_data.mutable_sim_account_data()->set_origin(bts::api::orderman::CustomerOrFirm::CUSTOMER_OR_FIRM_FIRM);
exchange_account_data.mutable_sim_account_data()->set_clearing_account(parent_account->name());
@@ -1412,33 +1617,87 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
exchange_account_data.mutable_cme_account_data()->set_clearing_account(account_1->name());
exchange_account_data.mutable_ice_account_data()->set_clearing_account(account_1->name());
exchange_account_data.mutable_sim_account_data()->set_clearing_account(account_1->name());
set_account_exchange_data(account_1, exchange_account_data);
exchange_account_data.mutable_cme_account_data()->set_clearing_account(account_2->name());
exchange_account_data.mutable_ice_account_data()->set_clearing_account(account_2->name());
exchange_account_data.mutable_sim_account_data()->set_clearing_account(account_2->name());
set_account_exchange_data(account_2, exchange_account_data);
exchange_account_data.mutable_cme_account_data()->set_clearing_account(account_3->name());
exchange_account_data.mutable_ice_account_data()->set_clearing_account(account_3->name());
exchange_account_data.mutable_sim_account_data()->set_clearing_account(account_3->name());
set_account_exchange_data(account_3, exchange_account_data);
exchange_account_data.mutable_ice_account_data()->set_clearing_account(account_4->name());
set_account_exchange_data(account_4, exchange_account_data);
// add cme and sim user data
bts::api::admin::ExchangeUserData exchange_user_data;
exchange_user_data.mutable_cme_data()->set_operator_id("op_id_" + user_1->name());
exchange_user_data.mutable_cme_data()->set_location("us,nc");
exchange_user_data.mutable_ice_data()->set_operator_id("op_id_" + user_1->name());
exchange_user_data.mutable_ice_data()->set_company_id(51251);
exchange_user_data.mutable_ice_data()->set_authorized_trader("bluetrd-fx");
exchange_user_data.mutable_ice_data()->set_authorized_group("Group");
exchange_user_data.mutable_ice_data()->set_password("Starts123");
exchange_user_data.mutable_ice_data()->set_mifid_direct_electronic_access(-1);
exchange_user_data.mutable_ice_data()->set_mifid_trading_capacity(-1);
exchange_user_data.mutable_ice_data()->set_mifid_liquidity_provision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_commodity_deriv_indicator(-1);
exchange_user_data.mutable_ice_data()->set_mifid_investment_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_execution_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_client_id_code(-1);
exchange_user_data.mutable_ice_data()->set_mifid_id(1);
exchange_user_data.mutable_sim_data()->set_operator_id("op_id_" + user_1->name());
exchange_user_data.mutable_sim_data()->set_location("us,nc");
set_user_exchange_data(user_1, exchange_user_data);
exchange_user_data.mutable_cme_data()->set_operator_id("op_id_" + user_2->name());
exchange_user_data.mutable_cme_data()->set_location("us,nc");
exchange_user_data.mutable_ice_data()->set_operator_id("op_id_" + user_2->name());
exchange_user_data.mutable_ice_data()->set_company_id(51251);
exchange_user_data.mutable_ice_data()->set_authorized_trader("bluetrd-fx");
exchange_user_data.mutable_ice_data()->set_authorized_group("Group");
exchange_user_data.mutable_ice_data()->set_password("Starts123");
exchange_user_data.mutable_ice_data()->set_mifid_direct_electronic_access(-1);
exchange_user_data.mutable_ice_data()->set_mifid_trading_capacity(-1);
exchange_user_data.mutable_ice_data()->set_mifid_liquidity_provision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_commodity_deriv_indicator(-1);
exchange_user_data.mutable_ice_data()->set_mifid_investment_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_execution_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_client_id_code(-1);
exchange_user_data.mutable_ice_data()->set_mifid_id(1);
exchange_user_data.mutable_sim_data()->set_operator_id("op_id_" + user_2->name());
exchange_user_data.mutable_sim_data()->set_location("us,nc");
set_user_exchange_data(user_2, exchange_user_data);
exchange_user_data.mutable_cme_data()->set_operator_id("op_id_" + user_3->name());
exchange_user_data.mutable_cme_data()->set_location("us,nc");
exchange_user_data.mutable_ice_data()->set_operator_id("op_id_" + user_3->name());
exchange_user_data.mutable_ice_data()->set_company_id(51251);
exchange_user_data.mutable_ice_data()->set_authorized_trader("bluetrd-fx");
exchange_user_data.mutable_ice_data()->set_authorized_group("Group");
exchange_user_data.mutable_ice_data()->set_password("Starts123");
exchange_user_data.mutable_ice_data()->set_mifid_direct_electronic_access(-1);
exchange_user_data.mutable_ice_data()->set_mifid_trading_capacity(-1);
exchange_user_data.mutable_ice_data()->set_mifid_liquidity_provision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_commodity_deriv_indicator(-1);
exchange_user_data.mutable_ice_data()->set_mifid_investment_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_execution_decision(-1);
exchange_user_data.mutable_ice_data()->set_mifid_client_id_code(-1);
exchange_user_data.mutable_ice_data()->set_mifid_id(1);
exchange_user_data.mutable_sim_data()->set_operator_id("op_id_" + user_3->name());
exchange_user_data.mutable_sim_data()->set_location("us,nc");
set_user_exchange_data(user_3, exchange_user_data);
@@ -1480,6 +1739,13 @@ void AdminServiceUtils::bootstrap_data (bts::api::admin::AdminData& data){
add_security_clip_sizes_to_account(account_1, api::Venue::VENUE_GLBX, api::SecurityType::SECURITYTYPE_SPREAD,100);
add_security_clip_sizes_to_account(account_1, api::Venue::VENUE_SIM, api::SecurityType::SECURITYTYPE_FUTURE,100);
add_security_clip_sizes_to_account(account_1, api::Venue::VENUE_SIM, api::SecurityType::SECURITYTYPE_SPREAD,100);
//ICE limits
add_product_position_limits(account_4, api::Venue::VENUE_ICE, api::SecurityType::SECURITYTYPE_FUTURE,50000);
add_product_position_limits(account_4, api::Venue::VENUE_ICE, api::SecurityType::SECURITYTYPE_SPREAD,50000);
add_security_clip_sizes_to_account(account_4, api::Venue::VENUE_ICE, api::SecurityType::SECURITYTYPE_FUTURE,50);
add_security_clip_sizes_to_account(account_4, api::Venue::VENUE_ICE, api::SecurityType::SECURITYTYPE_SPREAD,50);
}
bool AdminServiceUtils::has_id (uint32_t id){return id>0;}
bool AdminServiceUtils::is_symbol_set (const std::string& symbol){
@@ -35,6 +35,10 @@ public:
const AdminData& data,
const BTSAccount& account,
const api::Security& sec);
static const ExchangeConnection* resolve_ice_connection(
const AdminData& data,
const BTSAccount& account,
const api::Security& sec);
static const ExchangeConnection* resolve_sim_connection(
const AdminData& data,
const BTSAccount& account,
@@ -164,6 +168,8 @@ public:
// travels up the group tree until it finds a populated cme data
static const CMEUserData* get_group_cme_data(const BTSUserGroup& group,
const AdminData& data);
static const ICEUserData* get_group_ice_data(const BTSUserGroup& group,
const AdminData& data);
static const SIMUserData* get_group_sim_data(const BTSUserGroup& group,
const AdminData& data);
static const UserAccountPermissions* const get_group_user_permissions (
@@ -198,6 +204,8 @@ public:
static uint32_t find_max_user_id (const AdminData& data);
static const CMEUserData* get_user_cme_data(const BTSUser& user,
const AdminData& data);
static const ICEUserData* get_user_ice_data(const BTSUser& user,
const AdminData& data);
static const SIMUserData* get_user_sim_data(const BTSUser& user,
const AdminData& data);
// finds the "exchange user" (ex: "operator_id" at CME or "authorized_trader"
@@ -207,6 +215,15 @@ public:
const BTSUser& user,
api::Venue exchange,
AdminServiceOperationResult& out_result);
// i. uses the exchange and exchange_user to reverse lookup the user(s)
// ii. uses the exchange, connection and exchange_account to reverse lookup the account(s)
// iii. finds the first account from ii that a user from i is authorized to trade
static std::string find_user_company_id (
const AdminData& data,
const BTSUser& user,
api::Venue exchange,
AdminServiceOperationResult& out_result);
static std::pair<const BTSAccount*, const BTSUser*>
find_user_account_matches (const AdminData& admin_data,
const std::string& connection,
@@ -246,6 +263,9 @@ public:
static MDEntitlementReportUnit get_cme_md_entitlement_unit(
const BTSUser& user,
const CMEMicData& cme_mic_data);
static MDEntitlementReportUnit get_ice_md_entitlement_unit(
const BTSUser& user,
const ICEMicData& ice_mic_data);
static void get_user_symbol_permissions(
const AdminData& data,
const BTSUser& user,
@@ -272,8 +292,6 @@ public:
static void set_user_exchange_data(
BTSUser* user,
const ExchangeUserData& exchange_user_data);
static void set_user_md_entitlement_data(BTSUser* user,
const ExchangeUserMarketDataEntitlementData&);
static void clear_user_accounts (BTSUser* user);
static void set_user_accounts (BTSUser* user,
const UserAccountPermissions& user_account_permissions);
+100 -92
View File
@@ -55,11 +55,12 @@ message BTSUser{
string name = 30;
string password = 40;
string full_name = 42;
string company = 44;
string company = 44;
bool is_active = 50;
bool can_create = 55;
LicenseData license_data = 60; //unused
LicenseEntitlements license_entitlements = 70; //unused
LicenseData license_data = 60;
LicenseEntitlements license_entitlements = 70;
BTSUserDerivableData user_data = 80;
}
@@ -76,7 +77,7 @@ message BTSUserDerivableData{
// b. else its overridden at the user level
UserAccountPermissions account_permissions = 70;
ExchangeUserData exchange_user_data = 80;
ExchangeUserMarketDataEntitlementData exchange_md_entitlement_data = 90;
reserved 90; reserved "exchange_md_entitlement_data"; //ExchangeUserMarketDataEntitlementData exchange_md_entitlement_data = 90;
}
message LicenseData{
@@ -91,21 +92,22 @@ message LicenseEntitlements{
bool spreader = 30;
}
message AlgoTradingPermissionsUnit{
bool submit_iceberg_orders = 10; //unused
bool submit_time_box_orders = 20; //unused
bool submit_spreader_orders = 30; //unused
}
// message AlgoTradingPermissionsUnit{
// bool submit_iceberg_orders = 10; //unused
// bool submit_time_box_orders = 20; //unused
// bool submit_spreader_orders = 30; //unused
// }
message TradingPermissionUnit{
reserved 10; reserved "submit_market_orders"; //bool submit_market_orders = 10; //unused
reserved 20; reserved "submit_gtc_orders"; //bool submit_gtc_orders = 20; //unused
reserved 30; reserved "algo_trading_permission"; //AlgoTradingPermissionsUnit algo_trading_permission = 30; //unused
bool has_permissions = 5;
bool submit_market_orders = 10; //unused
bool submit_gtc_orders = 20; //unused
AlgoTradingPermissionsUnit algo_trading_permission = 30; //unused
}
message AdminPermissionUnit{
// TODO: needs to be more ellaborate (account writing,
// TODO: needs to be more ellaborate (account writing,
// reading etc, routing etc)
bool has_permissions = 10;
bool has_md_permissions = 20;
@@ -119,15 +121,15 @@ message UserAccountPermissionUnit{
message UserAccountPermissions{
//uint32 = account_id
map<uint32, UserAccountPermissionUnit> account_permissions = 10;
map<uint32, UserAccountPermissionUnit> account_permissions = 10;
}
// unused now
message UserSecurityTradingLimit{
SecurityScope security = 10;
uint32 clip_size = 20;
bool can_trade = 30;
}
// // unused now
// message UserSecurityTradingLimit{
// SecurityScope security = 10;
// uint32 clip_size = 20;
// bool can_trade = 30;
// }
/************************************************************************/
/********************************BTS Account*****************************/
@@ -152,7 +154,7 @@ message BTSAccount{
AccountLossLimit account_loss_limit = 130;
}
message RiskLimitEnforcement{
message RiskLimitEnforcement{
bool product_limit_in_net_terms = 10;
bool ignore_spread_position_limits = 20;
}
@@ -204,23 +206,22 @@ message AccountLossLimit{
message CMEMicData{
api.CMEMics mic=10;
bool enabled=20;
// there are other things here
// there are other things here
}
message ICEMicData{
api.CMEMics mic=10;
api.ICEMics mic=10;
bool enabled=20;
}
message ExchangeUserMarketDataEntitlementData{
CMEUserMarketDataEntitlementData cme_data = 10;
ICEUserMarketDataEntitlementData ice_data = 20;
}
message ExchangeUserData{
CMEUserData cme_data = 10;
ICEUserData ice_data = 20;
SIMUserData sim_data = 30;
enum AdminDisplay { All = 0; MD = 1; Routing = 2; None = 100; }
AdminDisplay admin_display_flag = 120;
}
message ExchangeAccountData{
@@ -229,9 +230,6 @@ message ExchangeAccountData{
SIMAccountData sim_account_data = 30;
}
message MarketDataEntitlement{
bool can_view = 10;
}
message ExchangeConnection{
uint32 id = 10;
@@ -274,19 +272,19 @@ message CMEMSGWConnection{
uint32 market_segment_id = 60;
}
message CMEAccountData{
// should perhaps be an enum
message CMEAccountData {
reserved 30; reserved "takeup_member_code"; //string takeup_member_code = 30;
reserved 50; reserved "direct_electronic_access"; //string direct_electronic_access = 50;
reserved 60; reserved "trading_capacity"; //string trading_capacity = 60;
reserved 70; reserved "liquidity_provision"; //string liquidity_provision = 70;
reserved 80; reserved "commodity_derivative_indicator"; //string commodity_derivative_indicator = 80;
reserved 90; reserved "investment_decision_id"; //string investment_decision_id = 90;
reserved 100; reserved "execution_decision_id"; //string execution_decision_id = 100;
reserved 110; reserved "client_id"; //string client_id = 110;
api.orderman.CTICode cti = 10;
api.orderman.CustomerOrFirm origin = 20;
string takeup_member_code = 30;
string clearing_account = 40;
string direct_electronic_access = 50;
string trading_capacity = 60;
string liquidity_provision = 70;
string commodity_derivative_indicator = 80;
string investment_decision_id = 90;
string execution_decision_id = 100;
string client_id = 110;
map<string, string> misc_tags = 120;
}
@@ -309,21 +307,22 @@ enum DisplayDesignation
}
message CMEUserData{
reserved 20; reserved "ats_operator_id"; //string ats_operator_id = 20;
reserved 40; reserved "text_a"; //string text_a = 40;
reserved 50; reserved "text_b"; //string text_b = 50;
reserved 80; reserved "max_order_rate_per_connection"; //string max_order_rate_per_connection = 80;
//enum AdminDisplay { All = 0; MD = 1; Routing = 2; None = 100; }
reserved 120; reserved "admin_display_flag"; //AdminDisplay admin_display_flag = 120;
repeated CMEMicData md_permissions = 1000;
string operator_id = 10;
string ats_operator_id = 20;
string smp_id = 30;
string text_a = 40;
string text_b = 50;
map<string, string> misc_tags = 60;
string smp_instruction = 70;
string max_order_rate_per_connection = 80;
string location = 90;
ProfessionalDesignation pro_nonpro = 100;
DisplayDesignation display_nondisplay = 110;
enum AdminDisplay { All = 0; MD = 1; Routing = 2; None = 100; }
AdminDisplay admin_display_flag = 120;
repeated CMEMicData md_permissions = 1000;
}
message SIMUserData {
@@ -331,58 +330,67 @@ message SIMUserData {
string location = 90;
}
message CMEUserMarketDataEntitlementData{
MarketDataEntitlement cbot_entitlement = 10;
MarketDataEntitlement cme_entitlement = 20;
MarketDataEntitlement nymex_entitlement = 30;
MarketDataEntitlement bmandf_entitlement = 40;
MarketDataEntitlement comex_entitlement = 50;
MarketDataEntitlement cme_europe_entitlement = 60;
}
/********************************ICE Data*********************************/
message ICEConnection{
string authorized_member_id = 10;
string sender_company_id = 20;
string sender_sub_id = 30;
string session_id = 40;
string session_password = 50;
string host_ip = 60;
string port = 70;
string default_routing_trader = 80;
string routing_trader_password = 90;
int32 max_order_rate = 100;
message ICEConnection {
string sender_compid = 10;
}
message ICEAccountData{
string nybit_house = 10;
int32 wce_house = 20;
string clearing_account_override = 30;
bool direct_electronic_access = 40;
string trading_capacity = 50;
bool liquidity_provision = 60;
bool commodity_derivative_indicator = 70;
string investment_decision_id = 80;
string execution_decision_id = 90;
string client_id = 100;
string mfid_id = 110;
message ICEAccountData {
reserved 10; reserved "nybit_house"; //string nybit_house = 10;
reserved 20; reserved "wce_house"; //int32 wce_house = 20;
reserved 30; reserved "clearing_account_override"; //string clearing_account_override = 30;
reserved 40; reserved "direct_electronic_access"; //bool direct_electronic_access = 40;
reserved 50; reserved "trading_capacity"; //string trading_capacity = 50;
reserved 60; reserved "liquidity_provision"; //bool liquidity_provision = 60;
reserved 70; reserved "commodity_derivative_indicator"; //bool commodity_derivative_indicator = 70;
reserved 80; reserved "investment_decision_id"; //string investment_decision_id = 80;
reserved 90; reserved "execution_decision_id"; //string execution_decision_id = 90;
reserved 100; reserved "client_id"; //string client_id = 100;
reserved 110; reserved "mfid_id"; //string mfid_id = 110;
api.orderman.CTICode cti = 3;
api.orderman.CustomerOrFirm origin = 5;
string clearing_firm = 200;
string clearing_account = 210;
string customer_account_ref_id = 220;
string account_code = 230;
map<string, string> misc_tags = 500;
}
message ICEUserData{
string authorized_trader = 10;
string memo_field = 20;
string text_b = 30;
uint32 max_order_rate = 40;
}
message ICEUserData {
reserved 20; reserved "memo_field"; //string memo_field = 20;
reserved 30; reserved "text_b"; //string text_b = 30;
reserved 40; reserved "max_order_rate"; //uint32 max_order_rate = 40;
message ICEUserMarketDataEntitlementData{
int32 company_id = 3; //tag 109 clientid
string operator_id = 5; //tag 50
string authorized_trader = 10; //tag 553 user_name
string authorized_group = 15; //tag 553 user_name
string password = 21; //tag 96 raw data
string cust_order_handing_inst = 25;
//mifid
int32 mifid_direct_electronic_access = 500;
int32 mifid_trading_capacity = 510;
int32 mifid_liquidity_provision = 520;
int32 mifid_commodity_deriv_indicator = 530;
int64 mifid_investment_decision = 540;
int64 mifid_execution_decision = 550;
int64 mifid_client_id_code = 560;
int64 mifid_id = 570;
map<string, string> misc_tags = 60;
ProfessionalDesignation pro_nonpro = 100;
DisplayDesignation display_nondisplay = 110;
repeated ICEMicData md_permissions = 1000;
}
///////////////////////////////////////////////////////////
// Order Auxiliary Service ////////////////////////////////
message OrdersSummaryUnit{
message OrdersSummaryUnit{
string account = 10;
string user = 20;
uint32 total_orders = 30;
@@ -393,11 +401,11 @@ message OrdersSummary{
}
message OrderSummaryRequest{
}
// top level orders that have account
// top level orders that have account
// and user that are present here, will
// be cancelled. wild cards are not
// supported.
message OrderCancelRequest{
message OrderCancelRequest{
repeated string accounts = 10;
repeated string users = 20;
}
@@ -433,7 +441,7 @@ message AccountCreateAPIArgument{
string creator_user = 40;
}
message AccountUpdateAPIArgument{
BTSAccount complete_data=10;
BTSAccount complete_data=10;
}
message UserCreateAPIArgument{
uint32 parent_group_id = 20;
@@ -477,7 +485,7 @@ service AdminService {
// users
rpc create_user(UserCreateAPIArgument) returns (AdminServiceCreateEntityResult);
rpc update_user(UserUpdateAPIArgument) returns (AdminServiceOperationResult);
rpc delete_user(IDAPIArgument) returns (AdminServiceOperationResult);
rpc delete_user(IDAPIArgument) returns (AdminServiceOperationResult);
// subscription
rpc admin_data(bts.api.VoidMessage) returns (stream AdminData);
rpc get_admin_data(bts.api.VoidMessage) returns (AdminData);
+3
View File
@@ -57,4 +57,7 @@ service AuthService {
rpc get_users(GetUsersRequest) returns (GetUsersResponse)
{option (bts.api.method_description)="Returns list of valid users";}
rpc clear_all_sessions(bts.api.VoidMessage) returns (bts.api.ResultMessage)
{option (bts.api.method_description)="Clears all reserved auth sessions";}
}
@@ -4,6 +4,11 @@ option csharp_namespace="bts.support";
import "lib/api/apioptions.proto";
import "google/protobuf/timestamp.proto";
message FileData {
string name = 1;
bytes contents = 2;
}
message ErrorReport {
google.protobuf.Timestamp timestamp = 1;
string user = 2;
@@ -13,6 +18,7 @@ message ErrorReport {
string log = 6;
bytes image = 7;
string contact = 8;
repeated FileData files = 9;
}
message ErrorResponse {
}
+18
View File
@@ -310,6 +310,13 @@ message Fill {
FILL_KIND_SOD = 2;
}
FillKind fill_kind = 10;
enum FillStatus {
FILL_STATUS_ACTIVE = 0;
FILL_STATUS_CORRECTED = 1;
FILL_STATUS_BUSTED = 2;
}
FillStatus fill_status = 20;
}
enum OrderSubType {
@@ -327,6 +334,17 @@ message RoutingRecord {
string smp_id = 6 ;
SelfMatchPreventionInstruction smp_instruction = 7;
string location = 8;
string cust_order_handling_inst = 9;
string sender_compid = 15;
string clearing_firm = 20;
string customer_account_ref_id = 25;
string account_code = 30;
string company_id = 45;
string authorized_trader = 50;
string authorized_group = 60;
string cust_order_handing_inst = 70;
string order_server_id = 200;
}
message NativeOrderState {
+2
View File
@@ -24,6 +24,7 @@
#include <map>
#include <tuple>
#define URDL_HEADER_ONLY 1
#define URDL_DISALE_SSL 1
#include <urdl/url.hpp>
@@ -908,3 +909,4 @@ std::string get_fallback(const proto::Message& message)
}
}}}//end namespaces
+35 -6
View File
@@ -62,15 +62,44 @@ ICEOptions {
value {
channel {
name: "oil" #these names are arbitrary and are for debugging
market_type: 3
uds_market_type: 3
market_type: 4 #ICE IPE Gas Oil Futures
uds_market_type: 4
market_type: 5 #ICE Futures Brent, IPE Brent Futures
market_type: 9 #ICE Futures WTI, ICE WTI Crude Futures
#udp_buffer_size: 33554432 #32mb
}
channel {
name: "juice"
market_type: 23 #ICE Futures US Agricultures, FCOJ A
uds_market_type: 5
market_type: 9 #ICE Futures WTI, ICE WTI Crude Futures
uds_market_type: 9
market_type: 13 #ICE Heating Oil Futures
uds_market_type: 13
market_type: 15 #ICE NYH (RBOB) Gasoline Futures
uds_market_type: 15
##market_type: 21 #ICE Futures US Agricultures, Coffee C
##uds_market_type: 21
##market_type: 23 #ICE Futures US Agricultures, FCOJ A
##uds_market_type: 23
##market_type: 26 #ICE Futures US Financials DX
##uds_market_type: 26
uds_market_type: 11 #ICE WTI-Brent spreads
uds_market_type: 14 #ICE Heating Oil/WTI Futures Crack
uds_market_type: 16 #ICE NYH (RBOB) Gasoline/WTI Futures Crack
uds_market_type: 58 #ICE Futures UI Heating Oil / Brent
uds_market_type: 59 #ICE NYH (RBOB) Gasoline/Brent Futures Crack
uds_market_type: 66 #ICE NYH (RBOB) Gasoline/Heating Oil Spread
uds_market_type: 70 #ICE Heating Oil/LS Gasoil Futures Spread
uds_market_type: 71 #ICE LS Gasoil/Brent Futures Crack
uds_market_type: 72 #ICE NYH (RBOB) Gasoline/LS Gasoil Futures Spread
#onixs_log_mode: Debug
}
# channel {
# name: "juice"
# market_type: 26 #ICE Futures US Agricultures, FCOJ A
# }
ice_config_file: "ConnectivityConfiguration.APITest.xml"
#ice_config_file: "ConnectivityConfiguration.PerfTest.xml"
}
}
+2 -1
View File
@@ -3,7 +3,8 @@ Ports {
value {
config_port: 8000
qbus_port: 8001
exchange_sim_fix_port: 8002
glbx_sim_fix_port: 8002
ice_sim_fix_port: 8003
replicator_port: 8080
}
}
+14 -4
View File
@@ -19,7 +19,6 @@ SymbolList {
symbol: "FOB"
symbol: "GC"
symbol: "GE"
symbol: "GLI"
symbol: "HE"
symbol: "HG"
symbol: "HO"
@@ -66,9 +65,16 @@ SymbolLists
list
{
key: "ICE"
# symbol: "BRN"
# symbol: "WBS"
# symbol: "OJ"
symbol: "BRN"
symbol: "WBS"
symbol: "OJ"
symbol: "G"
symbol: "KC"
symbol: "UHO"
symbol: "UHU"
symbol: "DX"
symbol: "*"
}
list
{
@@ -112,5 +118,9 @@ Symbols {
future: @SymbolLists.list[ICE].symbol
spread: @SymbolLists.list[ICE].symbol
}
simice {
future: @SymbolLists.list[ICE].symbol
spread: @SymbolLists.list[ICE].symbol
}
}
}
+52 -50
View File
@@ -3,9 +3,9 @@
# source: tools/cpp_helper/generate-cpps.ps1
#
CppConfig
{
value
CppConfig
{
value
{
cpp_entry { key: "098" value: 2000 }
cpp_entry { key: "0A" value: 100 }
@@ -354,6 +354,7 @@ CppConfig
cpp_entry { key: "BOB" value: 1000 }
cpp_entry { key: "BOO" value: 6350 }
cpp_entry { key: "BOS" value: 250 }
cpp_entry { key: "BPU" value: 1000 }
cpp_entry { key: "BR7" value: 1000 }
cpp_entry { key: "BSF" value: 25 }
cpp_entry { key: "BTC" value: 5 }
@@ -442,12 +443,12 @@ CppConfig
cpp_entry { key: "D3L" value: 80 }
cpp_entry { key: "D4L" value: 5 }
cpp_entry { key: "D7L" value: 80 }
cpp_entry { key: "DAB" value: 1000 }
cpp_entry { key: "DAX" value: 5 }
cpp_entry { key: "DAZ" value: 80 }
cpp_entry { key: "DBB" value: 1000 }
cpp_entry { key: "DBI" value: 1000 }
cpp_entry { key: "DBL" value: 100 }
cpp_entry { key: "DBR" value: 1000 }
cpp_entry { key: "DBT" value: 100 }
cpp_entry { key: "DC" value: 2000 }
cpp_entry { key: "DCB" value: 1000 }
@@ -458,14 +459,13 @@ CppConfig
cpp_entry { key: "DDE" value: 1000 }
cpp_entry { key: "DDI" value: 1000 }
cpp_entry { key: "DDO" value: 1000 }
cpp_entry { key: "DEB" value: 744 }
cpp_entry { key: "DEB" value: 720 }
cpp_entry { key: "DEN" value: 250 }
cpp_entry { key: "DEP" value: 264 }
cpp_entry { key: "DEP" value: 252 }
cpp_entry { key: "DFL" 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 }
cpp_entry { key: "DGI" value: 100 }
cpp_entry { key: "DGS" value: 100 }
cpp_entry { key: "DGT" value: 100 }
@@ -473,19 +473,13 @@ CppConfig
cpp_entry { key: "DHI" value: 1000 }
cpp_entry { key: "DJR" value: 100 }
cpp_entry { key: "DKR" value: 1000 }
cpp_entry { key: "DMB" value: 100 }
cpp_entry { key: "DOB" value: 1000 }
cpp_entry { key: "DOP" value: 1000 }
cpp_entry { key: "DRB" value: 1000 }
cpp_entry { key: "DRI" value: 100 }
cpp_entry { key: "DRS" value: 100 }
cpp_entry { key: "DRT" value: 100 }
cpp_entry { key: "DSD" value: 1000 }
cpp_entry { key: "DSE" value: 1000 }
cpp_entry { key: "DSG" value: 1000 }
cpp_entry { key: "DTR" value: 2 }
cpp_entry { key: "DTT" value: 2 }
cpp_entry { key: "DUA" value: 6350 }
cpp_entry { key: "DUP" value: 1000 }
cpp_entry { key: "DVE" value: 200 }
cpp_entry { key: "DVT" value: 200 }
@@ -530,8 +524,11 @@ CppConfig
cpp_entry { key: "EP1" value: 1000 }
cpp_entry { key: "EPN" value: 1000 }
cpp_entry { key: "EPZ" value: 500000 }
cpp_entry { key: "EQ1" value: 50 }
cpp_entry { key: "ERL" value: 5 }
cpp_entry { key: "ES" value: 50 }
cpp_entry { key: "ES1" value: 50 }
cpp_entry { key: "ES2" value: 50 }
cpp_entry { key: "ESB" value: 1000 }
cpp_entry { key: "ESK" value: 125000 }
cpp_entry { key: "ESQ" value: 50 }
@@ -733,8 +730,8 @@ CppConfig
cpp_entry { key: "IPO" value: 10 }
cpp_entry { key: "IPT" value: 10 }
cpp_entry { key: "IS" value: 50 }
cpp_entry { key: "ITB" value: 744 }
cpp_entry { key: "ITP" value: 264 }
cpp_entry { key: "ITB" value: 720 }
cpp_entry { key: "ITP" value: 252 }
cpp_entry { key: "IW" value: 50 }
cpp_entry { key: "J4L" value: 80 }
cpp_entry { key: "J7" value: 6250000 }
@@ -748,7 +745,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: 480 }
cpp_entry { key: "JML" value: 240 }
cpp_entry { key: "JNC" value: 1000 }
cpp_entry { key: "JNG" value: 10000 }
cpp_entry { key: "JNL" value: 80 }
@@ -776,6 +773,7 @@ CppConfig
cpp_entry { key: "K5" value: 20 }
cpp_entry { key: "K5K" value: 20 }
cpp_entry { key: "K5N" value: 20 }
cpp_entry { key: "KC" value: 375 }
cpp_entry { key: "KE" value: 50 }
cpp_entry { key: "KET" value: 50 }
cpp_entry { key: "KQ" value: 20 }
@@ -1005,6 +1003,7 @@ CppConfig
cpp_entry { key: "OAD" value: 1 }
cpp_entry { key: "ODO" value: 1000 }
cpp_entry { key: "OFF" value: 5 }
cpp_entry { key: "OJ" value: 150 }
cpp_entry { key: "OML" value: 5 }
cpp_entry { key: "OMM" value: 80 }
cpp_entry { key: "OOD" value: 5 }
@@ -1147,7 +1146,7 @@ CppConfig
cpp_entry { key: "SBT" value: 50 }
cpp_entry { key: "SD" value: 1000 }
cpp_entry { key: "SDA" value: 250 }
cpp_entry { key: "SDD" value: 1760 }
cpp_entry { key: "SDD" value: 1600 }
cpp_entry { key: "SDG" value: 250 }
cpp_entry { key: "SDI" value: 1000 }
cpp_entry { key: "SDM" value: 100 }
@@ -1186,7 +1185,7 @@ CppConfig
cpp_entry { key: "SR3" value: 2500 }
cpp_entry { key: "SR5" value: 1000 }
cpp_entry { key: "SRB" value: 1000 }
cpp_entry { key: "SRT" value: 1760 }
cpp_entry { key: "SRT" value: 1600 }
cpp_entry { key: "SSI" value: 1000 }
cpp_entry { key: "SSP" value: 5000 }
cpp_entry { key: "SSW" value: 1000 }
@@ -1197,27 +1196,28 @@ CppConfig
cpp_entry { key: "STY" value: 1000 }
cpp_entry { key: "SU" value: 250 }
cpp_entry { key: "SUT" value: 250 }
cpp_entry { key: "T01" value: 800 }
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: "T10" value: 800 }
cpp_entry { key: "T11" value: 800 }
cpp_entry { key: "T12" value: 800 }
cpp_entry { key: "T13" value: 800 }
cpp_entry { key: "T14" value: 800 }
cpp_entry { key: "T15" value: 800 }
cpp_entry { key: "T16" value: 800 }
cpp_entry { key: "T17" value: 800 }
cpp_entry { key: "T18" 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: "T22" value: 800 }
cpp_entry { key: "T23" value: 800 }
cpp_entry { key: "T24" value: 800 }
cpp_entry { key: "T25" 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 }
@@ -1276,7 +1276,7 @@ CppConfig
cpp_entry { key: "TT" value: 50000 }
cpp_entry { key: "TTD" value: 24 }
cpp_entry { key: "TTE" value: 10000 }
cpp_entry { key: "TTF" value: 744 }
cpp_entry { key: "TTF" value: 720 }
cpp_entry { key: "TUB" value: 1000 }
cpp_entry { key: "TUF" value: 1000 }
cpp_entry { key: "TUL" value: 1000 }
@@ -1295,12 +1295,11 @@ CppConfig
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: "UFV" value: 100 }
cpp_entry { key: "UGG" value: 42000 }
cpp_entry { key: "UKG" value: 310 }
cpp_entry { key: "UKG" value: 300 }
cpp_entry { key: "ULB" value: 42000 }
cpp_entry { key: "UMB" value: 1000 }
cpp_entry { key: "UMD" value: 1000 }
@@ -1308,6 +1307,9 @@ CppConfig
cpp_entry { key: "UN" value: 1000 }
cpp_entry { key: "UNB" value: 1000 }
cpp_entry { key: "UNS" value: 1000 }
cpp_entry { key: "UP5" value: 1000 }
cpp_entry { key: "UPB" value: 1000 }
cpp_entry { key: "UPM" value: 1000 }
cpp_entry { key: "UR" value: 1000 }
cpp_entry { key: "USC" value: 1000 }
cpp_entry { key: "USDBRL" value: 1 }
@@ -1455,12 +1457,12 @@ CppConfig
cpp_entry { key: "ZT" value: 2000 }
cpp_entry { key: "ZW" value: 50 }
cpp_entry { key: "ZWT" value: 50 }
}
}
}
}
CmeSymbolMics
{
value
CmeSymbolMics
{
value
{
cme_mic { key: "098" value: CBT }
cme_mic { key: "0A" value: NYMEX }
@@ -1809,6 +1811,7 @@ CmeSymbolMics
cme_mic { key: "BOB" value: CBT }
cme_mic { key: "BOO" value: NYMEX }
cme_mic { key: "BOS" value: CME }
cme_mic { key: "BPU" value: NYMEX }
cme_mic { key: "BR7" value: NYMEX }
cme_mic { key: "BSF" value: CBT }
cme_mic { key: "BTC" value: CME }
@@ -1897,12 +1900,12 @@ CmeSymbolMics
cme_mic { key: "D3L" value: NYMEX }
cme_mic { key: "D4L" value: NYMEX }
cme_mic { key: "D7L" value: NYMEX }
cme_mic { key: "DAB" value: NYMEX }
cme_mic { key: "DAX" value: NYMEX }
cme_mic { key: "DAZ" value: NYMEX }
cme_mic { key: "DBB" value: NYMEX }
cme_mic { key: "DBI" value: DME }
cme_mic { key: "DBL" value: NYMEX }
cme_mic { key: "DBR" value: DME }
cme_mic { key: "DBT" value: NYMEX }
cme_mic { key: "DC" value: CME }
cme_mic { key: "DCB" value: NYMEX }
@@ -1920,7 +1923,6 @@ CmeSymbolMics
cme_mic { key: "DFN" value: CBT }
cme_mic { key: "DG2" value: CBT }
cme_mic { key: "DG3" value: CBT }
cme_mic { key: "DGH" value: DME }
cme_mic { key: "DGI" value: CBT }
cme_mic { key: "DGS" value: CBT }
cme_mic { key: "DGT" value: CBT }
@@ -1928,19 +1930,13 @@ CmeSymbolMics
cme_mic { key: "DHI" value: DME }
cme_mic { key: "DJR" value: CBT }
cme_mic { key: "DKR" value: DME }
cme_mic { key: "DMB" value: DME }
cme_mic { key: "DOB" value: DME }
cme_mic { key: "DOP" value: DME }
cme_mic { key: "DRB" value: DME }
cme_mic { key: "DRI" value: CBT }
cme_mic { key: "DRS" value: CBT }
cme_mic { key: "DRT" value: CBT }
cme_mic { key: "DSD" value: DME }
cme_mic { key: "DSE" value: DME }
cme_mic { key: "DSG" value: DME }
cme_mic { key: "DTR" value: CBT }
cme_mic { key: "DTT" value: CBT }
cme_mic { key: "DUA" value: DME }
cme_mic { key: "DUP" value: DME }
cme_mic { key: "DVE" value: CME }
cme_mic { key: "DVT" value: CME }
@@ -1985,8 +1981,11 @@ CmeSymbolMics
cme_mic { key: "EP1" value: NYMEX }
cme_mic { key: "EPN" value: NYMEX }
cme_mic { key: "EPZ" value: CME }
cme_mic { key: "EQ1" value: CME }
cme_mic { key: "ERL" value: NYMEX }
cme_mic { key: "ES" value: CME }
cme_mic { key: "ES1" value: CME }
cme_mic { key: "ES2" value: CME }
cme_mic { key: "ESB" value: NYMEX }
cme_mic { key: "ESK" value: CME }
cme_mic { key: "ESQ" value: CME }
@@ -2652,27 +2651,28 @@ CmeSymbolMics
cme_mic { key: "STY" value: NYMEX }
cme_mic { key: "SU" value: CME }
cme_mic { key: "SUT" value: CME }
cme_mic { key: "T01" value: NYMEX }
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: "T10" value: NYMEX }
cme_mic { key: "T11" value: NYMEX }
cme_mic { key: "T12" value: NYMEX }
cme_mic { key: "T13" value: NYMEX }
cme_mic { key: "T14" value: NYMEX }
cme_mic { key: "T15" value: NYMEX }
cme_mic { key: "T16" value: NYMEX }
cme_mic { key: "T17" value: NYMEX }
cme_mic { key: "T18" 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: "T22" value: NYMEX }
cme_mic { key: "T23" value: NYMEX }
cme_mic { key: "T24" value: NYMEX }
cme_mic { key: "T25" 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 }
@@ -2750,7 +2750,6 @@ CmeSymbolMics
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: "UFV" value: CBT }
@@ -2763,6 +2762,9 @@ CmeSymbolMics
cme_mic { key: "UN" value: NYMEX }
cme_mic { key: "UNB" value: NYMEX }
cme_mic { key: "UNS" value: NYMEX }
cme_mic { key: "UP5" value: NYMEX }
cme_mic { key: "UPB" value: NYMEX }
cme_mic { key: "UPM" value: NYMEX }
cme_mic { key: "UR" value: NYMEX }
cme_mic { key: "USC" value: NYMEX }
cme_mic { key: "USDBRL" value: CME }
@@ -2910,5 +2912,5 @@ CmeSymbolMics
cme_mic { key: "ZT" value: CBT }
cme_mic { key: "ZW" value: CBT }
cme_mic { key: "ZWT" value: CBT }
}
}
}
+685 -188
View File
@@ -5,7 +5,7 @@ JetFIXSimConnection {
name: "sim"
platform: SIM
socket_connect_host_ip: "127.0.0.1"
socket_connect_port: @Ports.exchange_sim_fix_port
socket_connect_port: @Ports.glbx_sim_fix_port
sender_compid: "SPARK" # this is the FIX session name
sender_subid: "BTS"
target_compid: "BTS"
@@ -18,9 +18,506 @@ JetFIXSimConnection {
seconds_to_pause : 1
max_connection_attempts: 9999999
}
sim_ice {
name: "sim_ice"
platform: SIMICE
socket_connect_host_ip: "127.0.0.1"
socket_connect_port: @Ports.ice_sim_fix_port
sender_compid: "51239" # this is the FIX session name
sender_subid: "BTS"
target_compid: "BTS"
target_subid: "BTS"
cme_market_segment_id: 0
end_time: "02:00:00"
start_time: "02:05:00"
raw_data: "1JE9X"
use_cme_secure_logon: false
seconds_to_pause : 1
}
}
}
JetFIX {
rule: "CannedCertSession.name='ice_cert'"
value {
#connection: @JetFIXSimConnection.sim_ice
connection {
name: "ice_cert"
platform: ICE
use_cme_secure_logon: false
log_fix_stream: true
socket_connect_host_ip: "63.247.113.154"
socket_connect_port: 80
sender_compid: "51251"
target_compid: "ICE"
start_time: "22:55:00"
end_time: "22:05:00"
sender_subid: "BTS"
user_name: "bluetrd-os" #this is the order_server_id
raw_data: "Starts123"
max_order_msgs_per_window: 300
auto_fix_seq_num: true
seconds_to_replay: 6000
}
connection: @JetFIXSimConnection.sim
#connection: @JetFIXSimConnection.sim_ice
connection {
name: "cme_mc5_99"
platform: GLBX
socket_connect_host_ip: "69.50.112.199"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "99"
cme_market_segment_id: 99
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_58"
platform: GLBX
socket_connect_host_ip: "69.50.112.172"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "58"
cme_market_segment_id: 58
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_54"
platform: GLBX
socket_connect_host_ip: "69.50.112.191"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "54"
cme_market_segment_id: 54
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_82"
platform: GLBX
socket_connect_host_ip: "69.50.112.179"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "82"
cme_market_segment_id: 82
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_56"
platform: GLBX
socket_connect_host_ip: "69.50.112.174"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "56"
cme_market_segment_id: 56
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_50"
platform: GLBX
socket_connect_host_ip: "69.50.112.202"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "50"
cme_market_segment_id: 50
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_52"
platform: GLBX
socket_connect_host_ip: "69.50.112.181"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "52"
cme_market_segment_id: 52
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
}
}
JetFIX {
rule: "CannedCertSession.name='gt_cert'"
value {
connection {
name: "ice_cert"
platform: ICE
use_cme_secure_logon: false
log_fix_stream: true
socket_connect_host_ip: "63.247.113.154"
socket_connect_port: 80
sender_compid: "51251"
target_compid: "ICE"
start_time: "22:55:00"
end_time: "22:05:00"
sender_subid: "BTS"
user_name: "bluetrd-os" #this is the order_server_id
raw_data: "Starts123"
max_order_msgs_per_window: 300
auto_fix_seq_num: true
seconds_to_replay: 6000
}
connection: @JetFIXSimConnection.sim
connection {
name: "cme_mc7_99"
platform: GLBX
socket_connect_host_ip: "69.50.112.199"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "99"
cme_market_segment_id: 99
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_58"
platform: GLBX
socket_connect_host_ip: "69.50.112.172"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "58"
cme_market_segment_id: 58
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_54"
platform: GLBX
socket_connect_host_ip: "69.50.112.191"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "54"
cme_market_segment_id: 54
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_82"
platform: GLBX
socket_connect_host_ip: "69.50.112.179"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "82"
cme_market_segment_id: 82
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_56"
platform: GLBX
socket_connect_host_ip: "69.50.112.174"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "56"
cme_market_segment_id: 56
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_50"
platform: GLBX
socket_connect_host_ip: "69.50.112.202"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "50"
cme_market_segment_id: 50
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_52"
platform: GLBX
socket_connect_host_ip: "69.50.112.181"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "52"
cme_market_segment_id: 52
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_60"
platform: GLBX
socket_connect_host_ip: "69.50.112.195"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "60"
cme_market_segment_id: 60
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_76"
platform: GLBX
socket_connect_host_ip: "69.50.112.204"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "76"
cme_market_segment_id: 76
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_88"
platform: GLBX
socket_connect_host_ip: "69.50.112.169"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "88"
cme_market_segment_id: 88
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_74"
platform: GLBX
socket_connect_host_ip: "69.50.112.197"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "74"
cme_market_segment_id: 74
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_64"
platform: GLBX
socket_connect_host_ip: "69.50.112.177"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "64"
cme_market_segment_id: 64
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_72"
platform: GLBX
socket_connect_host_ip: "69.50.112.189"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "72"
cme_market_segment_id: 72
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_70"
platform: GLBX
socket_connect_host_ip: "69.50.112.183"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "70"
cme_market_segment_id: 70
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_68"
platform: GLBX
socket_connect_host_ip: "69.50.112.168"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "68"
cme_market_segment_id: 68
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_80"
platform: GLBX
socket_connect_host_ip: "69.50.112.187"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "80"
cme_market_segment_id: 80
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_84"
platform: GLBX
socket_connect_host_ip: "69.50.112.198"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "84"
cme_market_segment_id: 84
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc7_78"
platform: GLBX
socket_connect_host_ip: "69.50.112.167"
socket_connect_port: 61923
sender_compid: "MC7004N"
target_compid: "CME"
target_subid: "78"
cme_market_segment_id: 78
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
}
}
JetFIX {
rule: "CannedCertSession.name='mc7'"
value {
@@ -456,193 +953,193 @@ JetFIX {
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_60"
platform: GLBX
socket_connect_host_ip: "69.50.112.195"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "60"
cme_market_segment_id: 60
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_76"
platform: GLBX
socket_connect_host_ip: "69.50.112.204"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "76"
cme_market_segment_id: 76
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_88"
platform: GLBX
socket_connect_host_ip: "69.50.112.169"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "88"
cme_market_segment_id: 88
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_74"
platform: GLBX
socket_connect_host_ip: "69.50.112.197"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "74"
cme_market_segment_id: 74
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_64"
platform: GLBX
socket_connect_host_ip: "69.50.112.177"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "64"
cme_market_segment_id: 64
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_72"
platform: GLBX
socket_connect_host_ip: "69.50.112.189"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "72"
cme_market_segment_id: 72
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_70"
platform: GLBX
socket_connect_host_ip: "69.50.112.183"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "70"
cme_market_segment_id: 70
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_68"
platform: GLBX
socket_connect_host_ip: "69.50.112.168"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "68"
cme_market_segment_id: 68
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_80"
platform: GLBX
socket_connect_host_ip: "69.50.112.187"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "80"
cme_market_segment_id: 80
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_84"
platform: GLBX
socket_connect_host_ip: "69.50.112.198"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "84"
cme_market_segment_id: 84
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
connection {
name: "cme_mc5_78"
platform: GLBX
socket_connect_host_ip: "69.50.112.167"
socket_connect_port: 61922
sender_compid: "MC5004N"
target_compid: "CME"
target_subid: "78"
cme_market_segment_id: 78
start_time: "00:30:00"
end_time: "23:30:00"
start_day: "sunday"
end_day: "friday"
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
# connection {
# name: "cme_mc5_60"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.195"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "60"
# cme_market_segment_id: 60
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_76"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.204"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "76"
# cme_market_segment_id: 76
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_88"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.169"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "88"
# cme_market_segment_id: 88
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_74"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.197"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "74"
# cme_market_segment_id: 74
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_64"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.177"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "64"
# cme_market_segment_id: 64
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_72"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.189"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "72"
# cme_market_segment_id: 72
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_70"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.183"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "70"
# cme_market_segment_id: 70
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_68"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.168"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "68"
# cme_market_segment_id: 68
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_80"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.187"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "80"
# cme_market_segment_id: 80
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_84"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.198"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "84"
# cme_market_segment_id: 84
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
# connection {
# name: "cme_mc5_78"
# platform: GLBX
# socket_connect_host_ip: "69.50.112.167"
# socket_connect_port: 61922
# sender_compid: "MC5004N"
# target_compid: "CME"
# target_subid: "78"
# cme_market_segment_id: 78
# start_time: "00:30:00"
# end_time: "23:30:00"
# start_day: "sunday"
# end_day: "friday"
# sender_subid: "BTS"
# raw_data: "S4PMA"
# auto_fix_seq_num: true
# }
}
}
JetFIX {
+9 -5
View File
@@ -1,9 +1,13 @@
#nusers: 1
#allow concurrent : false
#expires: 2019-Sep-30 00:00:00 637053984000000000
#generation_time: 2019-Jun-18 18:25:44.333280 5248650809870720704
#allow concurrent : true
#expires: 2019-Dec-31 00:00:00 637133472000000000
#generation_time: 2019-Sep-30 15:52:10.434845 5248740573731736354
EncryptedKeyCode {
value {
keycode: "pgtv/OmievnpmNlgxTYuN801Hbetgu7ZGkHnlGWtK+DBrKSEgKxr5lGvCW1ld/jsztkWhKHDh0iediMDjrPm4+C5qmXlt4JJlAFvKolMN8HVC59m82fECvakcqKq28WSEjf6/DuPJNP1ZwxjcmKouxx1LZ15VlNkECtNrC9pkCnifazbfQZGV3kD08zMEyw/RPmOaVLFFeav8lwI5UpcjPYBIK1rJowXdGSvm1CJViwG5Z2JbdHR39QbKjVx112d5VbVtBq9nO3i0FEKvobjN/Gzcz/5x4TgQtEShKsbmgEN+MBVL3AItQlcFzZvE/05JLmfACUFmk5Eu0a3DlLs3A=="
keycode: "fVZlub92ulkXME+uZSyO9+WmyAXYKD735Qzxxfdj4G+SqEDTuwfNxOZVPS3TCFQqWPDmgjKTbbvfqIrGe3icxkVObUcUoS7lBXRXFrSvzOfs9eTz9RqHRvquDidnOzKxmSXsxV2bMb21UqBCJFeTzb4Q6Agp8EtjXJRc57UMVVygvdXg528S3ocBIq1V4W5NYraFn5WpqrTuBhpYbnsZAHi77s/EEwUT+6la3J2OHPtbiQnB6JFb0zsExMuzE4gwp79ojuQ5pnV2DXBZFNwxYvFyBUU/ac6oU89saZ/ay1DbOjz76TNqnNFewZvzdXZl3y6+X1eblX2streH2pn7gg=="
}
}
}
@@ -2,4 +2,14 @@ OrdersSoftCleanupCutoff {
value {
extra_days: 1
}
}
SODTime
{
rule: "DeploymentType.type == 'dev'"
value
{
sod_hh: 20
sod_mm: 30
}
}
+1
View File
@@ -155,6 +155,7 @@ message ICEOptions
message ICEChannel {
required string name = 1;
repeated uint32 market_type = 2;
repeated uint32 uds_market_type = 7;
optional uint32 udp_buffer_size = 3 [default = 4194304]; //4mb
optional uint32 heartbeat_interval = 4 [default = 36000];
optional uint32 sequence_gap_margin = 5 [default = 10000];
+2 -1
View File
@@ -5,6 +5,7 @@ message Ports {
// see ports.conf for actual defaults
optional int32 config_port = 1 ;
optional int32 qbus_port = 2 ;
optional int32 exchange_sim_fix_port = 3 ;
optional int32 glbx_sim_fix_port = 3 ;
optional int32 ice_sim_fix_port = 5 ;
optional int32 replicator_port = 4 ;
}
+1
View File
@@ -20,4 +20,5 @@ message Symbols {
optional SecurityExchangeList glbx = 10;
optional SecurityExchangeList sim = 20;
optional SecurityExchangeList ice = 30;
optional SecurityExchangeList simice = 40;
}
Loaded 100 of 194 files, more files were not shown because too many files have changed in this diff. Show more