Compare commits

...
158 Commits
Author SHA1 Message Date
Pedro Pinto 8a89b0c964 Pushed variant versions of timstamp and oid everywhere. 2020-07-02 12:59:14 -04:00
Pedro Pinto 1fba09cf94 Refactor of ids. 2020-07-02 11:05:04 -04:00
Pedro Pinto 0baa6b875e Fixed merge error. 2020-07-02 09:09:20 -04:00
Pedro Pinto cdacc2d4d4 Merged 2020-07-02 07:26:43 -04:00
Pedro Pinto 1433541947 Automatically advanced our own seq number on connection failure.
It is fairly easy for our sequence number to be behind CME if we
crash. Since we can detect this issue (CME tells us about it) we can
try to fix it automatically by incrementing our own sequence
number. This should allow us to recover automatically in some
scenarios.
2020-07-02 06:57:01 -04:00
Pedro Pinto 1070ca7ace Ran clang-format. 2020-07-02 06:28:32 -04:00
Pedro Pinto 56fa27dd7e Handled non text timestamp in native order. 2020-07-02 06:23:07 -04:00
Pedro Pinto d87b522bc6 Added better logging when terminated by exchange. 2020-07-02 06:22:38 -04:00
Eric Harding 166cb03782 Provide account when parsing execution reports. 2020-07-01 14:40:10 -04:00
Eric Harding c3786d9d64 ilink3: Provide SecurityOracle to execution report parser 2020-07-01 11:50:03 -04:00
Pedro Pinto 9080e3124b Filled in cust_order_handing_inst 2020-07-01 11:29:47 -04:00
Pedro Pinto d9c536124a Fixed logging of session seq numbers. 2020-07-01 11:29:30 -04:00
Pedro Pinto 7de6b2907e Filled in sendercompid in routing record.
iLink3 requires this.
2020-07-01 10:48:01 -04:00
Eric Harding 75f017e9f8 ilink3: Get PartyDetails from sender_cmp_id 2020-07-01 10:29:20 -04:00
Pedro Pinto 7757ab3ea0 Fixed a few bugs. 2020-06-30 19:35:53 -04:00
Pedro Pinto 3186dd383c We can connect now. 2020-06-30 19:03:35 -04:00
Pedro Pinto 45f751c9c6 Bad merge. 2020-06-30 19:03:35 -04:00
Pedro Pinto e4d3774980 Better logging. 2020-06-30 19:03:35 -04:00
Eric Harding eedb3ce05d Clear hmac for json logging 2020-06-30 17:11:01 -04:00
Eric Harding 6a7d38c0fd flip session bool 2020-06-30 16:10:26 -04:00
Eric Harding 31ccbfcd19 Switch to ilink3 logging group 2020-06-30 14:43:38 -04:00
Eric Harding c2abf90cc4 IL3MessageFramer owns outgoing messages so it needs to outlive ILinkGW 2020-06-30 14:36:02 -04:00
Eric Harding 8dc4735248 ilink3: set_state(Error) only after disconnect 2020-06-30 14:25:59 -04:00
Pedro Pinto d940d9f11d For now, caught serialization error in some ilink3 msgs. 2020-06-30 14:10:07 -04:00
Pedro Pinto 1e0c75c6c7 Added iLink3 subsystem for logging. 2020-06-30 14:09:55 -04:00
Pedro Pinto 3bb9961af4 Refactor. 2020-06-30 11:35:40 -04:00
Pedro Pinto da8088fd8d Rebased 2020-06-30 11:27:56 -04:00
Eric Harding 748a65f671 Merge branch 'ilink3_gateway' of bitbucket.org:bluetradesys/spark into ilink3_gateway 2020-06-30 10:05:33 -04:00
Eric Harding 66d80136bd ilink3: Keep outgoing messages alive forever. 2020-06-30 10:04:42 -04:00
Pedro Pinto 81189bb2cc Forgot to add message logger. 2020-06-29 12:08:22 -04:00
Pedro Pinto e5681a50f2 Made session name come from date. 2020-06-29 10:59:15 -04:00
Pedro Pinto 69fe4569e3 Made FIX session name available as uint64_t as well as strings. 2020-06-29 10:57:40 -04:00
Pedro Pinto c7caf66f9c Changed the ILink3 log format to json. 2020-06-26 19:11:05 -04:00
Pedro Pinto 14504f4a94 Cleaned up comment. 2020-06-26 19:10:49 -04:00
Pedro Pinto 5b601a4016 Fixed encofing of clorid. 2020-06-26 19:10:23 -04:00
Pedro Pinto 45aa75e8bb Brought back the ilink3/ilink2 encoding abstraction. 2020-06-25 16:49:46 -04:00
Pedro Pinto b2471d45b2 Added tool 2020-06-25 16:49:10 -04:00
Pedro Pinto 11e2df8c76 Tweaked build tools. 2020-06-25 16:49:10 -04:00
Pedro Pinto cba6852655 Updated docker 2020-06-25 16:49:10 -04:00
Pedro Pinto 5eeaedde26 Added a few build tools. 2020-06-25 16:49:10 -04:00
Pedro Pinto b63052dbaa Updated ICE Onixs 2020-06-25 16:49:10 -04:00
Pedro Pinto 29f5bc798e Added +x 2020-06-25 16:49:10 -04:00
Pedro Pinto 04603acbb9 Added publishing of new routing info when orders are recorevered from disk 2020-06-25 16:49:10 -04:00
Pedro Pinto bc6890055e temp commit, fixing glbxnative order 2020-06-25 16:49:10 -04:00
Pedro Pinto ea94c09c78 Eric intermediate ilink3 fixes 2020-06-25 16:49:10 -04:00
Eric Harding e3c3bc78fc Note what this address list is for 2020-06-24 20:55:20 -04:00
Eric Harding a11d390dcd ilink3 message logging 2020-06-24 20:52:21 -04:00
Eric Harding 7c74a961d4 Add canned cert sessions for ilink3 nrcert 2020-06-24 20:43:27 -04:00
Eric Harding 5db21ad2ca fix build, session and clordid changes 2020-06-24 19:32:12 -04:00
Eric Harding f703dabdfe Raw msg should be 2 strings 2020-06-24 17:53:30 -04:00
Eric Harding 237d3eea4b encode_clordid needs security key 2020-06-24 17:29:06 -04:00
Eric Harding 818bdec130 Add NrCert keys 2020-06-24 15:07:02 -04:00
Eric Harding d257cf2c77 Disable broken ilink3 tests for now 2020-06-24 13:28:33 -04:00
Eric Harding 079f46404f Add some testing notes 2020-06-24 10:57:15 -04:00
Eric Harding edcc73e934 Remove old ILink3ExecutionGateway. Instead use GlbxIlink3ExecutionGateway 2020-06-23 22:41:33 -04:00
Eric Harding 0c4c2b7231 cme autocert msgw_failover test script 2020-06-23 13:05:32 -04:00
Eric Harding 420351c093 Replay refactor #4 2020-06-23 12:01:52 -04:00
Eric Harding f69e6b89c5 Sequence number fixes 2020-06-22 22:23:13 -04:00
Eric Harding c3e22e4b23 Recovery revamp #3 2020-06-22 20:16:21 -04:00
Eric Harding 3231ffb343 Meaningless autocert code 2020-06-15 22:48:28 -04:00
Eric Harding 8d7f1738cf update cert secure logon 2020-06-15 22:47:30 -04:00
Eric Harding 9101214e66 Add message logger and revamp replay sequence handling 2020-06-15 14:51:41 -04:00
Eric Harding c6b2e2f21e OMF setting to true, always 2020-06-12 17:49:37 -04:00
Eric Harding 2eac97c1a9 meaningless cert change 2020-06-12 15:18:20 -04:00
Eric Harding b4b0e10f29 Fix IOC=FAK order type (not FOK) 2020-06-12 15:17:38 -04:00
Eric Harding 38d9db4a90 Session and sequence number fixes 2020-06-11 11:36:37 -04:00
Eric Harding 6a679ff78c Fix for cancel/replace 2020-06-10 14:13:28 -04:00
Eric Harding aba3f21020 stop order does not carry price 2020-06-09 19:18:36 -04:00
Eric Harding fede19fd11 stop-limit success 2020-06-09 16:30:00 -04:00
Eric Harding 3fa8dbf112 Cannot send price with market order 2020-06-08 23:09:10 -04:00
Eric Harding 77ae4703b3 Fix clOrdID and custOrdCapacity 2020-06-08 22:58:53 -04:00
Eric Harding a28bfa1175 execution report handling tweaks 2020-06-04 10:05:44 -04:00
Eric Harding 4e4a48283d bool parse_report(string&, SecurityOracle&, ExecutionReport*); 2020-06-03 13:09:56 -04:00
Pedro Pinto 7a761d00ce Added security oracle to SessionStore so we can resolve exe reports. 2020-06-03 08:51:31 -04:00
Pedro Pinto 968be6a99a Added storage for sessions. Still missing parsing of exec reports. 2020-06-02 17:13:53 -04:00
Pedro Pinto 03404eb3f1 Made some progress in GLBXiLink3ExecutionGateway 2020-06-02 09:16:02 -04:00
Pedro Pinto ff1a970982 Fixed build some more 2020-05-28 14:29:45 -04:00
Pedro Pinto ed890b4d84 Fixed broken tests for subscribe_exe_report change 2020-05-28 13:50:04 -04:00
Pedro Pinto e87003cc41 Merged with master 2020-05-28 12:21:51 -04:00
Eric Harding bc06037843 Fix the build 2020-05-28 12:20:30 -04:00
Pedro Pinto a502c365e5 Build tweaks 2020-05-28 12:15:16 -04:00
Pedro Pinto c4c7cebfc5 Updated externals 2020-05-28 12:12:46 -04:00
Pedro Pinto f18bcd2995 Build tweaks 2020-05-28 12:12:46 -04:00
Pedro Pinto a6a1b6ac53 Fixed clang build. 2020-05-28 12:12:46 -04:00
Pedro Pinto fdacd8b543 Added -f when removing simlinks in build setup. 2020-05-28 12:02:46 -04:00
John Colvin 3d1de9a0c7 nuget_restore.cmd uses externals package source (builds offline) 2020-05-28 12:02:31 -04:00
John Colvin b2b3fa5949 update jenkinsbuild.cmd to use externals nuget source (for windows) 2020-05-28 12:02:17 -04:00
Pedro Pinto 86ecf69820 Updated external subrepos 2020-05-28 11:53:51 -04:00
Eric Harding 8c3da4e43c Re-arrange some methods in ILinkGW.h 2020-05-27 16:51:36 -04:00
Eric Harding 06b955dceb Exchange seq number fix 2020-05-27 11:49:08 -04:00
Eric Harding e75d15146c cme cert test update 2020-05-26 23:55:27 -04:00
Eric Harding cb07384c9f Fix problem with party details 2020-05-26 23:55:13 -04:00
Eric Harding fc9e502539 cert refactor 2020-05-26 12:40:16 -04:00
Eric Harding fcbf3388c0 update ilinkbinaryxml templates 2020-05-26 12:40:04 -04:00
Eric Harding 899bea940f improve ilinkgw logging 2020-05-26 12:39:55 -04:00
Eric Harding 14b7509607 ensure local launch timezone 2020-05-26 12:39:41 -04:00
Pedro Pinto 8f537a8fda Merged in build_improvements (pull request #414)
Build improvements
2020-05-26 16:32:43 +00:00
Pedro Pinto 01b9ff6b47 Dropped celoxica 2020-05-26 12:28:35 -04:00
Pedro Pinto 2609663d3e Updated setup_builds to work even if its run outside the tree. 2020-05-26 12:06:08 -04:00
Eric Harding 25668e8df0 dont' build web client on wsl2 2020-05-26 11:54:19 -04:00
Pedro Pinto fd89241611 Updated externals pointer 2020-05-26 11:49:29 -04:00
John Colvin a69118c5d3 fix line endings in release_notes 2020-05-22 23:42:27 -05:00
John Colvin 5accd0e2b4 Merge branch 'master' into prod 2020-05-22 19:14:16 -05:00
John Colvin df5ad61cd2 release notes for synthetic gui integer tick sizes 2020-05-22 19:12:29 -05:00
John Colvin 4a7674eb29 synthetic gui supports integer tick sizes 2020-05-22 18:15:53 -05:00
Eric Harding 5a458287f4 update license search info in disable_onixs.py 2020-05-22 15:18:46 -04:00
Eric Harding 5345ba8ff8 securities for sending orders ilink3 test 2020-05-19 15:58:56 -05:00
Eric Harding 9bf05973bd Add in/out to logs 2020-05-14 20:51:15 -05:00
Eric Harding cea4d05bc4 log every msg 2020-05-13 20:19:48 -05:00
Eric Harding 0b7208784b Can't take the double negatives anymore 2020-05-13 14:01:16 -05:00
Eric Harding 059ccbdab6 Merge branch 'master' of bitbucket.org:bluetradesys/spark into ilink3_gateway 2020-05-13 11:05:31 -05:00
Eric Harding 75eaf8c3d4 IL3ExecutionReportParser 2020-05-12 13:54:28 -05:00
Eric Harding 1e8fcd794f Update ExecutionReport::exchange_order_id 2020-05-06 12:22:33 -05:00
Eric Harding 726329c4bf Add ilink3 execution report parser and order test 2020-05-06 11:56:52 -05:00
Eric Harding 2d01f3f0f4 CME Certification requires very specific UUID generation 2020-05-06 11:56:01 -05:00
Eric Harding 2a595c0fd7 cme cert hard coding 2020-05-06 11:54:32 -05:00
Eric Harding 5f9866c9e8 SecurityCache now hands out raw pointers. SecurityOracle now indexes exchange security key 2020-05-05 11:17:16 -05:00
Eric Harding 78f1cf88e0 cmake needs love too 2020-05-04 11:16:21 -05:00
Eric Harding 4877436877 Ilink3 order unit test 2020-05-04 11:32:30 -04:00
Eric Harding 1b43124756 Add ReentrancyGuard.h 2020-05-02 13:10:49 -04:00
Eric Harding a1feb3fddf PrimaryGatewayConnectionEnforcement 2020-05-01 13:22:35 -04:00
Eric Harding 024328bf8b Refactor empty session 2020-05-01 11:44:03 -04:00
Eric Harding 80d7e34bf1 Fixes for updated sbe codegen 2020-04-28 18:16:45 -04:00
Eric Harding 8ab69c919b Improve cme provided error message 2020-04-27 16:56:32 -04:00
Eric Harding 99531bcfa0 Update ilink3 generated templates 2020-04-27 16:50:54 -04:00
Eric Harding 6bd516d4f2 cleanup 2020-04-27 11:26:42 -04:00
Eric Harding 1a1d771e1b addition ilink3 tests 2020-04-25 13:18:58 -04:00
Eric Harding 050fcf7c6e Passing simple log in test 2020-04-24 12:31:30 -04:00
Eric Harding aadeae3201 update cmake, avoid web build on wsl 2020-04-17 22:38:53 -04:00
Eric Harding b72e8aed02 ilink3 test code 2020-04-17 20:30:11 -05:00
Eric Harding 0820cc3e9a Fix a very subtle bug in serializer 2020-04-17 13:15:12 -05:00
Eric Harding b1ba9a1315 update ilink code gen readme 2020-04-16 14:03:53 -05:00
Eric Harding 39ce4323a1 Add CME cert command line tool 2020-04-13 16:18:59 -05:00
Eric Harding d9fcd290d9 source files don't need to be executable 2020-04-13 09:53:28 -05:00
Eric Harding 05939b02c5 save 2020-04-12 15:11:46 -05:00
Eric Harding aa91638fe4 ilink3 receive buffer handler + tests 2020-04-10 10:55:53 -05:00
Eric Harding 065fc54f73 IL3Reactor 2020-04-07 14:05:31 -05:00
Eric Harding 95fb13f58b Fix some build issues 2020-04-01 15:21:04 -05:00
Eric Harding 4eb2931cb8 Additional ilink3 refactoring 2020-03-28 21:08:47 -05:00
Eric Harding 5326015a48 Testcase for framer 2020-03-27 13:46:29 -05:00
Eric Harding fcbe319470 Split out functional pieces for easier testing 2020-03-27 09:14:30 -05:00
Eric Harding 5ad21c88b2 Add tests and refactor includes for faster build 2020-03-25 21:15:19 -05:00
Eric Harding 3a9c1d557b Split Retransmit of old vs new session logic 2020-03-09 16:29:15 -05:00
Eric Harding 6fb5b83249 Only send Negotiate if the session is new 2020-02-28 15:33:27 -06:00
Eric Harding 95830fafdf send_cancel 2020-02-27 14:48:56 -06:00
Eric Harding d68b03bb91 send_cancel_replace 2020-02-26 17:56:50 -06:00
Eric Harding e7062ce01e send_order call for link3 2020-02-26 17:36:18 -06:00
Pedro Pinto 932738f98e Merge branch 'master' into ilink3_gateway 2020-02-20 08:39:47 -05:00
Pedro Pinto 1426b00e83 Added fake iLink3 gateway 2020-02-19 16:21:06 -05:00
Pedro Pinto e724409b58 Added jetfix support for string_view 2020-02-19 10:55:56 -05:00
Pedro Pinto 9cf828e9a4 Implemented iLink3 order 2020-02-18 15:37:06 -05:00
Eric Harding 41408fb609 ILink3ExecutionGateway placeholder 2020-02-14 16:07:44 -06:00
Eric Harding 4c21e32838 ILink3GW core gateway 2020-02-14 16:06:58 -06:00
Eric Harding 385f3ea402 add unix_nano_now() to datetime.h 2020-02-14 16:05:00 -06:00
Eric Harding 8d6d8cab18 Update SecureLogon for ilink3 2020-02-14 16:05:00 -06:00
Eric Harding 01615f824a Generated ilink3 messages 2020-02-14 16:05:00 -06:00
Pedro Pinto c6779ddc90 Reactore GLBX native order for iLink3. 2020-02-13 15:26:33 -05:00
Pedro Pinto 46eff65435 Changed IExecutionGateway to support non FIX gateways. 2020-02-12 10:11:53 -05:00
248 changed files with 149042 additions and 1563 deletions

No files matched your search

+9 -5
View File
@@ -8,13 +8,15 @@
"program": "${workspaceRoot}/build/ninja_debug/server/sparkd",
"args": [
"run",
// "test",
// "-a",
// "[ilink3]"
"test",
"-a",
"OutrightVanillaOrder"
],
"stopAtEntry": false,
"cwd": "${workspaceRoot}/build/ninja_debug/server/",
"environment": [],
"environment": [
{ "name": "TZ", "value": "America/Chicago" }
],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
@@ -31,7 +33,9 @@
"request": "launch",
"program": "/home/bts/spark/build/ninja_debug/server/sparkd",
"args": [
"run"
"test",
"-a",
"[ilink3]"
],
"stopAtEntry": false,
"cwd": "/home/bts/spark/build/ninja_debug/server/",
+2 -1
View File
@@ -41,6 +41,7 @@ else ()
-Wno-missing-braces -Wno-ignored-qualifiers \
--std=c++17 -fdiagnostics-color")
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -DNDEBUG -O3")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wno-undef")
add_subdirectory(src/server/sparkd)
add_subdirectory(src/lib)
@@ -55,7 +56,7 @@ else ()
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/web ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/data_files ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/lib/libspark.so ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${EXTERNALS_ROOT}/lib/Release/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.13.0.0 ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${EXTERNALS_ROOT}/lib/Release/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0 ${CMAKE_BINARY_DIR}/server
COMMAND ln ARGS -sf ${EXTERNALS_ROOT}/lib/Release/libACE-5.7.5.so ${CMAKE_BINARY_DIR}/server
COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/server/plugins
COMMENT "Creating server runtime layout"
+5 -1
View File
@@ -1,9 +1,12 @@
+++
+++
title = "Release notes"
weight = 3
sort_by = "weight"
insert_anchor_links = "right"
+++
## 2.16.2
### User Visible Change
- Synthetic creation dialog has a "fractional" checkbox next to the tick settings. Users may uncheck this box to enter integer tick sizes, so the synthetic security's prices will be displayed without decimals, or fractional units.
## 2.16.1
### Bug Fixes
- OrderBook's algo state parameters (in the panel on the right side) are sorted alphabetically
@@ -725,3 +728,4 @@ insert_anchor_links = "right"
- Start, Day and Total PnL columns are painted with a red or green background color based on if the pnl value is negative or positive respectively
- Corrected cash per point values, used in pnl calculations, for a number of products
- PnL report will now remember any customizations you make to filtering and/or sorting criteria
@@ -549,24 +549,48 @@
</u:BindingUpdateGroupCollection>
</u:Behavior.BindingUpdateGroups>
</TextBox>
<TextBlock
<StackPanel
x:Name="PART_TickFactors_Label"
Grid.Column="2"
VerticalAlignment="Center"
Margin="{StaticResource Margin.LHeaderPanelItem}"
Text="Ticks"
IsEnabled="True"
Orientation="Horizontal"
Visibility="{Binding LegTuples.Count, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource IntNotZeroVisibilityConverter}}"
/>
<c:TickFactorsPicker
>
<TextBlock
VerticalAlignment="Center"
Margin="{StaticResource Margin.LHeaderPanelItem}"
Text="Ticks ("
/>
<CheckBox
Margin="1,0,0,0"
IsChecked="{Binding UseFractionalTicks, RelativeSource={RelativeSource TemplatedParent}}"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Padding="0"
>
fractional
</CheckBox>
<TextBlock VerticalAlignment="Center" Margin="1,0,0,0">)</TextBlock>
</StackPanel>
<Grid
x:Name="PART_TickFactors_Picker"
Grid.Column="3"
Margin="{StaticResource Margin.LHeaderPanelItem}"
HorizontalAlignment="Stretch"
IsEnabled="True"
SelectedTickFactors="{Binding TickFactors, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Margin="{StaticResource Margin.LHeaderPanelItem}"
Visibility="{Binding LegTuples.Count, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource IntNotZeroVisibilityConverter}}"
/>
>
<c:TickFactorsPicker
HorizontalAlignment="Stretch"
SelectedTickFactors="{Binding TickFactors, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Visibility="{Binding UseFractionalTicks, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static cv:BooleanToVisibilityConverter.HiddenInstance}}"
/>
<c:TickUpDownInt
HorizontalAlignment="Stretch"
Minimum="1"
Value="{Binding IntegerTickSize, RelativeSource={RelativeSource TemplatedParent}}"
Visibility="{Binding UseFractionalTicks, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource FalseVisibilityConverter}}"
/>
</Grid>
<TextBlock
x:Name="PART_Pricing_Label"
Grid.Column="4"
@@ -52,6 +52,26 @@ namespace mbts.ui.spark {
public TickFactors TickFactors { get => GetValue(TickFactorsProperty) as TickFactors; set => SetValue(TickFactorsProperty, value); }
#endregion
#region UseFractionalTicks
public static readonly DependencyProperty UseFractionalTicksProperty = WPFHelper.create_dp<bool, ExecutionStrategyEditor>(
nameof(UseFractionalTicks), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, true);
public bool UseFractionalTicks {
get => (bool)GetValue(UseFractionalTicksProperty);
set => SetValue(UseFractionalTicksProperty, value);
}
#endregion
#region IntegerTickSize
public static readonly DependencyProperty IntegerTickSizeProperty = WPFHelper.create_dp<int, ExecutionStrategyEditor>(
nameof(IntegerTickSize), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 1);
public int IntegerTickSize {
get => (int)GetValue(IntegerTickSizeProperty);
set => SetValue(IntegerTickSizeProperty, value);
}
#endregion
#region IsNew
public static readonly DependencyProperty IsNewProperty =
DependencyProperty.Register(
@@ -36,6 +36,8 @@
ContractPickerModel="{Binding contract_picker_model}"
HedgePricing="{Binding hedge_pricing}"
HedgePricingItemsSource="{Binding hedge_pricing_options}"
UseFractionalTicks="{Binding use_fractional_ticks}"
IntegerTickSize="{Binding integer_tick_size}"
/>
<c:DialogSkirtOKCancel Grid.Row="1" OKCommand="{Binding commit}" CloseOnOK="False"/>
</Grid>
@@ -2,7 +2,6 @@
using bts.collections;
using bts.shell;
using bts.spark;
using bts.utils;
using mbts.ui;
using mbts.ui.shell;
using mbts.ui.spark;
@@ -30,8 +29,16 @@ namespace mbts.spark {
readonly Property<bool> _has_working_orders, _can_add_leg;
Security _synthetic;
bool _set_name_automatically, _set_ticks_automatically, _set_quantities_automatically, _set_price_mults_automatically, _is_setting_quantities, _is_setting_price_mults;
bool
_set_name_automatically,
_set_ticks_automatically,
_set_quantities_automatically,
_set_price_mults_automatically,
_is_setting_quantities,
_is_setting_price_mults,
_use_fractional_ticks = true;
TickFactors _tick_factors;
int _integer_tick_size = 1;
ExecutionStrategyImmutable _strategy;
HedgePricing _hedge_pricing;
@@ -44,6 +51,10 @@ namespace mbts.spark {
: this(synthetic, strategy, false) {
ExceptionAssert.InvalidOperation.That(synthetic.Id != 0, "This constructor may only be used for already-existing synthetic securities (id must be non-zero).");
_tick_factors = TickUtils.get_regional_ticks(synthetic.ContractSpec).low_tick;
if (TickUtils.is_integer_tick(synthetic.ContractSpec)) {
_use_fractional_ticks = false;
_integer_tick_size = DoubleHelper.to_optional_int32(synthetic.ContractSpec.LowTick) ?? 0;
}
title = $"Edit '{synthetic.Synthetic.Name}'";
icon = Icons.ModifySynthetic;
_has_working_orders = backing(nameof(has_working_orders), security_has_working_orders.OnDispatcher());
@@ -131,14 +142,14 @@ namespace mbts.spark {
flash_error_msg("Name already taken", SparkUtils.UI.MessageFlashDuration, nameof(name)).ignore();
valid = false;
}
if (_tick_factors == null || !_tick_factors.is_valid()) {
flash_error_msg("Please select ticks", SparkUtils.UI.MessageFlashDuration, nameof(tick_factors)).ignore();
if (use_fractional_ticks ? (_tick_factors == null || !_tick_factors.is_valid()) : integer_tick_size == 0) {
flash_error_msg("Please select ticks", SparkUtils.UI.MessageFlashDuration, use_fractional_ticks ? nameof(tick_factors) : nameof(integer_tick_size)).ignore();
valid = false;
}
if (valid) {
_synthetic.Synthetic.Legs.SetItems(leg_tuples.Select(l => l.leg));
_synthetic.Symbol = _deduce_symbol(_synthetic);
_synthetic.ContractSpec = _tick_factors.to_spec();
_synthetic.ContractSpec = use_fractional_ticks ? _tick_factors.to_spec() : TickUtils.create_integer_tick_spec(integer_tick_size);
uint? id = await model.create_synthetic(new SecurityImmutable(_synthetic));
if (id.HasValue && id != 0) {
if (await model.save_strategy(id.Value, get_strategy())) {
@@ -295,6 +306,20 @@ namespace mbts.spark {
public bool has_working_orders => _has_working_orders.Value;
public bool is_new { get; }
public bool is_new_leg_popup_open { get; set; }
public bool use_fractional_ticks {
get => _use_fractional_ticks;
set {
if (Set(ref _use_fractional_ticks, value))
_set_ticks_automatically = false;
}
}
public int integer_tick_size {
get => _integer_tick_size;
set {
if (Set(ref _integer_tick_size, value))
_set_ticks_automatically = false;
}
}
public bool can_add_leg => _can_add_leg.Value;
public SyntheticContract.Types.PriceCalc price_calc { get => _synthetic.Synthetic.PriceCalc; set => _synthetic.Synthetic.PriceCalc = value; }
public ObservableCollection<LegSpreaderParamsTuple> leg_tuples { get; } = new ObservableCollection<LegSpreaderParamsTuple>();
@@ -323,6 +348,16 @@ namespace mbts.spark {
_strategy = strategy;
hedge_pricing = strategy.HedgePricing;
leg_tuples.SetItems(_get_legs(_synthetic, strategy));
if (synthetic.HasContractSpec) {
/// assign the fields <see cref="_use_fractional_ticks"/> and <see cref="_integer_tick_size"/>,
/// rather than the properties <see cref="use_fractional_ticks"/> and <see cref="integer_tick_size"/>
/// because the setters of the former flip <see cref="_set_ticks_automatically"/> to false if the value changes.
/// This behavior causes the ticks to be automatically deduced as legs are added/removed,
/// until the user explicitly enters a different value (as the properties are bound to tick input controls in the view).
Set(ref _use_fractional_ticks, !TickUtils.is_integer_tick(synthetic.ContractSpec), nameof(use_fractional_ticks));
if (!use_fractional_ticks)
Set(ref _integer_tick_size, DoubleHelper.to_optional_int32(synthetic.ContractSpec.LowTick) ?? 0, nameof(integer_tick_size));
}
RaisePropertyChanged(nameof(name), nameof(tick_factors));
}
@@ -63,5 +63,20 @@ namespace mbts {
public static double? nan_nullable(double value) =>
double.IsNaN(value) ? (double?)null : value;
public static int? to_optional_int32(double value) {
if (double.IsNaN(value) || double.IsInfinity(value))
return null;
if (value > 0) {
value = Math.Floor(value);
if (value <= int.MaxValue)
return (int)value;
} else if (value < 0) {
value = Math.Ceiling(value);
if (value >= int.MinValue)
return (int)value;
}
return null;
}
}
}
@@ -1005,6 +1005,8 @@
ContractPickerModel="{Binding contract_picker_model}"
HedgePricing="{Binding hedge_pricing}"
HedgePricingItemsSource="{Binding hedge_pricing_options}"
UseFractionalTicks="{Binding use_fractional_ticks}"
IntegerTickSize="{Binding integer_tick_size}"
/>
<c:DialogSkirt Grid.Row="1" Margin="-4" VerticalAlignment="Top" RightItems="{Binding skirt_items}"/>
</Grid>
@@ -12,6 +12,9 @@ namespace mbts.ui.converters
public Visibility VisibilityForFalse { get { return _visfalse; } set { _visfalse = value; } }
public static BooleanToVisibilityConverter Instance => new BooleanToVisibilityConverter();
public static BooleanToVisibilityConverter HiddenInstance => new BooleanToVisibilityConverter {
VisibilityForFalse = Visibility.Hidden
};
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
bool flag = false;
@@ -49,6 +49,28 @@ namespace mbts.spark {
public static double parse(this ContractSpecificationImmutable? spec, string text, double display_multiplier, string nan_text) =>
spec.spec_or_default().parse(text, display_multiplier, nan_text);
public static bool is_integer_tick(ContractSpecificationImmutable spec) =>
spec.MainFraction == 0 &&
spec.PriceDisplayFormat == 0 &&
spec.LowTick > 0 &&
MathUtils.is_int(spec.LowTick) &&
spec.HighTick > 0 &&
MathUtils.is_int(spec.HighTick);
public static ContractSpecification create_integer_tick_spec(int low_tick) =>
create_integer_tick_spec(low_tick, low_tick);
public static ContractSpecification create_integer_tick_spec(int low_tick, int high_tick) {
var rv = SecurityDataHelper.Defaults.ContractSpecification;
rv.MainFraction = 0;
rv.SubFraction = 0;
rv.PriceDisplayFormat = 0;
rv.PriceBreak = 0;
rv.LowTick = low_tick;
rv.HighTick = high_tick;
return rv;
}
public static double low_tick(NativePriceSize[] bids, NativePriceSize[] asks) {
double low = bids[bids.Length - 1].price;
if (double.IsNaN(low))
+1
View File
@@ -36,6 +36,7 @@ namespace bts {
Plugin,
Sdk,
Http,
iLink3
// Please keep this list in sync with logging.h/logging.cpp
}
+19 -12
View File
@@ -1,12 +1,19 @@
Session ID Access ID Secret Key Creation Date Expiration Date Environment
M4D lLtjH74y1Kh5XUJTLyH2 f1K_tROQp2lTIplVp34WxKa7xDUgfFnIteolfik061o 2019-09-03 2020-09-03 CERT
MC1 VEMlkDuLz74OVHSuacQB IuHyYT3b-9KUo3WsuXykt-fXsjzp7L-JOrdCSQZLNl0 2019-09-03 2020-09-03 CERT
MC5 77lzSUwPLlM9obaXh2mK z6aA9qfASDKfZkYTVKFqJd-78i0HZ2Q9ec3CKCYIqHg 2019-09-03 2020-09-03 CERT
MC7 RphzI3rn71oGUEiYnX9e y6OvvPPyoyj2S8YAnE1gFduXT8v29HIMjO5EngYxSNg 2019-09-03 2020-09-03 CERT
MC8 PYBIm2TI9gFPIxmHbuYl 6o-ZolGH2DdeQOlGtJ5Zqoh_kg7VdbxkmjeOHmigKwU 2019-09-03 2020-09-03 CERT
Session ID Access ID Secret Key Creation Date Expiration Date Environment
M4D lLtjH74y1Kh5XUJTLyH2 f1K_tROQp2lTIplVp34WxKa7xDUgfFnIteolfik061o 2019-09-03 2020-09-03 CERT
MC1 VEMlkDuLz74OVHSuacQB IuHyYT3b-9KUo3WsuXykt-fXsjzp7L-JOrdCSQZLNl0 2019-09-03 2020-09-03 CERT
MC5 77lzSUwPLlM9obaXh2mK z6aA9qfASDKfZkYTVKFqJd-78i0HZ2Q9ec3CKCYIqHg 2019-09-03 2020-09-03 CERT
MC7 RphzI3rn71oGUEiYnX9e y6OvvPPyoyj2S8YAnE1gFduXT8v29HIMjO5EngYxSNg 2019-09-03 2020-09-03 CERT
MC8 PYBIm2TI9gFPIxmHbuYl 6o-ZolGH2DdeQOlGtJ5Zqoh_kg7VdbxkmjeOHmigKwU 2019-09-03 2020-09-03 CERT
NGG RYcigz3bSLIIBBF2A2Hq qB1dm9VkTKeXcdQpFzla8B3_jwTgya_-Fk5iyEJvr2E 2020-06-15 2021-06-15 NEWRELEASE
NGF o4OTmmTLQ7Lv4g6bCm26 HbD3FneMyb9Fu-FkCDLscCczHqFcFE2PyWv978RXGyA 2019-12-20 2020-12-20 NEWRELEASE
UZE EeFdZ1FPepk6U4k3xBZA 2LjEtdLvBLLB1QuDJ4KiJW6M4dF6IHWd_UKmo7p3_Us 2020-06-24 2021-06-24 NEWRELEASE
VAE Y8iqatTewuoHX16gghw8 FNcCB3Ks1qleS56quYzH4V7zAu78YY2bCdLRi9tmU9E 2020-06-24 2021-06-24 NEWRELEASE
+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/MarketDataService.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/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/subprocess.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;jetfix/codec/FIXArray.cpp;jetfix/common/OutFIX.cpp;jetfix/connection/AsyncReader.cpp;jetfix/connection/IConnection.cpp;jetfix/connection/SocketConnection.cpp;jetfix/gateway/CoreGateway.cpp;jetfix/gateway/JetFIXGateway.cpp;jetfix/gateway/Session.cpp;jetfix/store/FIXFileStore.cpp;jetfix/store/session_name.cpp;jetfix/tests/async_reader_tests.cpp;jetfix/tests/decoding_tests.cpp;jetfix/tests/fix_encoding_stream_tests.cpp;jetfix/tests/fix_fragment_tests.cpp;jetfix/tests/jetfix_performance_tests.cpp;jetfix/tests/sample_fix.cpp;jetfix/tests/store_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/Product.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/service/MarketDataServiceServer.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;md/vendor/OnixsUtils.cpp;mercury/actors/IPollableActor.cpp;mercury/broker/Broker.cpp;mercury/broker/BrokerProxy.cpp;mercury/broker/ILocalBroker.cpp;mercury/broker/IRemoteBroker.cpp;mercury/common/mercury_common.cpp;mercury/events/TimerEvent.cpp;mercury/executor/Executor.cpp;mercury/topics/Topic.cpp;metrics/metrics.cpp;metricsLine 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/MarketDataService.proto;api/services/MoneyFileService.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/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/subprocess.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;jetfix/codec/FIXArray.cpp;jetfix/common/OutFIX.cpp;jetfix/connection/AsyncReader.cpp;jetfix/connection/IConnection.cpp;jetfix/connection/SocketConnection.cpp;jetfix/gateway/CoreGateway.cpp;jetfix/gateway/JetFIXGateway.cpp;jetfix/gateway/Session.cpp;jetfix/store/FIXFileStore.cpp;jetfix/store/session_name.cpp;jetfix/tests/async_reader_tests.cpp;jetfix/tests/decoding_tests.cpp;jetfix/tests/fix_encoding_stream_tests.cpp;jetfix/tests/fix_fragment_tests.cpp;jetfix/tests/jetfix_performance_tests.cpp;jetfix/tests/sample_fix.cpp;jetfix/tests/store_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/Product.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/service/MarketDataServiceServer.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;md/vendor/OnixsUtils.cpp;mercury/actors/IPollableActor.cpp;mercury/broker/Broker.cpp;mercury/broker/BrokerProxy.cpp;mercury/broker/ILocalBroker.cpp;mercury/broker/IRemoteBroker.cpp;mercury/common/mercury_common.cpp;mercury/events/TimerEvent.cpp;mercury/executor/Executor.cpp;mercury/topics/Topic.cpp;metrics/metrics.cpp;metricsLine truncated
@@ -580,7 +580,9 @@ bts::api::orderman::RoutingRecord AdminServiceUtils::get_routing_record(const bt
rv.set_session(conn_ptr->name());
rv.set_operator_id(cme_user_data->operator_id());
rv.set_location(cme_user_data->location());
rv.set_smp_id(cme_user_data->smp_id());
if (cme_user_data->smp_instruction()== "O")
rv.set_smp_instruction(api::orderman::SelfMatchPreventionInstruction::SELF_MATCH_PREVENTION_INSTRUCTION_CANCEL_RESTING);
else if (cme_user_data->smp_instruction()== "N")
+4 -1
View File
@@ -383,7 +383,9 @@ message NativeOrderState {
RoutingRecord routing_record = 5;
NativeOrderType native_type = 6;
string last_transact_time = 7;
uint64 last_transact_time_unix_ns = 9;
double stop_px = 8;
uint64 exchange_order_id64 = 10;
}
// Custom order states
@@ -452,7 +454,8 @@ enum TimeInForce {
TIME_IN_FORCE_UNDEFINED = 0;
TIME_IN_FORCE_DAY = 48;
TIME_IN_FORCE_GTC = 49;
TIME_IN_FORCE_IOC = 51;
TIME_IN_FORCE_IOC = 51; // FAK
TIME_IN_FORCE_DATE = 52;
}
enum ManualOrderIndicator {
+1
View File
@@ -23,6 +23,7 @@ PlatformMap {
}
}
PublisherNamespace {
value {
shared_memory_namespace: @System.os_user
+95 -13
View File
@@ -14,7 +14,7 @@ JetFIXSimConnection {
end_time: "02:00:00"
start_time: "02:05:00"
raw_data: "1JE9X"
use_cme_secure_logon: false
use_cme_secure_logon: false
seconds_to_pause : 1
max_connection_attempts: 9999999
}
@@ -31,9 +31,9 @@ JetFIXSimConnection {
end_time: "02:00:00"
start_time: "02:05:00"
raw_data: "1JE9X"
use_cme_secure_logon: false
use_cme_secure_logon: false
seconds_to_pause : 1
}
}
}
}
@@ -49,7 +49,7 @@ JetFIX {
socket_connect_host_ip: "63.247.113.154"
socket_connect_port: 80
sender_compid: "51251"
target_compid: "ICE"
target_compid: "ICE"
start_time: "22:55:00"
end_time: "22:05:00"
sender_subid: "BTS"
@@ -57,12 +57,12 @@ JetFIX {
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
@@ -181,9 +181,9 @@ JetFIX {
sender_subid: "BTS"
raw_data: "S4PMA"
auto_fix_seq_num: true
}
}
}
}
}
JetFIX {
rule: "CannedCertSession.name='gt_cert'"
@@ -196,7 +196,7 @@ JetFIX {
socket_connect_host_ip: "63.247.113.154"
socket_connect_port: 80
sender_compid: "51251"
target_compid: "ICE"
target_compid: "ICE"
start_time: "22:55:00"
end_time: "22:05:00"
sender_subid: "BTS"
@@ -204,7 +204,7 @@ JetFIX {
raw_data: "Starts123"
max_order_msgs_per_window: 300
auto_fix_seq_num: true
seconds_to_replay: 6000
}
connection: @JetFIXSimConnection.sim
@@ -515,7 +515,7 @@ JetFIX {
auto_fix_seq_num: true
}
}
}
}
JetFIX {
@@ -2391,9 +2391,91 @@ JetFIX {
}
}
}
# NrCert gateways
# 69.50.112.184,12,OESGW
# 69.50.112.202,50,CME Eurodollar Options
# 69.50.112.181,52,CME Globex FX Options II
# 69.50.112.191,54,CME Equity Options
# 69.50.112.174,56,NYMEX and COMEX Options
# 69.50.112.172,58,CBOT Treasury Options
# 69.50.112.195,60,CBOT Commodity and Equity Options
# 69.50.112.177,64,CME E-mini S&P 500 Futures
# 69.50.112.168,68,CME Equity Futures excluding E-mini S&P
# 69.50.112.183,70,CME Commodity Futures
# 69.50.112.189,72,CBOT Commodity Futures
# 69.50.112.197,74,KRX Futures; BMD Futures and Options
# 69.50.112.204,76,NYMEX and COMEX Metals and Alternative Market Futures
# 69.50.112.167,78,NYMEX Non-Crude Energy Futures
# 69.50.112.187,80,NYMEX Crude Energy Futures
# 69.50.112.179,82,CME Eurodollar Futures
# 69.50.112.198,84,CBOT Treasury Futures
# 69.50.112.169,88,CME Globex FX Futures and Options
# 69.50.112.199,99,AutoCert Segment
macro {
name: "canned_004"
expression: "[CannedCertSession.name, '004']"
}
JetFIX {
rule: "CannedCertSession.name in ['NGG', 'NGF', 'UZE', 'VAE']"
value {
# ES
connection {
name: "cme_canned_64"
platform: GLBX
socket_connect_host_ip: "69.50.112.177"
socket_connect_port: 64530
sender_compid: $canned_004
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"
use_ilink3: true
}
# CL
connection {
name: "cme_canned_80"
platform: GLBX
socket_connect_host_ip: "69.50.112.187"
socket_connect_port: 64530
sender_compid: $canned_004
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"
use_ilink3: true
}
connection {
name: "cme_canned_99"
platform: GLBX
socket_connect_host_ip: "69.50.112.199"
socket_connect_port: 64530
sender_compid: $canned_004
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"
use_ilink3: true
}
}
}
#If no canned cert specified we fallback to just sim
CannedCertSession { value { name: "" }}
JetFIX {value {connection: @JetFIXSimConnection.sim}}
+5 -4
View File
@@ -9,9 +9,9 @@ message JetFIX {
enum JetFIXPlatform {
GLBX = 1;
CBOE = 6;
SIM = 2;
ICE = 3;
SIMICE = 4;
SIM = 2;
ICE = 3;
SIMICE = 4;
}
optional JetFIXPlatform platform = 15 [default = GLBX];
@@ -87,6 +87,7 @@ message JetFIX {
optional uint32 max_connection_attempts = 346 [default=10];
optional bool auto_fix_seq_num = 347 [default=false];
optional bool use_ilink3 = 348 [default=false] ;
}
repeated Connection connection = 10;
@@ -116,4 +117,4 @@ message CMECannedSecureLogon {
"MC8 AbEEtBn63WIAuItPDz1c n3ndjYb03Hx6wBO3me35HoONyDgO5TZKWk0tDSaX9KA 2018-04-05 2019-04-05 CERT \n"
"T39 UWggBgHWAe07aqW3ps2I tbb3it0rUQSSTa0TC9QcRwkrHEMDLWhaJH4VQ0FqGB4 2018-04-05 2019-04-05 NEWRELEASE \n"
];
}
}
+1 -1
View File
@@ -52,7 +52,7 @@ class FIXEncodingStream {
auto msg_offset = _buffer.size();
_current_msg = FIXFragment(_buffer);
_begin_string_bm = _current_msg.add<fix::BeginString>("FIX.4.2");
_begin_string_bm = _current_msg.add<fix::BeginString>(std::string_view {"FIX.4.2"});
_body_length_bm = _current_msg.add<fix::BodyLength>(0, 6);
char mt_encoding[4];
+1
View File
@@ -85,6 +85,7 @@ typedef StringField<307> UnderlyingSecurityDesc;
typedef StringField<336> TradingSessionID;
typedef StringField<35> MsgType;
typedef StringField<37> OrderID;
typedef BigIntField<37> OrderIDu64;
typedef StringField<41> OrigClOrdID;
typedef StringField<440> ClearingAccount;
typedef StringField<48> SecurityID;
+9
View File
@@ -2,6 +2,8 @@
#include <memory>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <string_view>
#include "lib/jetfix/codec/ReaderCursor.h"
#include "lib/utils/meta_programming.h"
#include "lib/utils/datetime.h"
@@ -203,6 +205,13 @@ public:
static std::pair<uint32_t,uint32_t> write (char*buffer,std::string const &str)
{return write (buffer,str.data (),str.size ());}
#if __cplusplus >= 201703L
static uint32_t max_value_size (std::string_view const&str) {return str.size ();}
static std::pair<uint32_t,uint32_t> write (char*buffer,std::string_view const &str)
{return write (buffer,str.data (),str.size ());}
#endif
static std::pair<uint32_t,uint32_t> write (char*buffer,const char*str,uint32_t sz)
{
memcpy (buffer,str,sz);
@@ -23,9 +23,9 @@ SocketConnection::SocketConnection(bts::config::JetFIX::Connection const &cfg,
: _fd(-1), _cfg(cfg), _log(cfg.log_fix_stream()), _in_log(), _out_log(),
_perf_log(perf_log) {
if (_log) {
_in_log.open(std::string("/tmp/fix_raw_read_log_") + session_name(cfg),
_in_log.open(std::string("/tmp/fix_raw_read_log_") + session_name(cfg).as_string,
std::ios_base::app);
_out_log.open(std::string("/tmp/fix_raw_write_log_") + session_name(cfg),
_out_log.open(std::string("/tmp/fix_raw_write_log_") + session_name(cfg).as_string,
std::ios_base::app);
}
}
+28 -29
View File
@@ -783,32 +783,32 @@ OutFIXPtr make_logon(uint32_t seq_num, uint32_t last_seq_num_processed,
const char *application = "O2";
#endif
if(session_cfg.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_ICE ||
session_cfg.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_SIMICE)
{
buffer.add<ICEApplicationSystemName>(application);
buffer.add<ICEApplicationSystemVersion>("1.0");
buffer.add<ICEApplicationSystemVendor>("BTS");
buffer.add<UserName>(session_cfg.user_name());
if (session_cfg.platform() ==
bts::config::JetFIX_Connection_JetFIXPlatform_ICE ||
session_cfg.platform() ==
bts::config::JetFIX_Connection_JetFIXPlatform_SIMICE) {
buffer.add<ICEApplicationSystemName>(std::string_view{application});
buffer.add<ICEApplicationSystemVersion>(std::string_view{"1.0"});
buffer.add<ICEApplicationSystemVendor>(std::string_view{"BTS"});
buffer.add<UserName>(session_cfg.user_name());
buffer.add<RawDataLength>(session_cfg.raw_data().size());
buffer.add<RawData>(session_cfg.raw_data());
buffer.add<RawData>(session_cfg.raw_data());
buffer.add<EncryptMethod>(0);
buffer.add<ICEStrategyPreference>(1);
buffer.add<ICETimeStampPreference>(1);
}
else
{
buffer.add<ApplicationSystemName>(application);
buffer.add<ApplicationSystemVersion>("1.0");
buffer.add<ApplicationSystemVendor>("BTS");
} else {
buffer.add<ApplicationSystemName>(std::string_view{application});
buffer.add<ApplicationSystemVersion>(std::string_view{"1.0"});
buffer.add<ApplicationSystemVendor>(std::string_view{"BTS"});
if (session_cfg.has_trading_session_id()) {
buffer.add<fix::NoTradingSessions>(1);
buffer.add<fix::TradingSessionID>(session_cfg.trading_session_id());
}
if (session_cfg.has_udf_support_indicator())
buffer.add<fix::UDFSupportIndicator>(session_cfg.udf_support_indicator());
buffer.add<fix::UDFSupportIndicator>(
session_cfg.udf_support_indicator());
if (session_cfg.use_cme_secure_logon()) {
bts_assert(session_cfg.sender_compid().size() >= 3);
@@ -819,25 +819,24 @@ OutFIXPtr make_logon(uint32_t seq_num, uint32_t last_seq_num_processed,
std::string last_seq_num_str(9, ' ');
i32_toa(last_seq_num_processed, &last_seq_num_str[0], 9);
auto ld = glbx::calculate_hmac(
session_id, seq_num_str, session_cfg.sender_compid(),
session_cfg.sender_subid(), time_str, session_cfg.target_subid(),
std::to_string(session_cfg.seconds_between_hbs()),
session_cfg.sender_locationid(), last_seq_num_str, application, "1.0",
"BTS");
#ifndef BTS_EDGE
LOG(Jetfix, Info, "Canonical string for secure logon: {}", ld.canonical);
#endif
session_id, seq_num_str, session_cfg.sender_compid(),
session_cfg.sender_subid(), time_str, session_cfg.target_subid(),
std::to_string(session_cfg.seconds_between_hbs()),
session_cfg.sender_locationid(), last_seq_num_str, application,
"1.0", "BTS");
#ifndef BTS_EDGE
LOG(Jetfix, Info, "Canonical string for secure logon: {}",
ld.canonical);
#endif
buffer.add<EncodedTextLen>(ld.access_key.size());
buffer.add<EncodedText>(ld.access_key);
buffer.add<EncryptedPasswordMethod>("CME-1-SHA-256");
buffer.add<EncryptedPasswordMethod>(std::string_view{"CME-1-SHA-256"});
buffer.add<EncryptedPasswordLen>(ld.signature.size());
buffer.add<EncryptedPassword>(ld.signature);
}
else
{
} else {
buffer.add<RawDataLength>(session_cfg.raw_data().size());
buffer.add<RawData>(session_cfg.raw_data());
if(session_cfg.user_name() != "")
if (session_cfg.user_name() != "")
buffer.add<UserName>(session_cfg.user_name());
}
}
+1 -1
View File
@@ -185,7 +185,7 @@ void load_seq_nums(std::string const &path, uint32_t *last_seq_num,
FIXFileStore::FIXFileStore(config::JetFIX::Connection const &cfg,
std::string base_path)
: me(new PImpl(cfg)) {
auto sn = session_name(cfg);
auto sn = session_name(cfg).as_string;
me->active = sn.size() > 0;
if (me->active) {
+19 -14
View File
@@ -75,49 +75,55 @@ bool in_session (datetime::PTime const &ref_date,
return closest_earlier_end<closest_earlier_start;
}
std::string session_name_from_ptime (datetime::PTime t,
SessionName session_name_from_ptime (datetime::PTime t,
boost::posix_time::time_duration time_of_day_start,
boost::posix_time::time_duration time_of_day_end)
{
std::string result (10,' ');
SessionName result;
result.as_string = std::string(10,' ');
auto start_of_session = t;
if (time_of_day_start > time_of_day_end &&
start_of_session.time_of_day () <= time_of_day_end)
start_of_session -= boost::gregorian::date_duration (1);
sprintf (&result[0], "%04d-%02d-%02d",
using namespace boost::posix_time;
ptime epoch(boost::gregorian::date(1970,1,1));
ptime session_start_date(start_of_session.date());
result.as_uint64_t = (session_start_date - epoch).total_milliseconds();
sprintf (&(result.as_string[0]), "%04d-%02d-%02d",
(unsigned short) start_of_session.date ().year (),
start_of_session.date ().month ().as_number (),
start_of_session.date ().day ().as_number ());
return result;
}
std::string session_name (datetime::PTime const &ref_date,
boost::gregorian::greg_weekday weekday_start,
boost::posix_time::time_duration time_of_day_start,
boost::gregorian::greg_weekday weekday_end,
boost::posix_time::time_duration time_of_day_end)
SessionName session_name (datetime::PTime const &ref_date,
boost::gregorian::greg_weekday weekday_start,
boost::posix_time::time_duration time_of_day_start,
boost::gregorian::greg_weekday weekday_end,
boost::posix_time::time_duration time_of_day_end)
{
if (in_session (ref_date,weekday_start,time_of_day_start,weekday_end,time_of_day_end))
return session_name_from_ptime (closest_before (ref_date,weekday_start,time_of_day_start),
boost::posix_time::time_duration(0, 0, 0),
boost::posix_time::time_duration(0, 0, 1));
else
return std::string ();
return {};
}
std::string session_name (datetime::PTime const &ref_date,
SessionName session_name (datetime::PTime const &ref_date,
boost::posix_time::time_duration time_of_day_start,
boost::posix_time::time_duration time_of_day_end)
{
if (in_session (ref_date,time_of_day_start,time_of_day_end))
return session_name_from_ptime (ref_date, time_of_day_start, time_of_day_end);
else
return "";
return {};
}
std::string session_name (config::JetFIX::Connection const &session_cfg)
SessionName session_name (config::JetFIX::Connection const &session_cfg)
{
auto now = datetime::local_now ();
@@ -134,7 +140,6 @@ std::string session_name (config::JetFIX::Connection const &session_cfg)
parse_time (session_cfg.end_time ()));
}
}}
+34 -28
View File
@@ -1,9 +1,9 @@
#pragma once
#include "lib/config/protos/jetfix.pb.h"
#include "lib/utils/datetime.h"
#include <memory>
#include <string>
#include "lib/utils/datetime.h"
#include "lib/config/protos/jetfix.pb.h"
namespace boost {
namespace gregorian {
@@ -11,39 +11,45 @@ class greg_weekday;
}
namespace posix_time {
class time_duration;
}}
}
} // namespace boost
namespace bts {
namespace jetfix {
boost::gregorian::greg_weekday parse_weekday (std::string weekday_str);
bool parse_time (std::string const &time_str,boost::posix_time::time_duration *out);
boost::gregorian::greg_weekday parse_weekday(std::string weekday_str);
bool parse_time(std::string const &time_str,
boost::posix_time::time_duration *out);
datetime::PTime closest_before (datetime::PTime const &ref_date,
boost::gregorian::greg_weekday weekday,
boost::posix_time::time_duration time_of_day);
datetime::PTime closest_before(datetime::PTime const &ref_date,
boost::gregorian::greg_weekday weekday,
boost::posix_time::time_duration time_of_day);
bool in_session (datetime::PTime const &ref_date,
boost::gregorian::greg_weekday weekday_start,
boost::posix_time::time_duration time_of_day_start,
boost::gregorian::greg_weekday weekday_end,
boost::posix_time::time_duration time_of_day_end);
bool in_session(datetime::PTime const &ref_date,
boost::gregorian::greg_weekday weekday_start,
boost::posix_time::time_duration time_of_day_start,
boost::gregorian::greg_weekday weekday_end,
boost::posix_time::time_duration time_of_day_end);
bool in_session (datetime::PTime const &ref_date,
boost::posix_time::time_duration time_of_day_start,
boost::posix_time::time_duration time_of_day_end);
bool in_session(datetime::PTime const &ref_date,
boost::posix_time::time_duration time_of_day_start,
boost::posix_time::time_duration time_of_day_end);
std::string session_name (datetime::PTime const &ref_date,
boost::gregorian::greg_weekday weekday_start,
boost::posix_time::time_duration time_of_day_start,
boost::gregorian::greg_weekday weekday_end,
boost::posix_time::time_duration time_of_day_end);
struct SessionName {
std::string as_string;
uint64_t as_uint64_t;
bool empty() const {return as_string.empty();};
};
std::string session_name (datetime::PTime const &ref_date,
boost::posix_time::time_duration time_of_day_start,
boost::posix_time::time_duration time_of_day_end);
SessionName session_name(datetime::PTime const &ref_date,
boost::gregorian::greg_weekday weekday_start,
boost::posix_time::time_duration time_of_day_start,
boost::gregorian::greg_weekday weekday_end,
boost::posix_time::time_duration time_of_day_end);
SessionName session_name(datetime::PTime const &ref_date,
boost::posix_time::time_duration time_of_day_start,
boost::posix_time::time_duration time_of_day_end);
SessionName session_name(config::JetFIX::Connection const &session_cfg);
std::string session_name (config::JetFIX::Connection const &session_cfg);
}}
} // namespace jetfix
} // namespace bts
+7 -7
View File
@@ -81,9 +81,9 @@ TEST_CASE ("JetFIX Field2Tests", "[jetfix]")
std::string out (20, ' ');
typedef StringField<123> Field;
REQUIRE(Field::max_value_size ("hello")==5);
REQUIRE(Field::max_value_size (std::string_view{"hello"})==5);
auto result = Field::write (&out[0],"hello");
auto result = Field::write (&out[0],std::string_view{"hello"});
REQUIRE (result.first==5);
REQUIRE (result.second=='h'+'e'+'l'+'l'+'o');
REQUIRE (out.compare (0,5,"hello") == 0);
@@ -112,7 +112,7 @@ TEST_CASE ("JetFIX FIXFragmentTests" , "[jetfix]")
FIXFragment g (0);
g.add<CharField<1>> ('a');
g.add<FloatField<2>> (1.2,-1,6);
g.add<StringField<3>> ("hello");
g.add<StringField<3>> (std::string_view{"hello"});
g.add<IntField<4>> (123,3);
const char*t_s = "20150427-19:05:18.922";
g.add<TimeField<5>> (datetime::parse_FIX_timestamp (t_s));
@@ -141,14 +141,14 @@ TEST_CASE ("JetFIX FIXFragmentTests" , "[jetfix]")
FIXFragment g;
auto c_bm = g.add<CharField<1>> ('a');
auto f_bm = g.add<FloatField<2>> (1.2,-1,6);
auto s_bm = g.add<StringField<3>> ("hello");
auto s_bm = g.add<StringField<3>> (std::string_view{"hello"});
auto i_bm = g.add<IntField<4>> (123,3);
auto t_bm = g.add<TimeField<5>> (datetime::parse_FIX_timestamp (t_s1));
auto b_bm = g.add<BoolField<6>> (true);
g.overwrite (c_bm,'b');
g.overwrite (f_bm,1.3,-1,6);
g.overwrite (s_bm,"olleh");
g.overwrite (s_bm,std::string_view {"olleh"});
g.overwrite (i_bm,321,3);
g.overwrite (t_bm,(datetime::parse_FIX_timestamp (t_s2)));
g.overwrite (b_bm,false);
@@ -172,11 +172,11 @@ TEST_CASE ("JetFIX FIXFragmentTests" , "[jetfix]")
FIXFragment g1;;
g1.add<CharField<1>> ('a');
g1.add<FloatField<2>> (1.2,-1,6);
g1.add<StringField<3>> ("hello");
g1.add<StringField<3>> (std::string_view{"hello"});
auto chk1 = g1.checksum ();
FIXFragment g2;
g2.add<StringField<4>> ("goodbye");
g2.add<StringField<4>> (std::string_view{"goodbye"});
g2.add<IntField<5>> (321,3);
auto chk2 = g2.checksum ();
+202 -211
View File
@@ -6,279 +6,270 @@
#include "lib/jetfix/common/OutFIXPtr.h"
#include "lib/jetfix/store/FIXFileStore.h"
#include "lib/jetfix/store/session_name.h"
#include "lib/logging/logging.h"
#include "lib/utils/TempDir.h"
#include "lib/utils/TimeStamp.h"
#include "lib/utils/datetime.h"
#include "lib/logging/logging.h"
#include <boost/date_time.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/filesystem.hpp>
#include <boost/date_time.hpp>
namespace bts {
namespace jetfix {
TEST_CASE ("JetFIX SessionNameTests", "[jetfix]")
{
SECTION("greg_weekday_works")
{
const char*days [] = {"sun","Monday","tuesday","Wedn","Thursday","Friday","sat"};
TEST_CASE("JetFIX SessionNameTests", "[jetfix]") {
SECTION("greg_weekday_works") {
const char *days[] = {"sun", "Monday", "tuesday", "Wedn",
"Thursday", "Friday", "sat"};
int i =0;
int i = 0;
for (auto d : days)
REQUIRE (parse_weekday (d)==boost::gregorian::greg_weekday (i++));
}
SECTION("closest_before_works")
{
auto same_day_before = closest_before (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::gregorian::Friday,
boost::posix_time::time_duration(16, 59, 59));
REQUIRE (datetime::FIX_date_time_string (same_day_before)=="20150717-16:59:59");
auto same_day_after = closest_before (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::gregorian::Friday,
boost::posix_time::time_duration(17,0,1));
REQUIRE (datetime::FIX_date_time_string (same_day_after)=="20150710-17:00:01");
auto another_day_same_week = closest_before (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::gregorian::Thursday,
boost::posix_time::time_duration(16, 59, 59));
REQUIRE (datetime::FIX_date_time_string (another_day_same_week)=="20150716-16:59:59");
auto another_day_previous_week = closest_before (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::gregorian::Saturday,
boost::posix_time::time_duration(16, 59, 59));
REQUIRE (datetime::FIX_date_time_string (another_day_previous_week)=="20150711-16:59:59");
REQUIRE(parse_weekday(d) == boost::gregorian::greg_weekday(i++));
}
SECTION("in_session_works")
{
REQUIRE (in_session (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::gregorian::Sunday,
boost::posix_time::time_duration(16, 59, 59),
boost::gregorian::Friday,
boost::posix_time::time_duration(17, 0, 1)));
SECTION("closest_before_works") {
auto same_day_before =
closest_before(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::gregorian::Friday,
boost::posix_time::time_duration(16, 59, 59));
REQUIRE(datetime::FIX_date_time_string(same_day_before) ==
"20150717-16:59:59");
REQUIRE (!in_session (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::gregorian::Sunday,
boost::posix_time::time_duration(16, 59, 59),
boost::gregorian::Friday,
boost::posix_time::time_duration(16, 59, 59)));
auto same_day_after = closest_before(
datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::gregorian::Friday, boost::posix_time::time_duration(17, 0, 1));
REQUIRE(datetime::FIX_date_time_string(same_day_after) ==
"20150710-17:00:01");
REQUIRE (in_session (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::posix_time::time_duration(16, 59, 59),
boost::posix_time::time_duration(17, 59, 59)));
auto another_day_same_week =
closest_before(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::gregorian::Thursday,
boost::posix_time::time_duration(16, 59, 59));
REQUIRE(datetime::FIX_date_time_string(another_day_same_week) ==
"20150716-16:59:59");
REQUIRE (!in_session (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::posix_time::time_duration(0,0,0),
boost::posix_time::time_duration(16, 0,0)));
REQUIRE (in_session (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)));
REQUIRE (!in_session (datetime::make_ptime (2015,7,17,17,47,0,0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)));
auto another_day_previous_week =
closest_before(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::gregorian::Saturday,
boost::posix_time::time_duration(16, 59, 59));
REQUIRE(datetime::FIX_date_time_string(another_day_previous_week) ==
"20150711-16:59:59");
}
SECTION("session_name_works")
{
REQUIRE (session_name (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::gregorian::Sunday,
boost::posix_time::time_duration(16, 59, 59),
boost::gregorian::Friday,
boost::posix_time::time_duration(17, 0, 1)) ==
"2015-07-12");
SECTION("in_session_works") {
REQUIRE(in_session(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::gregorian::Sunday,
boost::posix_time::time_duration(16, 59, 59),
boost::gregorian::Friday,
boost::posix_time::time_duration(17, 0, 1)));
REQUIRE (session_name (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::gregorian::Sunday,
boost::posix_time::time_duration(16, 59, 59),
boost::gregorian::Friday,
boost::posix_time::time_duration(16, 59, 59)) == "");
REQUIRE(!in_session(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::gregorian::Sunday,
boost::posix_time::time_duration(16, 59, 59),
REQUIRE (session_name (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::posix_time::time_duration(16, 59, 59),
boost::posix_time::time_duration(17, 59, 59)) ==
"2015-07-17");
boost::gregorian::Friday,
boost::posix_time::time_duration(16, 59, 59)));
REQUIRE (session_name (datetime::make_ptime (2015,7,17,18,0,0,0),
boost::posix_time::time_duration(16, 59, 59),
boost::posix_time::time_duration(17, 59, 59)) ==
"");
REQUIRE(in_session(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::posix_time::time_duration(16, 59, 59),
boost::posix_time::time_duration(17, 59, 59)));
REQUIRE (session_name (datetime::make_ptime (2015,7,17,17,0,0,0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)) ==
"2015-07-16");
REQUIRE(!in_session(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::posix_time::time_duration(0, 0, 0),
boost::posix_time::time_duration(16, 0, 0)));
REQUIRE (session_name (datetime::make_ptime (2015,7,17,17,51,0,0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)) ==
"2015-07-17");
REQUIRE (session_name (datetime::make_ptime (2015,7,17,17,47,0,0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)) ==
"");
REQUIRE(in_session(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)));
REQUIRE(!in_session(datetime::make_ptime(2015, 7, 17, 17, 47, 0, 0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)));
}
SECTION("session_name_works") {
REQUIRE(session_name(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::gregorian::Sunday,
boost::posix_time::time_duration(16, 59, 59),
boost::gregorian::Friday,
boost::posix_time::time_duration(17, 0, 1)).as_string ==
"2015-07-12");
REQUIRE(session_name(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::gregorian::Sunday,
boost::posix_time::time_duration(16, 59, 59),
boost::gregorian::Friday,
boost::posix_time::time_duration(16, 59, 59)).as_string == "");
REQUIRE(session_name(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::posix_time::time_duration(16, 59, 59),
boost::posix_time::time_duration(17, 59, 59)).as_string ==
"2015-07-17");
REQUIRE(session_name(datetime::make_ptime(2015, 7, 17, 18, 0, 0, 0),
boost::posix_time::time_duration(16, 59, 59),
boost::posix_time::time_duration(17, 59, 59)).as_string == "");
REQUIRE(session_name(datetime::make_ptime(2015, 7, 17, 17, 0, 0, 0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)).as_string ==
"2015-07-16");
REQUIRE(session_name(datetime::make_ptime(2015, 7, 17, 17, 51, 0, 0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)).as_string ==
"2015-07-17");
REQUIRE(session_name(datetime::make_ptime(2015, 7, 17, 17, 47, 0, 0),
boost::posix_time::time_duration(17, 50, 59),
boost::posix_time::time_duration(17, 45, 59)).as_string == "");
}
}
TEST_CASE ("JetFIX FileStoreTests", "[jetfix]")
{
SECTION("empty_store_works")
{
TEST_CASE("JetFIX FileStoreTests", "[jetfix]") {
SECTION("empty_store_works") {
config::JetFIX::Connection c;
c.set_name ("test");
c.set_sender_compid ("CME");
c.set_sender_subid ("G");
c.set_target_compid ("1U7001N");
c.set_target_subid ("BLUESTREAM");
c.set_name("test");
c.set_sender_compid("CME");
c.set_sender_subid("G");
c.set_target_compid("1U7001N");
c.set_target_subid("BLUESTREAM");
c.set_start_time ("00:00:00");
c.set_end_time ("23:59:59");
c.set_start_time("00:00:00");
c.set_end_time("23:59:59");
utils::TempDir td;
FIXFileStore fs (c,td.name ());
REQUIRE (fs.session_active ());
REQUIRE (fs.replay ().size ()==0);
REQUIRE (fs.last_seq_num ()==0);
REQUIRE (fs.last_seq_num_processed ()==0);
FIXFileStore fs(c, td.name());
REQUIRE(fs.session_active());
REQUIRE(fs.replay().size() == 0);
REQUIRE(fs.last_seq_num() == 0);
REQUIRE(fs.last_seq_num_processed() == 0);
}
SECTION("in_msg_is_stored")
{
auto td = std::make_shared<utils::TempDir> ();
SECTION("in_msg_is_stored") {
auto td = std::make_shared<utils::TempDir>();
config::JetFIX::Connection c;
c.set_name ("test");
c.set_sender_compid ("CME");
c.set_sender_subid ("G");
c.set_target_compid ("1U7001N");
c.set_target_subid ("BLUESTREAM");
c.set_name("test");
c.set_sender_compid("CME");
c.set_sender_subid("G");
c.set_target_compid("1U7001N");
c.set_target_subid("BLUESTREAM");
c.set_start_time ("00:00:00");
c.set_end_time ("23:59:59");
c.set_start_time("00:00:00");
c.set_end_time("23:59:59");
FIXEncodingStream stream (c);
auto &buf = stream.new_msg (MessageTypes::Logon);
buf.add<fix::TargetLocationID> ("US,NC");
buf.add<fix::EncryptMethod> (0);
FIXEncodingStream stream(c);
auto &buf = stream.new_msg(MessageTypes::Logon);
buf.add<fix::TargetLocationID>(std::string_view{"US,NC"});
buf.add<fix::EncryptMethod>(0);
buf.add<fix::HeartBtInt>(30);
buf.add<fix::ApplicationSystemName> ("O2");
buf.add<fix::ApplicationSystemVersion> ("1.0");
buf.add<fix::ApplicationSystemVendor> ("BTS");
stream.close ();
stream.stamp (2,3,datetime::FIX_timestamp (datetime::now ()));
auto fix = stream.to_str ();
buf.add<fix::ApplicationSystemName>(std::string_view{"O2"});
buf.add<fix::ApplicationSystemVersion>(std::string_view{"1.0"});
buf.add<fix::ApplicationSystemVendor>(std::string_view{"BTS"});
stream.close();
stream.stamp(2, 3, datetime::FIX_timestamp(datetime::now()));
auto fix = stream.to_str();
{
FIXFileStore fs (c,td->name ());
fs.store (InMsgBuffer (fix));
fs.set_last_msg_processed (3);
FIXFileStore fs(c, td->name());
fs.store(InMsgBuffer(fix));
fs.set_last_msg_processed(3);
}
FIXFileStore fs (c,td->name ());
auto replay = fs.replay ();
REQUIRE (replay.size ()==1);
REQUIRE (replay[0].type ()==MessageTypes::Logon);
REQUIRE (replay[0].to_str ()==fix);
REQUIRE (fs.last_seq_num ()==0);
REQUIRE (fs.last_seq_num_processed ()==3);
FIXFileStore fs(c, td->name());
auto replay = fs.replay();
REQUIRE(replay.size() == 1);
REQUIRE(replay[0].type() == MessageTypes::Logon);
REQUIRE(replay[0].to_str() == fix);
REQUIRE(fs.last_seq_num() == 0);
REQUIRE(fs.last_seq_num_processed() == 3);
}
SECTION("out_msg_is_stored")
{
auto td = std::make_shared<utils::TempDir> ();
SECTION("out_msg_is_stored") {
auto td = std::make_shared<utils::TempDir>();
config::JetFIX::Connection c;
c.set_name ("test");
c.set_sender_compid ("CME");
c.set_sender_subid ("G");
c.set_target_compid ("1U7001N");
c.set_target_subid ("BLUESTREAM");
c.set_name("test");
c.set_sender_compid("CME");
c.set_sender_subid("G");
c.set_target_compid("1U7001N");
c.set_target_subid("BLUESTREAM");
c.set_start_time ("00:00:00");
c.set_end_time ("23:59:59");
c.set_start_time("00:00:00");
c.set_end_time("23:59:59");
auto msg_vec = std::make_shared<OutFIX>(c);
auto &stream = msg_vec->fix.back ();
auto &buf = stream.new_msg (MessageTypes::Logon);
buf.add<fix::TargetLocationID> ("US,NC");
buf.add<fix::EncryptMethod> (0);
auto &stream = msg_vec->fix.back();
auto &buf = stream.new_msg(MessageTypes::Logon);
buf.add<fix::TargetLocationID>(std::string_view{"US,NC"});
buf.add<fix::EncryptMethod>(0);
buf.add<fix::HeartBtInt>(30);
buf.add<fix::ApplicationSystemName> ("O2");
buf.add<fix::ApplicationSystemVersion> ("1.0");
buf.add<fix::ApplicationSystemVendor> ("BTS");
stream.close ();
stream.stamp (2,3,datetime::FIX_timestamp (datetime::now ()));
buf.add<fix::ApplicationSystemName>(std::string_view{"O2"});
buf.add<fix::ApplicationSystemVersion>(std::string_view{"1.0"});
buf.add<fix::ApplicationSystemVendor>(std::string_view{"BTS"});
stream.close();
stream.stamp(2, 3, datetime::FIX_timestamp(datetime::now()));
{
FIXFileStore fs (c,td->name ());
fs.store (msg_vec);
FIXFileStore fs(c, td->name());
fs.store(msg_vec);
}
FIXFileStore fs (c,td->name ());
auto replay = fs.replay ();
REQUIRE (replay.size ()==0);
REQUIRE (fs.last_seq_num ()==3);
REQUIRE (fs.last_seq_num_processed ()==0);
FIXFileStore fs(c, td->name());
auto replay = fs.replay();
REQUIRE(replay.size() == 0);
REQUIRE(fs.last_seq_num() == 3);
REQUIRE(fs.last_seq_num_processed() == 0);
}
SECTION("test_performance")
{
auto td = std::make_shared<utils::TempDir> ();
SECTION("test_performance") {
auto td = std::make_shared<utils::TempDir>();
config::JetFIX::Connection c;
c.set_name ("test");
c.set_sender_compid ("CME");
c.set_sender_subid ("G");
c.set_target_compid ("1U7001N");
c.set_target_subid ("BLUESTREAM");
c.set_name("test");
c.set_sender_compid("CME");
c.set_sender_subid("G");
c.set_target_compid("1U7001N");
c.set_target_subid("BLUESTREAM");
c.set_start_time ("00:00:00");
c.set_end_time ("23:59:59");
c.set_start_time("00:00:00");
c.set_end_time("23:59:59");
auto start = utils::TimeStamp::now ();
auto start = utils::TimeStamp::now();
{
FIXFileStore fs (c,td->name ());
for (int i = 0; i < 10000;i++) {
FIXFileStore fs(c, td->name());
for (int i = 0; i < 10000; i++) {
auto msg_vec = std::make_shared<std::vector<FIXEncodingStream>>();
msg_vec->emplace_back (c);
auto &stream = msg_vec->back ();
auto &buf = stream.new_msg (MessageTypes::Logon);
buf.add<fix::TargetLocationID> ("US,NC");
buf.add<fix::EncryptMethod> (0);
msg_vec->emplace_back(c);
auto &stream = msg_vec->back();
auto &buf = stream.new_msg(MessageTypes::Logon);
buf.add<fix::TargetLocationID>(std::string_view{"US,NC"});
buf.add<fix::EncryptMethod>(0);
buf.add<fix::HeartBtInt>(30);
buf.add<fix::ApplicationSystemName> ("O2");
buf.add<fix::ApplicationSystemVersion> ("1.0");
buf.add<fix::ApplicationSystemVendor> ("BTS");
stream.close ();
stream.stamp (i,3,datetime::FIX_timestamp (datetime::now () - boost::gregorian::days (1)));
fs.store (InMsgBuffer (stream.to_str ()));
buf.add<fix::ApplicationSystemName>(std::string_view{"O2"});
buf.add<fix::ApplicationSystemVersion>(std::string_view{"1.0"});
buf.add<fix::ApplicationSystemVendor>(std::string_view{"BTS"});
stream.close();
stream.stamp(i, 3,
datetime::FIX_timestamp(datetime::now() -
boost::gregorian::days(1)));
fs.store(InMsgBuffer(stream.to_str()));
}
}
auto stop = utils::TimeStamp::now ();
LOG(Testing,Info,"jetfix store gen: {} ms", (stop-start).milliseconds () );
start = utils::TimeStamp::now ();
FIXFileStore fs (c,td->name ());
stop = utils::TimeStamp::now ();
LOG(Testing,Info,"jetfix store load: {} ms", (stop-start).milliseconds () );
auto stop = utils::TimeStamp::now();
LOG(Testing, Info, "jetfix store gen: {} ms",
(stop - start).milliseconds());
start = utils::TimeStamp::now();
FIXFileStore fs(c, td->name());
stop = utils::TimeStamp::now();
LOG(Testing, Info, "jetfix store load: {} ms",
(stop - start).milliseconds());
}
}
}}
} // namespace jetfix
} // namespace bts
+1
View File
@@ -120,6 +120,7 @@ void configure_logging(bts::config::Logging const&cfg, bts::config::ThreadGroupC
{log::Plugin,"Plugin"},
{log::Sdk,"Sdk"},
{log::Http,"Http"},
{log::iLink3,"ilink3"},
};
real_cfg.sinks["console"] =
+1
View File
@@ -46,6 +46,7 @@ constexpr log::Subsystem DataFlow {Latency.ordinal+1 };
constexpr log::Subsystem Plugin {DataFlow.ordinal+1 };
constexpr log::Subsystem Sdk {Plugin.ordinal+1 };
constexpr log::Subsystem Http {Sdk.ordinal+1 };
constexpr log::Subsystem iLink3 {Http.ordinal+1 };
struct LoggerHandle {
LoggerHandle(LoggerHandle const&) = delete;
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include "lib/utils/ValueWrapper.h"
namespace bts {
using ExchangeSecurityKey = utils::ValueWrapper<struct ExchangeSecurityKeyTag,uint64_t>;
}
+1 -1
View File
@@ -92,7 +92,7 @@ MDConsumer& MDClient::current_consumer() const {
return _self->_consumer;
}
SecurityOracle MDClient::oracle() const {
return SecurityOracle(*this);
return SecurityOracle(_self->_cache);
}
std::set<UserSymbol> MDClient::symbols() const {
return _self->_symbols;
+2 -2
View File
@@ -897,7 +897,7 @@ public:
scan_securities(resolve_legs);
}
SecurityPtr get_security(SecurityKey key) const {
const Security* get_security(SecurityKey key) const {
return _cache.get_security(key);
}
@@ -979,7 +979,7 @@ size_t MDConsumer::walk_security_list(SecurityCallback cb, const string& symbol,
size_t MDConsumer::scan_securities(bool resolve_legs) { return _pimpl->scan_securities(resolve_legs); }
void MDConsumer::on_security(SecurityCallback cb, bool resolve_legs) { _pimpl->on_security(cb, resolve_legs); }
const api::Security* MDConsumer::get_security(SecurityKey key) const { return _pimpl->get_security(key).get(); }
const api::Security* MDConsumer::get_security(SecurityKey key) const { return _pimpl->get_security(key); }
std::vector<api::Security const*> MDConsumer::get_securities() const {return _pimpl->get_securities();}
MDConsumerChannel MDConsumer::get_channel(const std::string& symbol, SecurityType type, Venue exchange) const {
+66 -42
View File
@@ -1,8 +1,10 @@
#include "SecurityCache.h"
#include "SecurityDB.h"
#include "lib/utils/Dispatcher.h"
#include "lib/utils/LockBox.h"
#include <unordered_map>
#include <google/btree/btree_map.h>
#include <tbb/concurrent_queue.h>
#include <mutex>
@@ -10,8 +12,8 @@ namespace bts {
namespace md {
struct SecurityCacheImpl {
std::mutex cache_mutex;
std::unordered_map<SecurityKey, SecurityPtr> cache;
utils::LockBox<btree::btree_map<SecurityKey, SecurityPtr>> cache;
utils::LockBox<btree::btree_map<ExchangeSecurityKey, SecurityPtr>> ex_cache;
tbb::concurrent_queue<SecurityPtr> update_queue;
void enqueue_update_db(const SecurityPtr&);
void flush();
@@ -42,61 +44,83 @@ void SecurityCacheImpl::flush() {
SecurityCache::SecurityCache() : _me(std::make_shared<SecurityCacheImpl>()) {}
SecurityCache::~SecurityCache() {}
SecurityPtr SecurityCache::try_get_security(SecurityKey key) const {
std::lock_guard<std::mutex> lock(_me->cache_mutex);
auto iter = _me->cache.find(key);
if (iter != _me->cache.end()) {
return iter->second;
}
return nullptr;
const Security* SecurityCache::try_get_security(SecurityKey key) const {
return _me->cache.lock([key](btree::btree_map<SecurityKey, SecurityPtr>& t) {
auto iter = t.find(key);
if (iter != t.end()) {
return iter->second.get();
}
return (const api::Security*)nullptr;
});
}
const Security* SecurityCache::try_get_security(ExchangeSecurityKey key) const {
return _me->ex_cache.lock([key](btree::btree_map<ExchangeSecurityKey,SecurityPtr>& t) {
auto iter = t.find(key);
if (iter != t.end()) {
return iter->second.get();
}
return (const api::Security*)nullptr;
});
}
SecurityPtr SecurityCache::get_security(SecurityKey key) {
std::unique_lock<std::mutex> lock(_me->cache_mutex);
auto iter = _me->cache.find(key);
if (iter != _me->cache.end()) {
return iter->second;
}
else {
// unlock for db read
lock.unlock();
const Security* SecurityCache::get_security(SecurityKey key) {
const Security* result = try_get_security(key);
if (result == nullptr) {
// outside lock
auto security = db::find_security(key);
if (security) {
LOG(md,Info, "Loaded security from database: {} {}", security->symbol(), security->id());
return add_db_security(security);
}
return security;
return nullptr;
}
}
std::vector<api::Security const*> SecurityCache::get_securities()
{
std::vector<api::Security const*> result;
result.reserve(100000);
std::unique_lock<std::mutex> lock(_me->cache_mutex);
for (auto const&p : _me->cache)
result.push_back(p.second.get());
return result;
}
SecurityPtr SecurityCache::add_db_security(const SecurityPtr& security) {
std::vector<api::Security const*> SecurityCache::get_securities() {
std::vector<api::Security const*> result;
result.reserve(100000);
_me->cache.lock([&result](auto& cache) {
for (auto const&p : cache) {
result.push_back(p.second.get());
}
});
return result;
}
const Security* SecurityCache::add_db_security(const SecurityPtr& security) {
bts_assert(security);
std::lock_guard<std::mutex> lock(_me->cache_mutex);
SecurityKey key(security->id());
auto result = _me->cache.insert(std::make_pair(SecurityKey(security->id()), security));
// If result was inserted result.first->second is equal to security
// If the value was already present it must be a recently inserted 'live' security and we should use it
return result.first->second;
if (security->has_glbx()) {
_me->ex_cache.lock([&security](auto& cache) {
ExchangeSecurityKey key(security->id());
cache.insert(std::make_pair(key, security));
});
}
return _me->cache.lock([&security](auto& cache) {
SecurityKey key(security->id());
auto result = cache.insert(std::make_pair(key, security));
// If result was inserted result.first->second is equal to security
// If the value was already present it must be a recently inserted 'live' security and we should use it
return result.first->second.get();
});
}
bool SecurityCache::add_live_security(const SecurityPtr& security) {
bts_assert(security);
std::lock_guard<std::mutex> lock(_me->cache_mutex);
SecurityKey key(security->id());
// Insert but don't overwrite existing
auto result = _me->cache.insert(std::make_pair(SecurityKey(security->id()), security));
_me->enqueue_update_db(security);
return result.second;
if (security->has_glbx()) {
_me->ex_cache.lock([&security](auto& cache) {
ExchangeSecurityKey key(security->id());
cache.insert(std::make_pair(key, security));
});
}
return _me->cache.lock([&](auto& cache) {
SecurityKey key(security->id());
// Insert but don't overwrite existing
auto result = cache.insert(std::make_pair(SecurityKey(security->id()), security));
_me->enqueue_update_db(security);
return result.second;
});
}
void SecurityCache::flush_to_disk() { _me->flush(); }
+5 -3
View File
@@ -3,6 +3,7 @@
#include "lib/domain_model/Security.pb.h"
#include "MDConsumerHandle.h"
#include "lib/domain_model/SecurityKey.h"
#include "lib/md/ExchangeSecurityKey.h"
#include "SecurityPtr.h"
#include <memory>
@@ -20,17 +21,18 @@ public:
~SecurityCache();
//Load security from cache with fallback to database
SecurityPtr get_security(SecurityKey key);
const Security* get_security(SecurityKey key);
// Load all securities from cache, no fallback to database
std::vector<api::Security const*> get_securities();
// Get the security if it's in the cache otherwise return nullptr. Does not query security database.
SecurityPtr try_get_security(SecurityKey key) const;
const Security* try_get_security(SecurityKey key) const;
const Security* try_get_security(ExchangeSecurityKey key) const;
// returns true if the cache was updated
bool add_live_security(const SecurityPtr& security);
SecurityPtr add_db_security(const SecurityPtr& security);
const Security* add_db_security(const SecurityPtr& security);
void flush_to_disk();
+7 -3
View File
@@ -4,14 +4,18 @@
namespace bts {
namespace md {
SecurityOracle::SecurityOracle(const MDClient& client): _client(client) {}
SecurityOracle::SecurityOracle(SecurityCache& cache): _cache(cache) {}
SecurityOracle::~SecurityOracle() { }
const api::Security* SecurityOracle::get_security(SecurityKey key) const {
return _client.current_consumer().get_security(key);
return _cache.get_security(key);
}
const api::Security* SecurityOracle::get_security(ExchangeSecurityKey key) const {
return _cache.try_get_security(key);
}
std::vector<api::Security const*> SecurityOracle::get_securities() const {
return _client.current_consumer().get_securities();
return _cache.get_securities();
}
}}//namespace
+5 -2
View File
@@ -1,6 +1,8 @@
#pragma once
#include "lib/domain_model/SecurityKey.h"
#include "lib/md/ExchangeSecurityKey.h"
#include "lib/md/SecurityCache.h"
#include <memory>
#include <vector>
@@ -9,11 +11,12 @@ namespace api {class Security;}
namespace md {
class MDClient;
class SecurityOracle {
const MDClient& _client;
SecurityCache& _cache;
public:
SecurityOracle(const MDClient&);
SecurityOracle(SecurityCache&);
~SecurityOracle();
const api::Security* get_security(SecurityKey key) const;
const api::Security* get_security(ExchangeSecurityKey key) const;
std::vector<api::Security const*> get_securities() const;
};
+16 -2
View File
@@ -10,6 +10,7 @@
#include "lib/persistence/SqliteStore.h"
#include "lib/utils/PBUtils.h"
#include "lib/orderman/actors/SODPosition.h"
#include "lib/utils/overloaded.h"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <sys/time.h>
@@ -119,8 +120,21 @@ void FillStore::on_execution_report(
fill.set_fill_status(api::orderman::Fill::FILL_STATUS_CORRECTED);
fill.set_fill_key(fk);
auto exchange_ts = utils::pb::to_timestamp(
datetime::parse_FIX_timestamp(to_str(er.transact_time)));
auto exchange_ts =
std::visit(overloaded {
[](const orderman::ExchangeTimeStampStr& ts) {
return utils::pb::to_timestamp(
datetime::parse_FIX_timestamp(to_str(ts)));
},
[](ExchangeTimeStamp64 ts) {
google::protobuf::Timestamp gts;
auto seconds = ts.value() / 1E9;
gts.set_seconds(seconds);
gts.set_nanos(ts.value() - (seconds * 1E9));
return gts;
}
}, er.transact_time);
*fill.mutable_timestamp() = exchange_ts;
auto it = me->known_orders.find(er.order_key);
@@ -222,7 +222,9 @@ void GLBXExecutionGateway::on_exe_report(
msg.get<fix::ManualOrderIndicator>()
? api::orderman::MANUAL_ORDER_INDICATOR_YES
: api::orderman::MANUAL_ORDER_INDICATOR_YES;
str_to(msg.get<fix::OrderID>(), &data->exchange_order_id);
str_to(msg.get<fix::OrderID>(),
& std::get<ExchangeOrderID>(
data->exchange_order_id));
if (msg.has<fix::Price>())
data->price = securities::decode_exchange_price(
@@ -261,7 +263,9 @@ void GLBXExecutionGateway::on_exe_report(
: Price(0);
if (msg.has<fix::ExecID>())
str_to(msg.get<fix::ExecID>(), &data->exchange_fill_id);
str_to(msg.get<fix::TransactTimeStr>(), &data->transact_time);
orderman::ExchangeTimeStampStr t;
str_to(msg.get<fix::TransactTimeStr>(), &t);
data->transact_time = t;
if (msg.has<fix::CustOrderHandlingInst>())
data->cust_order_handling_inst = msg.get<fix::CustOrderHandlingInst>();
@@ -18,6 +18,7 @@ class GLBXExecutionGateway : public IExecutionGateway {
void on_securities(const mercury::Update<NewSecuritiesEvent> &) override;
void on_admin_data(const mercury::Update<NewAdminDataEvent> &) override;
void send_fix(jetfix::OutFIXPtr const &fix, trace::CorID trace) override;
void send_msgs(std::vector<OrderMsg> const&, trace::CorID) override {bts_assert(false);}
OnExeReport& on_exe_report() override;
OnGwStatusChange& on_gw_status_change() override;
@@ -0,0 +1,284 @@
#include "lib/orderman/actors/GLBXiLink3ExecutionGateway.h"
#include "lib/config/config.h"
#include "lib/config/protos/orderman_cfg.pb.h"
#include "lib/domain_model/Security.h"
#include "lib/jetfix/common/OutFIX.h"
#include "lib/jetfix/store/session_name.h"
#include "lib/orderman/actors/GLBXExecutionGateway.h"
#include "lib/orderman/actors/ilink3/IL3Reactor.h"
#include "lib/orderman/actors/ilink3/ILinkGW.h"
#include "lib/orderman/actors/ilink3/SessionStore.h"
#include "lib/orderman/events/NewSecuritiesEvent.h"
#include "lib/orderman/orderman_utils/fix_order_codec.h"
#include "lib/orderman/actors/ilink3/IL3MessageFramer.h"
namespace bts {
namespace orderman {
namespace ilink3 {
enum class GLBXiLink3ExecutionGateway::State {
WAITING_FOR_SECURITIES,
PAUSED,
CONNECTING,
READY
};
struct GLBXiLink3ExecutionGateway::PImpl {
PImpl(config::JetFIX::Connection const &cfg, trace::PerfLog &log,
md::SecurityOracle o)
: state(), cfg(cfg), reactor(), start_of_pause(), on_exe_report(),
on_gw_status_change(), on_cancel_reject(), perf_log(log),
sec_oracle(o), securities(), securities_by_descriptor(),
gw_name(cfg.name()), session_store(), gw(), connection(nullptr),
connection_failures(0) {
TCPEndpoint endpoint{cfg.socket_connect_host_ip(),
(ushort)cfg.socket_connect_port()};
connection = &reactor.register_connection({endpoint});
}
State state;
config::JetFIX::Connection const cfg;
IL3Reactor reactor;
IL3MessageFramer framer;
TimeStamp start_of_pause;
OnExeReport on_exe_report;
OnGwStatusChange on_gw_status_change;
orderman::OnCancelReject on_cancel_reject;
trace::PerfLog &perf_log;
md::SecurityOracle sec_oracle;
std::unordered_map<SecurityKey::Value, api::Security const *> securities;
std::unordered_map<std::string, api::Security const *>
securities_by_descriptor;
GatewayName gw_name;
std::optional<SessionStore> session_store;
std::optional<ILinkGW> gw;
IL3Connection *connection;
size_t connection_failures;
};
GLBXiLink3ExecutionGateway::GLBXiLink3ExecutionGateway(
config::JetFIX::Connection const &cfg, trace::PerfLog &log,
md::SecurityOracle o)
: me(new PImpl(cfg, log, o)) {
me->state = State::WAITING_FOR_SECURITIES;
}
GLBXiLink3ExecutionGateway::~GLBXiLink3ExecutionGateway() {}
void GLBXiLink3ExecutionGateway::start() {}
void GLBXiLink3ExecutionGateway::dispatch_incoming_fix_messages() {
switch (me->state) {
case State::WAITING_FOR_SECURITIES:
break;
case State::PAUSED:
on_time();
break;
case State::READY:
case State::CONNECTING:
me->reactor.do_work();
me->gw->on_time();
break;
}
}
void GLBXiLink3ExecutionGateway::on_time() {
bts_assert(me->state == State::PAUSED);
// If we are still paused bail early, this avoids logging too much
// or spending too much CPU
if (pause_in_effect())
return;
me->start_of_pause = Timer::now();
// If we alread exceed the maximum number of failures per run
// bail. This is a safety measure to avoid overwhelming the
// exchange in the event of a bug or operational problem that
// results in repeated connection failures.
if (max_failures_reached()) {
LOG(iLink3, Warn,
"Maximum number of connection failures reached for {}. Reboot to try "
"again",
me->gw_name.value());
return;
}
// If we reach this point we are no longer in the pause window and
// we have not exceed our connection failure limit. The only thing
// to check now is wheter we are inside the exchange's active
// hours.
auto current_session = jetfix::session_name(me->cfg);
if (current_session.empty()) {
LOG(iLink3, Info, "Outside of session in ", me->gw_name.value());
return;
}
// Yep, the stars are all aligned, lets try to connect
connect(current_session);
}
void GLBXiLink3ExecutionGateway::connect(jetfix::SessionName const &sn) {
bts_assert(me->state == State::PAUSED);
transition(State::CONNECTING);
Config c;
c.cme_session = me->cfg.sender_compid().substr(0, 3);
c.firm = me->cfg.sender_compid().substr(3);
c.failover_on_disconnect = false;
me->session_store.emplace(me->sec_oracle, sn, me->cfg);
c.raw_message_logger =
[store = &me->session_store.value()](auto d, auto const &msg) {
store->async_store_raw_msg(d, msg);
};
me->gw.emplace(*me->connection, me->framer, &me->sec_oracle, me->session_store->starting_session_descriptor(), c, me->cfg);
me->gw->subscribe_cancel_reject([this](auto k, auto const &msg) {
bts_assert(me->state == State::READY || me->state == State::CONNECTING);
me->on_cancel_reject(k, msg);
});
me->gw->subscribe_execution_reports([this](auto er) {
bts_assert(me->state == State::READY || me->state == State::CONNECTING);
me->on_exe_report(*er, {});
});
me->gw->subscribe_session([this](auto const &s) {
me->session_store->async_update_session(s);
});
me->gw->subscribe_state([this](auto gw_state) {
LOG(iLink3, Info, "Internal gateway state change in {}. State is now {}",
me->gw_name.value(),
log::CharPtrWrapper{ilink3::state_string(gw_state)});
switch (me->state) {
case State::CONNECTING:
if (gw_state == ilink3::State::READY) {
transition(State::READY);
me->on_gw_status_change(true);
} else if (gw_state == ilink3::State::ERROR) {
me->connection_failures++;
pause();
}
break;
case State::READY:
if (gw_state == ilink3::State::ERROR) {
me->connection_failures++;
pause();
me->on_gw_status_change(false);
}
break;
default:
bts_assert(false);
break;
}
});
me->gw->connect();
}
void GLBXiLink3ExecutionGateway::pause() {
me->start_of_pause = Timer::now();
me->gw.reset();
transition(State::PAUSED);
}
bool GLBXiLink3ExecutionGateway::pause_in_effect() const {
return sec_diff(Timer::now(), me->start_of_pause) <=
me->cfg.seconds_to_pause();
}
bool GLBXiLink3ExecutionGateway::max_failures_reached() const {
return me->connection_failures > me->cfg.max_connection_attempts();
}
void GLBXiLink3ExecutionGateway::on_securities(
const mercury::Update<NewSecuritiesEvent> &update) {
if (update.events) {
for (auto const &ev : *(update.events)) {
auto sec_ptr = ev.security;
me->securities[sec_ptr->id()] = sec_ptr;
me->securities_by_descriptor[securities::descriptor(*sec_ptr)] =
sec_ptr;
}
if (me->state == State::WAITING_FOR_SECURITIES) {
LOG(iLink3, Warn,
"Received first set of {} securities. Proceeding "
"with initialization of execution gateway {}",
update.events->size(), me->gw_name.value());
// got our security synopsis, ready to start the GW
transition(State::PAUSED);
}
}
}
void GLBXiLink3ExecutionGateway::on_admin_data(
const mercury::Update<NewAdminDataEvent> &) {}
void GLBXiLink3ExecutionGateway::send_msgs(std::vector<OrderMsg> const &msgs,
trace::CorID) {
if (me->state == State::READY) {
for (auto &m : msgs) {
// NewOrderSingle
auto create_ptr = std::get_if<CreateOrderMsg>(&m);
if (create_ptr) {
me->gw->send_order(*create_ptr);
break;
}
// CancelReplace
auto cancel_replace_ptr = std::get_if<CancelReplaceOrderMsg>(&m);
if (cancel_replace_ptr) {
me->gw->send_cancel_replace(*cancel_replace_ptr);
break;
}
// Cancel
auto cancel_ptr = std::get_if<CancelOrderMsg>(&m);
if (cancel_ptr) {
me->gw->send_cancel(*cancel_ptr);
break;
}
}
me->gw->flush();
}
}
OnExeReport &GLBXiLink3ExecutionGateway::on_exe_report() {
return me->on_exe_report;
}
OnGwStatusChange &GLBXiLink3ExecutionGateway::on_gw_status_change() {
return me->on_gw_status_change;
}
orderman::OnCancelReject &GLBXiLink3ExecutionGateway::on_cancel_reject() {
return me->on_cancel_reject;
}
log::CharPtrWrapper GLBXiLink3ExecutionGateway::state_name(State st) {
switch (st) {
case State::WAITING_FOR_SECURITIES:
return {"WAITING_FOR_SECURITIES"};
case State::PAUSED:
return {"PAUSED"};
case State::CONNECTING:
return {"CONNECTING"};
case State::READY:
return {"READY"};
}
bts_assert(false);
return {""};
}
void GLBXiLink3ExecutionGateway::transition(State new_state) {
LOG(iLink3, Info, "Transitioning {} from {} to {}", me->gw_name.value(),
state_name(me->state), state_name(new_state));
me->state = new_state;
}
} // namespace ilink3
} // namespace orderman
} // namespace bts
@@ -0,0 +1,48 @@
#pragma once
#include "IExecutionGateway.h"
#include "lib/logging/logging.h"
namespace bts {
namespace jetfix {struct SessionName;}
namespace orderman {
namespace ilink3 {
struct Session;
class GLBXiLink3ExecutionGateway : public IExecutionGateway {
public:
GLBXiLink3ExecutionGateway(config::JetFIX::Connection const &, trace::PerfLog &,
md::SecurityOracle);
virtual ~GLBXiLink3ExecutionGateway();
void start() override;
void dispatch_incoming_fix_messages() override;
void on_securities(const mercury::Update<NewSecuritiesEvent> &) override;
void on_admin_data(const mercury::Update<NewAdminDataEvent> &) override;
void send_fix(jetfix::OutFIXPtr const &, trace::CorID ) override {bts_assert(false);}
void send_msgs(std::vector<OrderMsg> const&, trace::CorID) override;
OnExeReport& on_exe_report() override;
OnGwStatusChange& on_gw_status_change() override;
OnCancelReject &on_cancel_reject() override;
private:
enum class State;
struct PImpl;
std::unique_ptr<PImpl> me;
// Time passing
void on_time();
bool pause_in_effect() const;
bool max_failures_reached()const;
static log::CharPtrWrapper state_name(State);
void transition(State);
void pause();
void connect(jetfix::SessionName const&);
};
} // namespace orderman
} // namespace bts
}
@@ -390,7 +390,9 @@ void ICEExecutionGateway::on_exe_report(const jetfix::fix::ICEExecutionReportMsg
data->manual_order_indicator = api::orderman::MANUAL_ORDER_INDICATOR_NO;
std::string oid_string = get_ice_order_id_string(msg);
str_to(oid_string, &data->exchange_order_id);
str_to(oid_string,
& std::get<ExchangeOrderID>(
data->exchange_order_id));
data->ice_cl_ord_id = 0;
if(msg.has<fix::Int_ClOrdID>())
data->ice_cl_ord_id = msg.get<fix::Int_ClOrdID>();
@@ -438,8 +440,10 @@ void ICEExecutionGateway::on_exe_report(const jetfix::fix::ICEExecutionReportMsg
if (msg.has<fix::TransactTimeStr>())
{
std::string stamp = msg.get<fix::TransactTimeStr>();
stamp.resize(sizeof(mercury::TimeStampStr));
str_to(stamp, &data->transact_time);
stamp.resize(sizeof(orderman::ExchangeTimeStampStr));
orderman::ExchangeTimeStampStr t;
str_to(stamp, &t);
data->transact_time = t;
}
data->cfg = &me->cfg;
data->msg = text_msg;
@@ -17,6 +17,7 @@ class ICEExecutionGateway : public IExecutionGateway {
void on_securities(const mercury::Update<NewSecuritiesEvent> &) override;
void on_admin_data(const mercury::Update<NewAdminDataEvent> &) override;
void send_fix(const jetfix::OutFIXPtr& fix, trace::CorID trace) override;
void send_msgs(std::vector<OrderMsg> const&, trace::CorID) override {bts_assert(false);}
OnExeReport& on_exe_report() override;
OnGwStatusChange& on_gw_status_change() override;
+12 -5
View File
@@ -1,17 +1,24 @@
#include "IExecutionGateway.h"
#include "ICEExecutionGateway.h"
#include "GLBXExecutionGateway.h"
#include "ICEExecutionGateway.h"
#include "lib/utils/ValueWrapper.h"
#include "lib/orderman/actors/GLBXiLink3ExecutionGateway.h"
#include <variant>
namespace bts {
namespace orderman {
std::unique_ptr<IExecutionGateway>
ExecutionGatewayFactory::create_gateway(const config::JetFIX::Connection& conn, trace::PerfLog& pl, md::SecurityOracle o)
{
if(conn.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_ICE ||
conn.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_SIMICE)
ExecutionGatewayFactory::create_gateway(const config::JetFIX::Connection &conn,
trace::PerfLog &pl,
md::SecurityOracle o) {
if (conn.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_ICE ||
conn.platform() == bts::config::JetFIX_Connection_JetFIXPlatform_SIMICE)
return std::make_unique<ICEExecutionGateway>(conn, pl, o);
else if (conn.use_ilink3())
return std::make_unique<ilink3::GLBXiLink3ExecutionGateway>(conn, pl, o);
else
return std::make_unique<GLBXExecutionGateway>(conn, pl, o);
}
+33 -1
View File
@@ -9,6 +9,7 @@
#include "lib/utils/bts_no_copy.h"
#include <memory>
#include <variant>
namespace bts {
namespace trace {struct CorID;class PerfLog;}
@@ -18,6 +19,37 @@ class NewAdminDataEvent;
class ExecutionReport;
struct CreateOrderMsg {
OrderKey key;
Price price;
Quantity quantity;
api::Security const *security;
api::Side side;
Price stop_px;
Quantity display_quantity;
api::orderman::NativeOrderType order_type;
api::orderman::TimeInForce time_in_force;
api::orderman::ManualOrderIndicator manual_order_indicator;
api::orderman::RoutingRecord const *routing_record;
};
struct CancelReplaceOrderMsg {
CreateOrderMsg create_fields;
ExchangeOrderID64 exchange_order_id;
};
struct CancelOrderMsg {
OrderKey key;
ExchangeOrderID64 exchange_order_id;
api::orderman::ManualOrderIndicator manual_order_indicator;
api::Security const *security;
api::orderman::RoutingRecord const *routing_record;
api::Side side;
};
using OrderMsg =
std::variant<CreateOrderMsg, CancelReplaceOrderMsg, CancelOrderMsg>;
using OnGwStatusChange = std::function<void(bool)>;
using OnExeReport = std::function<void(ExecutionReport const &, trace::CorID const &)>;
using OnCancelReject = std::function<void(OrderKey, std::string const &)>;
@@ -33,7 +65,7 @@ class IExecutionGateway {
virtual void on_securities(const mercury::Update<NewSecuritiesEvent> &) = 0;
virtual void on_admin_data(const mercury::Update<NewAdminDataEvent> &) = 0;
virtual void send_fix(const jetfix::OutFIXPtr&, trace::CorID) = 0;
virtual void send_msgs(std::vector<OrderMsg> const&, trace::CorID) = 0;
virtual OnExeReport& on_exe_report() = 0;
virtual OnGwStatusChange& on_gw_status_change() = 0;
virtual OnCancelReject &on_cancel_reject() = 0;
@@ -0,0 +1,20 @@
#pragma once
#include "IL3ConnectionHandler.h"
#include <string>
#include <vector>
namespace bts {
namespace orderman {
namespace ilink3 {
struct IL3Connection {
virtual ~IL3Connection() = default;
virtual void connect(IL3ConnectionHandler&) = 0;
virtual void disconnect() = 0;
// Switch connection but do not connect()
virtual void failover() = 0;
virtual void send(const std::string_view) = 0;
virtual void send(const std::vector<std::string_view>&) = 0;
};
}}}//namespace
@@ -0,0 +1,10 @@
#include "IL3ConnectionHandler.h"
namespace bts {
namespace orderman {
namespace ilink3 {
IL3ConnectionHandler::~IL3ConnectionHandler() = default;
}}}
@@ -0,0 +1,17 @@
#pragma once
#include <cstddef>
#include <string>
namespace bts {
namespace orderman {
namespace ilink3 {
struct IL3ConnectionHandler {
virtual ~IL3ConnectionHandler() ;
virtual void on_connect_success() = 0;
virtual void on_disconnect() = 0;
// Send available data and length. Handler will return what it consumed
virtual size_t on_data(const std::string_view&) = 0;
};
}}}//namespace
@@ -0,0 +1,135 @@
#pragma once
#include <cstdint>
#include "IL3GeneratedFull.h"
#include "IL3MessageFramer.h"
namespace bts {
namespace orderman {
namespace ilink3 {
template <class Handler, class T>
void handle(Handler& h, const char* data, uint16_t len) {
T t {
const_cast<char*>(data),
sizeof(FramingHeader) + iLinkBinary::MessageHeader::encodedLength(),
len,
T::sbeBlockLength(),
T::sbeSchemaVersion() };
h.handle(t);
}
template <class H>
void dispatch_message(H& handler, const FramingHeader* header, const char* data) {
using namespace iLinkBinary;
bts_assert_d(header->encoding_type == 0XCAFE);
MessageHeader mheader {
(char*)data, sizeof(FramingHeader), header->message_size,
MessageHeader::sbeSchemaVersion() };
switch(mheader.templateId()) {
case 501: handle<H, NegotiationResponse501>(handler, data, header->message_size); break;
case 502: handle<H, NegotiationReject502>(handler, data, header->message_size); break;
case 504: handle<H, EstablishmentAck504>(handler, data, header->message_size); break;
case 505: handle<H, EstablishmentReject505>(handler, data, header->message_size); break;
case 506: handle<H, Sequence506>(handler, data, header->message_size); break;
case 507: handle<H, Terminate507>(handler, data, header->message_size); break;
case 509: handle<H, Retransmission509>(handler, data, header->message_size); break;
case 510: handle<H, RetransmitReject510>(handler, data, header->message_size); break;
case 513: handle<H, NotApplied513>(handler, data, header->message_size); break;
case 519: handle<H, PartyDetailsDefinitionRequestAck519>(handler, data, header->message_size); break;
case 521: handle<H, BusinessReject521>(handler, data, header->message_size); break;
case 522: handle<H, ExecutionReportNew522>(handler, data, header->message_size); break;
case 523: handle<H, ExecutionReportReject523>(handler, data, header->message_size); break;
case 524: handle<H, ExecutionReportElimination524>(handler, data, header->message_size); break;
case 525: handle<H, ExecutionReportTradeOutright525>(handler, data, header->message_size); break;
case 526: handle<H, ExecutionReportTradeSpread526>(handler, data, header->message_size); break;
case 527: handle<H, ExecutionReportTradeSpreadLeg527>(handler, data, header->message_size); break;
case 531: handle<H, ExecutionReportModify531>(handler, data, header->message_size); break;
case 532: handle<H, ExecutionReportStatus532>(handler, data, header->message_size); break;
case 534: handle<H, ExecutionReportCancel534>(handler, data, header->message_size); break;
case 535: handle<H, OrderCancelReject535>(handler, data, header->message_size); break;
case 536: handle<H, OrderCancelReplaceReject536>(handler, data, header->message_size); break;
// case 538: handle<H, PartyDetailsListReport538>(handler, data, header->message_size); break;
// The Execution Acknowledgment message notifies CME that a given fill has either been accepted or rejected by a counterparty for EU bilateral trades.
// case 539: handle<H, ExecutionAck539>(handler, data, header->message_size); break;
// case 544: handle<H, NewOrderCross544>(handler, data, header->message_size); break;
// case 545: handle<H, MassQuoteAck545>(handler, data, header->message_size); break;
// case 546: handle<H, RequestForQuoteAck546>(handler, data, header->message_size); break;
// case 547: handle<H, QuoteCancelAck547>(handler, data, header->message_size); break;
case 548: handle<H, ExecutionReportTradeAddendumOutright548>(handler, data, header->message_size); break;
case 549: handle<H, ExecutionReportTradeAddendumSpread549>(handler, data, header->message_size); break;
case 550: handle<H, ExecutionReportTradeAddendumSpreadLeg550>(handler, data, header->message_size); break;
// case 558: handle<H, iLinkBinary::OrderMassActionReport558>(handler, data, header->message_size); break;
// case 561: handle<H, iLinkBinary::SecurityDefinitionResponse561>(handler, data, header->message_size); break;
}
}
template <class H>
void dispatch_execution_reports(H& handler, const FramingHeader* header, const char* data) {
using namespace iLinkBinary;
bts_assert_d(header->encoding_type == 0XCAFE);
MessageHeader mheader {
(char*)data, sizeof(FramingHeader), header->message_size,
MessageHeader::sbeSchemaVersion() };
switch(mheader.templateId()) {
case 522: handle<H, ExecutionReportNew522>(handler, data, header->message_size); break;
case 523: handle<H, ExecutionReportReject523>(handler, data, header->message_size); break;
case 524: handle<H, ExecutionReportElimination524>(handler, data, header->message_size); break;
case 525: handle<H, ExecutionReportTradeOutright525>(handler, data, header->message_size); break;
case 526: handle<H, ExecutionReportTradeSpread526>(handler, data, header->message_size); break;
case 527: handle<H, ExecutionReportTradeSpreadLeg527>(handler, data, header->message_size); break;
case 531: handle<H, ExecutionReportModify531>(handler, data, header->message_size); break;
case 532: handle<H, ExecutionReportStatus532>(handler, data, header->message_size); break;
case 534: handle<H, ExecutionReportCancel534>(handler, data, header->message_size); break;
}
}
// This handler handles exchange messages for testing
template <class H>
void dispatch_exchange_message(H& handler, const FramingHeader* header, const char* data) {
using namespace iLinkBinary;
bts_assert_d(header->encoding_type == 0XCAFE);
MessageHeader mheader {
(char*)data, sizeof(FramingHeader), header->message_size,
MessageHeader::sbeSchemaVersion() };
// Rather than trying to be exhaustive like the client
// we will only add handlers for the messages we use for testing
switch(mheader.templateId()) {
case 500: handle<H, Negotiate500>(handler, data, header->message_size); break;
case 503: handle<H, Establish503>(handler, data, header->message_size); break;
case 506: handle<H, Sequence506>(handler, data, header->message_size); break;
case 508: handle<H, RetransmitRequest508>(handler, data, header->message_size); break;
case 518: handle<H, PartyDetailsDefinitionRequest518>(handler, data, header->message_size); break;
case 514: handle<H, NewOrderSingle514>(handler, data, header->message_size); break;
case 515: handle<H, OrderCancelReplaceRequest515>(handler, data, header->message_size); break;
case 516: handle<H, OrderCancelRequest516>(handler, data, header->message_size); break;
}
}
template <class Handler, class Dispatcher>
size_t consume_messages(
Handler& handler, const char* data, size_t len, Dispatcher dispatch) {
// void(*dispatch)(Handler&, const FramingHeader*, const char*)) {
size_t read = 0;
while(len > sizeof(FramingHeader)) {
// read the FramingHeader
const FramingHeader* header = reinterpret_cast<const FramingHeader*>(data);
// Check if we can consume the message
auto msize = header->message_size;
if (msize <= len) {
read += msize;
dispatch(handler, header, data);
data += msize;
len -= msize;
}
else {
return read;
}
}
return read;
}
}}}//namespace
@@ -0,0 +1,162 @@
#include "IL3ExecutionReportParser.h"
#include "IL3GeneratedFull.h"
#include "ILink3Utils.h"
#include "IL3Dispatcher.h"
#include "lib/md/IntPrice.h"
#include "lib/orderman/orderman_utils/fix_order_codec.h"
namespace bts {
namespace orderman {
namespace ilink3 {
IL3ExecutionReportParser::IL3ExecutionReportParser(config::JetFIX::Connection const &cfg, md::SecurityOracle* o):
oracle(o),
most_recent_account(),
cfg(cfg)
{}
void IL3ExecutionReportParser::cache(const api::Security* security) {
auto id = SecurityKey { security->id() };
if (security_cache.find(id) == security_cache.end()) {
security_cache.insert(std::make_pair(id, security));
}
}
const api::Security* IL3ExecutionReportParser::get_security(SecurityKey id) {
auto iter = security_cache.find(id);
if (iter == security_cache.end()) {
if (oracle) {
return oracle->get_security(id);
}
else return nullptr;
}
return iter->second;
}
template <class T>
void IL3ExecutionReportParser::common(const T& msg, ExecutionReport* data) {
data->account_name = most_recent_account;
static_assert(sizeof(OperatorID) == T::senderIDLength());
memcpy(&data->operator_id.value(), msg.senderID(), msg.senderIDLength());
auto& price = const_cast<T&>(msg).price();
data->exchange = api::VENUE_GLBX;
data->exchange_order_id = ExchangeOrderID64 { msg.orderID() };
data->leg_security = nullptr;
data->manual_order_indicator = map_manual_order_indicator(msg.manualOrderIndicator());
data->msg_seq_num = msg.seqNum();
SecurityKey sk;
decode_clorid(msg.clOrdID(),&data->order_key,&sk);
auto sec = get_security(sk);
bts_assert(sec);
data->security = sec;
//data->security = get_security(ExchangeSecurityKey { (uint64_t) msg.securityID() });
data->order_type = map_order_type(msg.ordType());
data->price = Price { price.mantissa() * md::pow10(price.exponent()) };
data->quantity = Quantity { msg.orderQty() };
data->side = map_side(msg.side());
data->stop_price = Price { 0.0 };
data->time_in_force = map_time_in_force(msg.timeInForce());
data->transact_time = ExchangeTimeStamp64 { msg.transactTime() };
data->ice_cl_ord_id = 0;
data->ice_company_id = 0;
data->cfg = &cfg;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportNew522& msg, ExecutionReport* data) {
common(msg, data);
data->avg_price = Price { 0.0 };
data->cust_order_handling_inst = "";
data->exchange_fill_id = ExchangeFillID { };
data->exec_type = api::orderman::EXEC_TYPE_NEW;
data->filled_quantity = Quantity { 0 };
data->last_price = Price { 0.0 };
data->last_shares = Quantity { 0 };
data->max_show = Quantity { 0 };
data->memo = "";
data->msg = "";
data->order_status = api::orderman::NativeOrderStatus::NATIVE_ORDER_STATUS_NEW;
return true;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportReject523& msg, ExecutionReport* data) {
common(msg, data);
data->order_status = api::orderman::NativeOrderStatus::NATIVE_ORDER_STATUS_REJECTED;
return true;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportElimination524& msg, ExecutionReport* data) {
common(msg, data);
return true;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportTradeOutright525& msg, ExecutionReport* data) {
common(msg, data);
switch(msg.ordStatus()) {
case iLinkBinary::OrdStatusTrd::Filled:
data->order_status = api::orderman::NativeOrderStatus::NATIVE_ORDER_STATUS_FILLED;
break;
case iLinkBinary::OrdStatusTrd::PartiallyFilled:
data->order_status = api::orderman::NativeOrderStatus::NATIVE_ORDER_STATUS_PARTIALLY_FILLED;
break;
default:
data->order_status = api::orderman::NativeOrderStatus::NATIVE_ORDER_STATUS_UNDEFINED;
}
data->last_shares = Quantity { msg.lastQty() };
data->filled_quantity = Quantity { msg.cumQty() };
return true;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportTradeSpread526& msg, ExecutionReport* data) {
common(msg, data);
return true;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportTradeSpreadLeg527& msg, ExecutionReport* data) {
// determine spread security from order key?
(void)msg;
(void)data;
return false;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportModify531& msg, ExecutionReport* data) {
common(msg, data);
return true;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportStatus532& msg, ExecutionReport* data) {
common(msg, data);
// data->order_status = msg.
return true;
}
bool IL3ExecutionReportParser::parse(const iLinkBinary::ExecutionReportCancel534& msg, ExecutionReport* data) {
common(msg, data);
data->order_status = api::orderman::NativeOrderStatus::NATIVE_ORDER_STATUS_CANCELED;
return true;
}
void IL3ExecutionReportParser::set_account(const iLinkBinary::PartyDetailsDefinitionRequestAck519& msg) {
// When using on-demand format the PartyDetailsDefinitionRequestAck519
// is sent back immediately preceding the execution report on the wire.
auto details =const_cast<iLinkBinary::PartyDetailsDefinitionRequestAck519&> (msg).noPartyDetails();
while(details.hasNext()) {
details.next();
if (details.partyDetailRole() == iLinkBinary::PartyDetailRole::CustomerAccount) {
const char* p_account = details.partyDetailID();
strncpy(most_recent_account.value().data(), p_account, most_recent_account.value().size());
break;
}
}
}
struct ParseHandler {
IL3ExecutionReportParser& parser;
ExecutionReport* result;
bool success = false;
template<class T>
void handle(const T& t) { success = parser.parse(t, result); }
void handle(iLinkBinary::PartyDetailsDefinitionRequestAck519& t) { parser.set_account(t); }
};
bool parse_report(const std::string& data, IL3ExecutionReportParser& parser, ExecutionReport* result) {
ParseHandler handler { parser, result };
consume_messages(handler, data.c_str(), data.size(), dispatch_execution_reports<ParseHandler>);
return handler.success;
}
}}}//namespace
@@ -0,0 +1,42 @@
#pragma once
#include "lib/orderman/orderman_utils/ExecutionReport.h"
#include "IL3GeneratedFwd.h"
#include "lib/md/SecurityOracle.h"
#include "lib/md/ExchangeSecurityKey.h"
#include <boost/pool/object_pool.hpp>
#include <google/btree/btree_map.h>
namespace bts {
namespace orderman {
namespace ilink3 {
class IL3ExecutionReportParser {
btree::btree_map<SecurityKey, const api::Security*> security_cache;
md::SecurityOracle* oracle;
AccountName most_recent_account;
config::JetFIX::Connection const cfg;
const api::Security* get_security(SecurityKey);
public:
IL3ExecutionReportParser(config::JetFIX::Connection const &, md::SecurityOracle*);
void cache(const api::Security*);
bool parse(const iLinkBinary::ExecutionReportNew522&, ExecutionReport*);
bool parse(const iLinkBinary::ExecutionReportReject523&, ExecutionReport*);
bool parse(const iLinkBinary::ExecutionReportElimination524&, ExecutionReport*);
bool parse(const iLinkBinary::ExecutionReportTradeOutright525&, ExecutionReport*);
bool parse(const iLinkBinary::ExecutionReportTradeSpread526&, ExecutionReport*);
bool parse(const iLinkBinary::ExecutionReportTradeSpreadLeg527&, ExecutionReport*);
bool parse(const iLinkBinary::ExecutionReportModify531&, ExecutionReport*);
bool parse(const iLinkBinary::ExecutionReportStatus532&, ExecutionReport*);
bool parse(const iLinkBinary::ExecutionReportCancel534&, ExecutionReport*);
void set_account(const iLinkBinary::PartyDetailsDefinitionRequestAck519&);
template <class T> void common(const T&, ExecutionReport*);
};
bool parse_report(const std::string&, IL3ExecutionReportParser&, ExecutionReport*);
}}}//namespace
@@ -0,0 +1,56 @@
#pragma once
//
// Message templates
// BTS -> CME
#include "generated/Negotiate500.h"
#include "generated/Establish503.h"
#include "generated/RetransmitRequest508.h"
#include "generated/NewOrderSingle514.h"
#include "generated/OrderCancelReplaceRequest515.h"
#include "generated/OrderCancelRequest516.h"
// #include "generated/MassQuote517.h"
#include "generated/PartyDetailsDefinitionRequest518.h"
// #include "generated/QuoteCancel528.h"
// #include "generated/OrderMassActionRequest529.h"
// #include "generated/OrderMassStatusRequest530.h"
// #include "generated/OrderStatusRequest533.h"
// #include "generated/PartyDetailsListRequest537.h"
// #include "generated/RequestForQuote543.h"
// #include "generated/SecurityDefinitionRequest560.h"
// CME -> BTS
#include "generated/NegotiationResponse501.h"
#include "generated/NegotiationReject502.h"
#include "generated/EstablishmentAck504.h"
#include "generated/EstablishmentReject505.h"
#include "generated/Sequence506.h"
#include "generated/Terminate507.h"
#include "generated/Retransmission509.h"
#include "generated/RetransmitReject510.h"
#include "generated/NotApplied513.h"
#include "generated/PartyDetailsDefinitionRequestAck519.h"
#include "generated/BusinessReject521.h"
#include "generated/ExecutionReportNew522.h"
#include "generated/ExecutionReportReject523.h"
#include "generated/ExecutionReportElimination524.h"
#include "generated/ExecutionReportTradeOutright525.h"
#include "generated/ExecutionReportTradeSpread526.h"
#include "generated/ExecutionReportTradeSpreadLeg527.h"
#include "generated/ExecutionReportModify531.h"
#include "generated/ExecutionReportStatus532.h"
#include "generated/ExecutionReportCancel534.h"
#include "generated/OrderCancelReject535.h"
#include "generated/OrderCancelReplaceReject536.h"
// #include "generated/PartyDetailsListReport538.h"
#include "generated/ExecutionAck539.h"
// #include "generated/NewOrderCross544.h"
// #include "generated/MassQuoteAck545.h"
// #include "generated/RequestForQuoteAck546.h"
// #include "generated/QuoteCancelAck547.h"
#include "generated/ExecutionReportTradeAddendumOutright548.h"
#include "generated/ExecutionReportTradeAddendumSpread549.h"
#include "generated/ExecutionReportTradeAddendumSpreadLeg550.h"
// #include "generated/OrderMassActionReport558.h"
// #include "generated/SecurityDefinitionResponse561.h"
@@ -0,0 +1,37 @@
#pragma once
namespace iLinkBinary {
class Negotiate500;
class Establish503;
class RetransmitRequest508;
class NewOrderSingle514;
class OrderCancelReplaceRequest515;
class OrderCancelRequest516;
class PartyDetailsDefinitionRequest518;
class NegotiationResponse501;
class NegotiationReject502;
class EstablishmentAck504;
class EstablishmentReject505;
class Sequence506;
class Terminate507;
class Retransmission509;
class RetransmitReject510;
class NotApplied513;
class PartyDetailsDefinitionRequestAck519;
class BusinessReject521;
class ExecutionReportNew522;
class ExecutionReportReject523;
class ExecutionReportElimination524;
class ExecutionReportTradeOutright525;
class ExecutionReportTradeSpread526;
class ExecutionReportTradeSpreadLeg527;
class ExecutionReportModify531;
class ExecutionReportStatus532;
class ExecutionReportCancel534;
class OrderCancelReject535;
class OrderCancelReplaceReject536;
class ExecutionAck539;
class ExecutionReportTradeAddendumOutright548;
class ExecutionReportTradeAddendumSpread549;
class ExecutionReportTradeAddendumSpreadLeg550;
}
@@ -0,0 +1,58 @@
#pragma once
#include <memory>
#include <cstring>
#include "IL3Connection.h"
#include "IL3ReceiveBuffer.h"
#include "generated/MessageHeader.h"
namespace bts {
namespace orderman {
namespace ilink3 {
struct FramingHeader {
uint16_t message_size;
uint16_t encoding_type;
};
class IL3MessageFramer {
std::vector<std::string_view> _buffer_ptrs;
IL3ReceiveBuffer _memory;
public:
IL3MessageFramer():
_buffer_ptrs(), _memory()
{
_buffer_ptrs.reserve(512);
}
~IL3MessageFramer() = default;
//
// Framing
template <class Msg>
Msg frame(size_t extra=0) {
auto size =
sizeof(FramingHeader) +
iLinkBinary::MessageHeader::encodedLength() +
Msg::sbeBlockLength() +
extra;
auto buffer = _memory.allocate(size);
_memory.advance(size);
FramingHeader* fhead = (FramingHeader*)(buffer.data());
fhead->message_size = size;
fhead->encoding_type = 0xCAFE;
Msg msg;
msg.wrapAndApplyHeader(const_cast<char*>(buffer.data()), sizeof(FramingHeader), size+sizeof(FramingHeader));
_buffer_ptrs.push_back(buffer);
return msg;
}
void flush(IL3Connection& connection) {
if (!_buffer_ptrs.empty()) {
connection.send(_buffer_ptrs);
_buffer_ptrs.clear();
}
}
};
}}} //namespace
@@ -0,0 +1,221 @@
#include "IL3Reactor.h"
#include "lib/utils/bts_assert.h"
#include "IL3ReceiveBuffer.h"
#include <arpa/inet.h>
#include <fcntl.h>
#include <fstream>
#include <netinet/tcp.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <array>
#include <queue>
namespace bts {
namespace orderman {
namespace ilink3 {
struct IL3Reactor::Connection : public IL3Connection {
int epoll_fd;
int fd;
bool is_connected;
IL3ConnectionHandler* handler;
std::queue<TCPEndpoint> end_points;
IL3ReceiveBuffer rc_buffer;
Connection(int epoll_fd, const std::vector<TCPEndpoint>& end_points):
epoll_fd(epoll_fd), fd(0), is_connected(false), handler(nullptr),
end_points(std::deque<TCPEndpoint> { end_points.begin(), end_points.end() }),
rc_buffer()
{ }
~Connection() {
if (is_connected) disconnect();
}
void connect(IL3ConnectionHandler& h) override {
bts_assert(!is_connected);
handler = &h;
fd = socket(AF_INET, SOCK_STREAM, 0);
int flag = 1;
auto result = ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
bts_assert(result == 0);
bts_assert(fd >= 0);
struct sockaddr_in serv_addr;
memset(&serv_addr, '0', sizeof(serv_addr));
auto end_point = current_end_point();
auto& host = end_point.host;
auto port = end_point.port;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
result = inet_pton(AF_INET, host.c_str(), &serv_addr.sin_addr);
bts_assert(result > 0);
result = ::connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (result < 0) {
auto er = errno;
char msg[256];
LOG(iLink3, Error, "Failed to connect: {} {}:{}",
std::string(strerror_r(er, msg, sizeof(msg))),host,port);
disconnect();
}
else {
int flag = 1;
result = ::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
sizeof(int));
bts_assert(result == 0);
epoll_event ev;
ev.events = EPOLLIN | EPOLLHUP | EPOLLERR | EPOLLRDHUP;
ev.data.ptr = this;
auto result = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev);
bts_assert_msg(result == 0, "epoll");
is_connected = true;
handler->on_connect_success();
}
}
void disconnect() override {
if (fd) close(fd);
fd = 0;
is_connected = false;
handler->on_disconnect();
}
void send(const std::string_view data) override {
if (!is_connected) {
LOG(iLink3, Error, "Attempted to send on closed connection. {}:{}", current_end_point().host, current_end_point().port);
return;
}
auto result = write(fd, data.data(), data.size());
if (result < 0) {
auto er = errno;
char msg[256];
auto host = current_end_point().host;
auto port = current_end_point().port;
LOG(iLink3, Warn, "Could not write to reactor connection. {}:{}",
std::string(strerror_r(er, msg, sizeof(msg))),host,port);
disconnect();
}
}
void send(const std::vector<std::string_view>& dt) override {
if (!is_connected) {
LOG(iLink3, Error, "Attempted to send on closed connection. {}:{}", current_end_point().host, current_end_point().port);
return;
}
iovec *iv = (iovec*)alloca(sizeof(iovec)*dt.size());
for (size_t i = 0; i < dt.size();i++) {
iv[i].iov_base = (void*)dt[i].data();
iv[i].iov_len = dt[i].size();
}
auto result = ::writev(fd,iv,dt.size());
if (result < 0) {
auto er = errno;
char msg[256];
auto host = current_end_point().host;
auto port = current_end_point().port;
LOG(iLink3, Warn, "Could not write to reactor connection. {}:{}",
std::string(strerror_r(er, msg, sizeof(msg))),host,port);
disconnect();
}
}
void on_data(const std::string_view data) {
bts_assert_d(is_connected);
// Copy input data into a permanent buffer
rc_buffer.append(data);
bts_assert_d(rc_buffer.unread() > 0);
auto read = handler->on_data(rc_buffer.data());
rc_buffer.advance(read);
}
void failover() override {
bts_assert(!is_connected);
next_end_point();
}
TCPEndpoint current_end_point() {
return end_points.front();
}
void next_end_point() {
auto next = end_points.front();
end_points.pop();
end_points.push(next);
}
};
struct IL3Reactor::PImpl {
int epoll_fd = -1;
std::vector<std::unique_ptr<Connection>> connections;
};
IL3Reactor::IL3Reactor() : me(new PImpl()) {
me->epoll_fd = epoll_create(100);
bts_assert(me->epoll_fd >= 0);
}
IL3Reactor::~IL3Reactor() {
me->connections.clear();
close(me->epoll_fd);
me->epoll_fd = -1;
}
IL3Connection& IL3Reactor::register_connection(const std::vector<TCPEndpoint>& end_points) {
me->connections.emplace_back(
std::make_unique<Connection>(me->epoll_fd, end_points));
return *me->connections.back();
}
[[gnu::noinline]]
void non_inline_assert() {
bts_assert(false);
}
constexpr bool has_error(int events) {
return events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP);
}
void IL3Reactor::do_work() {
std::array<epoll_event, 100> ev_list;
auto ready = epoll_wait(me->epoll_fd, ev_list.data(), ev_list.size(), 0);
if (ready == -1) {
if (errno == EINTR) return;
else non_inline_assert();
}
for (int i = 0; i < ready; ++i) {
auto& ev = ev_list[i];
auto handler = (Connection*)(ev.data.ptr);
if (ev.events & EPOLLIN) {
char buffer[4096];
auto sz = read(handler->fd, buffer, sizeof(buffer));
if (sz > 0) {
bts_assert_d(handler->is_connected);
handler->on_data(std::string_view(buffer, sz));
}
else if (has_error(ev.events)) {
handler->disconnect();
}
}
else if (has_error(ev.events)) {
// if EPOLLIN was set along with
// EPOLLHUP/EPOLLERR/EPOLLRDHUP, we pretend it is a normal
// read so that we drain the bytes in the socket. The error
// or hup condition would remain and we would catch in the
// next iteration.
handler->disconnect();
}
}
}
}}} //namespace
@@ -0,0 +1,33 @@
#pragma once
#include "IL3Connection.h"
#include "IL3ConnectionHandler.h"
#include <vector>
#include <memory>
namespace bts {
namespace orderman {
namespace ilink3 {
struct TCPEndpoint {
std::string host;
uint16_t port;
};
class IL3Reactor {
struct PImpl;
struct Connection;
std::unique_ptr<PImpl> me;
public:
IL3Reactor();
~IL3Reactor();
IL3Connection& register_connection(const std::vector<TCPEndpoint>&);
void do_work();
};
}}} //namespace
@@ -0,0 +1,77 @@
#pragma once
#include "lib/utils/bts_assert.h"
#include <string>
#include <vector>
#include <list>
namespace bts {
namespace orderman {
namespace ilink3 {
class IL3ReceiveBuffer {
std::list<std::vector<char>> buffers;
size_t read_pos, write_pos;
size_t buffer_size;
public:
IL3ReceiveBuffer(size_t size = 1024*1024) : buffers(), read_pos(0), write_pos(0), buffer_size(size) {
add_buffer(size);
}
void append(const std::string_view& data) {
auto dest = allocate(data.size());
memcpy(const_cast<char*>(dest.data()), data.data(), data.size());
}
std::string_view allocate(size_t size) {
// If we have enough space append the data
if (size <= available_write_space()) {
char* write_ptr = buffers.back().data() + write_pos;
write_pos += size;
return std::string_view(write_ptr, size);
}
else {
// If we don't have enough space...
// Compute the minimum size of the new buffer
auto min_size = unread() + size;
// allocate a new buffer
const auto& prev_buffer = buffers.back();
auto prev_read = read_pos;
auto prev_write = write_pos;
add_buffer(std::max(buffer_size, min_size));
// copy unread portion of old buffer + the new data into the new buffer
auto unread_sz = prev_write - prev_read;
memcpy(buffers.back().data(), prev_buffer.data()+prev_read, unread_sz);
write_pos = unread_sz;
bts_assert_d(size <= available_write_space());
return allocate(size);
}
}
void advance(size_t consumed) {
read_pos += consumed;
bts_assert_d(read_pos <= write_pos);
}
size_t unread() const {
return write_pos - read_pos;
}
const std::string_view data() const {
return std::string_view(buffers.back().data()+read_pos, unread());
}
private:
size_t available_write_space() const {
return buffers.back().size() - write_pos;
}
void add_buffer(size_t size) {
buffers.emplace_back(std::vector<char>());
buffers.back().resize(size);
read_pos = write_pos = 0;
}
};
}}} //namespace
@@ -0,0 +1,528 @@
#include "ILink3Utils.h"
#include "lib/orderman/orderman_utils/fix_order_codec.h"
#include "lib/utils/base62.h"
namespace bts {
namespace orderman {
namespace ilink3 {
iLinkBinary::SideReq::Value map_side(api::Side side) {
switch (side) {
case api::Side::SIDE_BUY:
return iLinkBinary::SideReq::Buy;
case api::Side::SIDE_SELL:
return iLinkBinary::SideReq::Sell;
default:
return iLinkBinary::SideReq::NULL_VALUE;
}
}
api::Side map_side(iLinkBinary::SideReq::Value side) {
switch (side) {
case iLinkBinary::SideReq::Buy:
return api::Side::SIDE_BUY;
case iLinkBinary::SideReq::Sell:
return api::Side::SIDE_SELL;
default:
return api::Side::SIDE_UNDEFINED;
}
}
iLinkBinary::OrderTypeReq::Value
map_order_type(api::orderman::NativeOrderType ot) {
using namespace api::orderman;
using namespace iLinkBinary;
switch (ot) {
case NativeOrderType::NATIVE_ORDER_TYPE_MARKET:
return OrderTypeReq::MarketwithProtection;
case NativeOrderType::NATIVE_ORDER_TYPE_LIMIT:
return OrderTypeReq::Limit;
case NativeOrderType::NATIVE_ORDER_TYPE_STOP:
return OrderTypeReq::StopwithProtection;
case NativeOrderType::NATIVE_ORDER_TYPE_STOP_LIMIT:
return OrderTypeReq::StopLimit;
case NativeOrderType::NATIVE_ORDER_TYPE_MARKET_LIMIT:
return OrderTypeReq::MarketWithLeftoverAsLimit;
default:
return iLinkBinary::OrderTypeReq::NULL_VALUE;
}
}
api::orderman::NativeOrderType
map_order_type(iLinkBinary::OrderType::Value ot) {
using namespace api::orderman;
using namespace iLinkBinary;
switch (ot) {
case OrderType::MarketWithProtection:
return NativeOrderType::NATIVE_ORDER_TYPE_MARKET;
case OrderType::Limit:
return NativeOrderType::NATIVE_ORDER_TYPE_LIMIT;
case OrderType::StopLimit:
return NativeOrderType::NATIVE_ORDER_TYPE_STOP_LIMIT;
case OrderType::MarketWithLeftoverAsLimit:
return NativeOrderType::NATIVE_ORDER_TYPE_MARKET_LIMIT;
case OrderType::NULL_VALUE:
return NativeOrderType::NATIVE_ORDER_TYPE_UNDEFINED;
}
return NativeOrderType::NATIVE_ORDER_TYPE_UNDEFINED;
}
iLinkBinary::TimeInForce::Value
map_time_in_force(api::orderman::TimeInForce tif) {
using namespace api::orderman;
switch (tif) {
case TimeInForce::TIME_IN_FORCE_DATE:
return iLinkBinary::TimeInForce::GoodTillDate;
case TimeInForce::TIME_IN_FORCE_DAY:
return iLinkBinary::TimeInForce::Day;
case TimeInForce::TIME_IN_FORCE_GTC:
return iLinkBinary::TimeInForce::GoodTillCancel;
case TimeInForce::TIME_IN_FORCE_IOC:
return iLinkBinary::TimeInForce::FillAndKill;
default:
return iLinkBinary::TimeInForce::NULL_VALUE;
}
}
api::orderman::TimeInForce
map_time_in_force(iLinkBinary::TimeInForce::Value tif) {
using namespace api::orderman;
switch (tif) {
case iLinkBinary::TimeInForce::Day:
return TimeInForce::TIME_IN_FORCE_DAY;
case iLinkBinary::TimeInForce::GoodTillCancel:
return TimeInForce::TIME_IN_FORCE_GTC;
case iLinkBinary::TimeInForce::FillOrKill:
return TimeInForce::TIME_IN_FORCE_IOC;
default:
return TimeInForce::TIME_IN_FORCE_UNDEFINED;
}
}
iLinkBinary::ManualOrdIndReq::Value
map_manual_order_indicator(api::orderman::ManualOrderIndicator moi) {
using namespace api::orderman;
using namespace iLinkBinary;
switch (moi) {
case ManualOrderIndicator::MANUAL_ORDER_INDICATOR_NO:
return ManualOrdIndReq::Automated;
case ManualOrderIndicator::MANUAL_ORDER_INDICATOR_YES:
return ManualOrdIndReq::Manual;
default:
return ManualOrdIndReq::NULL_VALUE;
}
}
api::orderman::ManualOrderIndicator
map_manual_order_indicator(iLinkBinary::ManualOrdIndReq::Value moi) {
using namespace api::orderman;
using namespace iLinkBinary;
switch (moi) {
case ManualOrdIndReq::Automated:
return ManualOrderIndicator::MANUAL_ORDER_INDICATOR_NO;
case ManualOrdIndReq::Manual:
return ManualOrderIndicator::MANUAL_ORDER_INDICATOR_YES;
default:
return ManualOrderIndicator::MANUAL_ORDER_INDICATOR_NO;
}
}
iLinkBinary::ClearingAcctType::Value
map_customer_or_firm(api::orderman::CustomerOrFirm c) {
using namespace api::orderman;
using namespace iLinkBinary;
switch (c) {
case CustomerOrFirm::CUSTOMER_OR_FIRM_CUSTOMER:
return ClearingAcctType::Customer;
case CustomerOrFirm::CUSTOMER_OR_FIRM_FIRM:
return ClearingAcctType::Firm;
default:
return ClearingAcctType::NULL_VALUE;
}
}
iLinkBinary::SMPI::Value
map_smp_instruction(api::orderman::SelfMatchPreventionInstruction smpi) {
using namespace api::orderman;
using namespace iLinkBinary;
switch (smpi) {
case SELF_MATCH_PREVENTION_INSTRUCTION_CANCEL_RESTING:
return SMPI::CancelOldest;
case SELF_MATCH_PREVENTION_INSTRUCTION_CANCEL_AGRESSING:
return SMPI::CancelNewest;
default:
return SMPI::NULL_VALUE;
}
}
iLinkBinary::CustOrderCapacity::Value
map_cust_cti(api::orderman::CTICode code) {
using namespace api::orderman;
using namespace iLinkBinary;
switch (code) {
case CTI_CODE_CTI_CODE1:
return CustOrderCapacity::Membertradingfortheirownaccount;
case CTI_CODE_CTI_CODE2:
return CustOrderCapacity::Clearingfirmtradingforitsproprietaryaccount;
case CTI_CODE_CTI_CODE3:
return CustOrderCapacity::Membertradingforanothermember;
case CTI_CODE_CTI_CODE4:
return CustOrderCapacity::Allother;
default:
case CTI_CODE_UNDEFINED:
return CustOrderCapacity::NULL_VALUE;
}
}
const char *translate_business_reject_reason(int reason) {
switch (reason) {
case 0:
return "Other";
case 1:
return "Unknown ID (unknown PartyDetailsListReqID being referenced in "
"business message)";
case 2:
return "Unknown Security";
case 3:
return "Unsupported Message Type (for example using messages specific to "
"cash markets for futures)";
case 5:
return "Required Field Missing";
case 6:
return "Not Authorized";
case 8:
return "Throttle Limit Exceeded (volume controls)";
case 100:
return "Value is incorrect (out of range) for this tag (for example "
"using a value outside defined range of integer) ";
case 101:
return "Incorrect data format for value (for example using ASCII "
"character outside 32-126 in string field)";
case 102:
return "Rejected due to Kill Switch";
case 103:
return "Rejected due to Risk Management API";
case 104:
return "Rejected due to Globex Credit Controls";
case 105:
return "Not Authorized to trade Deliverable Swap Futures";
case 106:
return "Not Authorized to trade Interest Rate Swap Futures";
case 107:
return "Rejected due to Inline Credit Controls";
case 108:
return "Invalid PartyDetailsListReqID (reusing already existing "
"PartyDetailsListReqID while creating Party Details Definition "
"Request)";
case 109:
return "Incoming message could not be decoded. (Check schema version)";
case 110:
return "Same repeating group entry appears more than once";
case 111:
return "Exceeded maximum number of allowable Party Details Definition "
"Requests";
case 112:
return "Technical Error in Registering Party Details";
case 113:
return "Rejected due to Cross Venue Risk";
case 114:
return "Order Status Not Available";
case 115:
return "Enum Not Supported";
case 116:
return "Order Status Not Found";
case 117:
return "Mass Order Status Cannot be Completed";
case 118:
return "Exceeded Maximum Number of Allowable RequestingPartyID's in "
"Party Details List Request";
case 119:
return "Duplicate Order Threshold Exceeded";
case 120:
return "On-Demand Message Rejected Due to Preceding Party Details "
"Definition Request Being Rejected";
case 121:
return "Message Rejected Since PartyDetailsListReqID Does Not Match with "
"Immediately Preceding Party Details Definition Request sent to "
"MSGW when using On-demand administrative information";
case 122:
return "Party Details Definition Request sent to MSGW Being Rejected Due "
"to Corresponding Business Message Being Rejected";
case 123:
return "Another Message Sent in Between Party Details Definition Request "
"and Business Message when using On-demand administrative "
"information";
case 124:
return "Cannot Have More Than One In-Flight Mass Order Status Request in "
"Progress";
case 125:
return "Exceeded Maximum Number of In-Flight Order Status Requests";
case 126:
return "Cannot Have More Than One In-Flight Party Details List Request "
"in Progress";
case 127:
return "Party Details List Request is Missing Requesting Party ID and "
"Party ID";
case 128:
return "Party Details List Request cannot contain both RequestingPartyID "
"and PartyID";
case 129:
return "Party Details Definition Request Being Rejected Since Another "
"Message was sent in Between On-Demand Message";
case 130:
return "Buy Side Firm ID Does Not Match Sell Side Firm ID in New Order "
"Cross";
case 131:
return "Message Type Not Supported on Backup Instance";
case 132:
return "New Order Cross Does Not Contain Buy Side Followed by Sell Side";
}
return "Unknown or invalid business reject reason.";
}
const char *translate_negotiation_reject(int reason) {
// https://www.cmegroup.com/confluence/display/EPICSANDBOX/Negotiation+Reject
// 01/13/2020
switch (reason) {
case 0:
return "HMACNotAuthenticated: failed authentication because identity is "
"not recognized";
case 1:
return "HMACNotAvailable: HMAC component is not responding (5sec)";
case 2:
return "InvalidUUID: UUID is not greater than the one last used or value "
"sent by the client is out of acceptable range (MIN, MAX)";
case 3:
return "InvalidTimestamp: Timestamp is not greater than the one last "
"used or value sent by the client is out of acceptable range "
"(MIN, MAX)";
case 4:
return "RequiredHMACSignatureMissing: empty bytes in HMACSignature field";
case 5:
return "RequiredAccessKeyIDMissing: empty bytes in AccessKeyID field";
case 6:
return "RequiredSessionMissing: empty bytes in Session field";
case 7:
return "RequiredFirmMissing: empty bytes in Firm field";
case 8:
return "RequiredUUIDMisssing: null value in UUID field";
case 9:
return "RequiredRequestTimestampMissing: null value in RequestTimestamp "
"field";
case 10:
return "SessionBlocked: session and firm are not authorized for this "
"port";
case 12:
return "InvalidAccessKeyID: contains non-printable ASCII character";
case 13:
return "InvalidSession: contains non-printable ASCII character";
case 14:
return "InvalidFirm: contains non-printable ASCII character";
case 15:
return "Volume Controls - exceeding TPS limit as defined for volume "
"controls (reject action)";
case 16:
return "SplitMessageRejected - Messages queued due to split message "
"penalty being rejected because of logout or disconnect";
case 17:
return "SplitMessageQueue - Reached threshold of messages queued due to "
"split message penalty";
case 27:
return "DesignatedBackup - Using Designated backup before designated "
"primary not allowed";
}
return "Unknown or invalid Negotiate reject reason.";
}
const char *translate_establish_reject(int reason) {
switch (reason) {
case 0:
return "HMACNotAuthenticated: failed authentication because identity is "
"not recognized";
case 1:
return "HMACNotAvailable: HMAC component is not responding (5sec)";
case 2:
return "InvalidUUID: UUID is not greater than the one last used or value "
"sent by the client is out of acceptable range (MIN, MAX)";
case 3:
return "InvalidTimestamp: Timestamp is not greater than the one last "
"used or value sent by the client is out of acceptable range "
"(MIN, MAX)";
case 4:
return "RequiredHMACSignatureMissing: empty bytes in HMACSignature field";
case 5:
return "RequiredAccessKeyIDMissing: empty bytes in AccessKeyID field";
case 6:
return "RequiredSessionMissing: empty bytes in Session field";
case 7:
return "RequiredFirmMissing: empty bytes in Firm field";
case 8:
return "RequiredUUIDMisssing: null value in UUID field";
case 9:
return "RequiredRequestTimestampMissing: null value in RequestTimestamp "
"field";
case 10:
return "SessionBlocked: session and firm are not authorized for this "
"port";
case 11:
return "InvalidKeepAliveInterval: value is out of acceptable range (MIN, "
"MAX)";
case 12:
return "InvalidAccessKeyID: contains non-printable ASCII character";
case 13:
return "InvalidSession: contains non-printable ASCII character";
case 14:
return "InvalidFirm: contains non-printable ASCII character";
case 15:
return "Volume Controls - exceeding TPS limit as defined for volume "
"controls (reject action)";
case 16:
return "SplitMessageRejected - Messages queued due to split message "
"penalty being rejected because of logout or disconnect";
case 17:
return "SplitMessageQueue - Reached threshold of messages queued due to "
"split message penalty";
case 18:
return "RequiredTradingSystemNameMissing: empty bytes in "
"TradingSystemName";
case 19:
return "RequiredTradingSystemVersionMissing: empty bytes in "
"TradingSystemVersion";
case 20:
return "RequiredTradingSystemVendorMissing: empty bytes in "
"TradingSystemVendor";
case 21:
return "RequiredKeepAliveIntervalMissing: null value in "
"KeepAliveInterval field";
case 22:
return "RequiredNextSeqNoMissing: empty bytes in NextSeqNo field";
case 23:
return "InvalidTradingSystemName: contains non-prinatable ASCII "
"character";
case 24:
return "InvalidTradingSystemVersion: contains non-prinatable ASCII "
"character";
case 25:
return "InvalidTradingSystemVendor: contains non-prinatable ASCII "
"character";
case 26:
return "DesignatedBackup - Using Designated backup before designated "
"primary not allowed";
case 27:
return "DesignatedBackup - Using Designated backup before designated "
"primary not allowed";
}
return "Unknown or invalid Establish reject reason.";
}
const char *translate_terminate(int reason) {
switch (reason) {
case 0:
return "Finished: session is being terminated without finalization";
case 2:
return "Unnegotiated: Sending any message when session has not been "
"Negotiated ";
case 3:
return "NotEstablished: Sending any message (except Negotiate) when "
"session has not been established";
case 4:
return "AlreadyNegotiated: NegotiationResponse was already sent; "
"Negotiate was redundant";
case 5:
return "NegotiationInProgress: Previous Negotiate still being processed; "
"Wait for NegotiationResponse or timeout";
case 6:
return "AlreadyEstablished: EstablishmentAck was already sent; Establish "
"was redundant";
case 7:
return "EstablishInProgress: Previous Establish still being processed; "
"Wait for EstablishmentAck or timeout";
case 8:
return "CMEAdministeredPortClosure: due to invalid number of "
"Negotiate/Establish attempts being exceeded";
case 9:
return "Volume Controls - exceeding TPS limit as defined for volume "
"controls (logout action)";
case 10:
return "InvalidNextSeqNo - value is not greater than the one last used "
"for same UUID or value sent by the client is out of acceptable "
"range (MIN, MAX)";
case 11:
return "InvalidMsgSeqNo - value is lower than the last one used for the "
"same UUID or value is not initialized to 1 at the beginning of "
"the week or value sent by the client is out of acceptable range "
"(MIN, MAX)";
case 12:
return "InvalidLastSeqNo - value is lower than the last one used for the "
"same UUID or value sent by the client is out of acceptable range "
"(MIN, MAX)";
case 13:
return "InvalidUUID: UUID value does not match current UUID or value "
"sent by the client is out of acceptable range (MIN, MAX)";
case 14:
return "InvalidTimestamp: Timestamp value does not match with "
"RequestTimestamp sent by CME or value sent by the client is out "
"of acceptable range (MIN, MAX)";
case 15:
return "RequiredUUIDMisssing: null value in UUID field";
case 16:
return "RequiredRequestTimestampMissing: null value in RequestTimestamp "
"field";
case 17:
return "RequiredCodeMisssing: null value in Code field";
case 18:
return "InvalidSOFH: Invalid message length or invalid encoding type "
"specified";
case 19:
return "DecodingError: Incoming message could not be decoded";
case 20:
return "KeepAliveIntervalLapsed: KeepAliveInterval has lapsed without "
"any response so terminating session";
case 21:
return "RequiredNextSeqNoMissing: null value in NextSeqNo field";
case 22:
return "RequiredKeepAliveIntervalLapsedMissing: null value in "
"KeepAliveIntervalLapsed field";
case 23:
return "Non-Negotiate/Establish message received when not "
"Negotiated/Established";
case 24:
return "TerminateInProgress: Previous Terminate still being processed; "
"Wait for Terminate or timeout";
case 25:
return "Other: any other error condition not mentioned above";
case 26:
return "DisconnectFromPrimary: Backup session will be terminated as "
"well}";
default:
return "Unknown error";
}
}
} // namespace ilink3
} // namespace orderman
} // namespace bts
@@ -0,0 +1,51 @@
#pragma once
#include "lib/domain_model/common.h"
#include "lib/domain_model/Security.pb.h"
#include "lib/api/services/OrderService.pb.h"
#include "lib/orderman/orderman_utils/orderman_common.h"
#include "generated/SideReq.h"
#include "generated/OrderTypeReq.h"
#include "generated/OrderType.h"
#include "generated/TimeInForce.h"
#include "generated/ManualOrdInd.h"
#include "generated/ManualOrdIndReq.h"
#include "generated/ClearingAcctType.h"
#include "generated/SMPI.h"
#include "generated/CustOrderCapacity.h"
#include <tuple>
namespace bts {
namespace orderman {
namespace ilink3 {
iLinkBinary::SideReq::Value map_side(api::Side side);
api::Side map_side(iLinkBinary::SideReq::Value side);
inline int64_t to_price9(Price p) {
return p.value() * 1E9;
}
iLinkBinary::OrderTypeReq::Value map_order_type(api::orderman::NativeOrderType ot);
api::orderman::NativeOrderType map_order_type(iLinkBinary::OrderType::Value);
iLinkBinary::TimeInForce::Value map_time_in_force(api::orderman::TimeInForce);
api::orderman::TimeInForce map_time_in_force(iLinkBinary::TimeInForce::Value);
iLinkBinary::ManualOrdIndReq::Value map_manual_order_indicator(api::orderman::ManualOrderIndicator moi);
api::orderman::ManualOrderIndicator map_manual_order_indicator(iLinkBinary::ManualOrdIndReq::Value moi);
iLinkBinary::ClearingAcctType::Value map_customer_or_firm(api::orderman::CustomerOrFirm c);
iLinkBinary::SMPI::Value map_smp_instruction(api::orderman::SelfMatchPreventionInstruction smpi);
iLinkBinary::CustOrderCapacity::Value map_cust_cti(api::orderman::CTICode code);
const char* translate_business_reject_reason(int reason) ;
const char* translate_negotiation_reject(int reason) ;
const char* translate_establish_reject(int reason) ;
const char* translate_terminate(int reason) ;
}}}//namespace
+645
View File
@@ -0,0 +1,645 @@
#include "ILinkGW.h"
#include "lib/utils/bts_assert.h"
#include "lib/utils/SecureLogon.h"
#include "ILink3Utils.h"
#include "IL3GeneratedFull.h"
#include "IL3Dispatcher.h"
#include "IL3MessageFramer.h"
#include "lib/utils/datetime.h"
#include "lib/orderman/orderman_utils/fix_order_codec.h"
/*
# Some notes about session binding and initialization: #
## Official documentation:
https://www.cmegroup.com/confluence/display/EPICSANDBOX/iLink+3+Binary+Order+Entry+-+Session+Layer#iLink3BinaryOrderEntry-SessionLayer-WeeklyReset
## Begining of week (new session?)
- config.session = X
- config.outgoing_sequence = 1
-> Negotiate session=X
<- NegotiateResponse session=X, oldsession=Y, oldSeq=N
if oldSeq > 0 -> ReplayRequest
-> Establish seq=1
<- EstablishAck oldsession=Y, oldSeq=N
## Middle of week (same session)
- config.session = X
- config.outgoing_sequence > 1
-> Establish seq=N
*/
namespace bts {
namespace orderman {
namespace ilink3 {
log::CharPtrWrapper wrap(const char* str) { return log::CharPtrWrapper{ str }; }
ILinkGW::ILinkGW(
IL3Connection& con,
IL3MessageFramer& buffer,
md::SecurityOracle* oracle,
const Session& session,
const Config& conf,
config::JetFIX::Connection const & cfg) :
_config(conf),
_x_state(State::INIT),
_buffer(buffer),
_on_state_change([](auto){}),
_on_exe_report([](auto*){}),
_on_session_change([](auto){}),
_connection(con),
_session(session),
_msg_count(0),
_time(),
_pool(),
_exe_parser(cfg,oracle),
_retransmit()
{
_clorid_buffer.resize(clordid_sz());
}
void ILinkGW::connect() {
bts_assert(state() == State::INIT || state() == State::ERROR);
set_state(State::CONNECTING);
_connection.connect(*this); // -> on_connect_success
}
// This determines the session uuid
void ILinkGW::send_negotiate() {
// add 2 bytes for the empty 'credentials' (39008) length which must be present
auto msg = _buffer.frame<iLinkBinary::Negotiate500>(
iLinkBinary::Negotiate500::credentialsHeaderLength());
msg.uUID(_session.uuid);
msg.requestTimestamp(_time.now());
msg.putSession(_config.cme_session);
// We need this call to set the length of the credential block to 0
// This behavior is specific to "data" in the xml template
msg.putCredentials("", 0);
msg.putFirm(_config.firm);
const auto ld = glbx::calculate_hmac(
_config.cme_session,
std::to_string(msg.requestTimestamp()),
std::to_string(msg.uUID()),
_config.cme_session,
_config.firm
);
msg.putAccessKeyID(ld.access_key);
msg.putHMACSignature(ld.hmac);
std::string temp = ld.canonical;
for (size_t x = 0; x < temp.size(); ++x) { if (temp[x] == '\n') temp[x] = '$'; }
flush(false);
// clear HMAC for json logging
msg.putHMACSignature(std::string_view { nullptr, 0 });
log_out(msg);
// expect -> NegotiationResponse501 or NegotiationReject502
}
void ILinkGW::send_establish() {
// add 2 bytes for the empty 'credentials' (39008) length which must be present
auto msg = _buffer.frame<iLinkBinary::Establish503>(2);
msg.uUID(_session.uuid);
msg.requestTimestamp(_time.now());
msg.putSession(_config.cme_session);
msg.putCredentials("", 0);
msg.putFirm(_config.firm);
msg.putTradingSystemName(std::string_view("SPARK"));
msg.putTradingSystemVersion(std::string_view("1"));
msg.putTradingSystemVendor(std::string_view("BTS"));
// On primary connection, the expected message sequence number of the next business message from customer to CME
msg.nextSeqNo(_session.to_cme);
msg.keepAliveInterval(30000);
const auto ld = glbx::calculate_hmac(
_config.cme_session,
// RequestTimestamp
std::to_string(msg.requestTimestamp()),
std::to_string(msg.uUID()),
_config.cme_session,
// Firm ID
_config.firm,
// TradingSystemName
msg.getTradingSystemNameAsString(),
// TradingSystemVersion
msg.getTradingSystemVersionAsString(),
// TradingSystemVendor
msg.getTradingSystemVendorAsString(),
// NextSeqNo
std::to_string(msg.nextSeqNo()),
// KeepAliveInterval
std::to_string(msg.keepAliveInterval())
);
msg.putAccessKeyID(ld.access_key);
msg.putHMACSignature(ld.hmac);
flush(false);
// clear HMAC for json logging
msg.putHMACSignature(std::string_view { nullptr, 0 });
log_out(msg);
// expect -> EstablishmentAck504 or EstablishmentReject505
}
void ILinkGW::send_sequence(bool lapsed) {
auto msg = _buffer.frame<iLinkBinary::Sequence506>();
msg.uUID(_session.uuid);
msg.nextSeqNo(_session.to_cme);
msg.faultToleranceIndicator(iLinkBinary::FTI::NULL_VALUE);
msg.keepAliveIntervalLapsed(
lapsed ?
iLinkBinary::KeepAliveLapsed::Lapsed :
iLinkBinary::KeepAliveLapsed::NotLapsed);
log_out(msg);
}
void ILinkGW::send_retransmit_request(uint64_t uuid, uint32_t from, size_t count) {
bts_assert(from > 0);
using namespace iLinkBinary;
auto msg = _buffer.frame<RetransmitRequest508>();
msg.uUID(_session.uuid);
msg.lastUUID(uuid);
msg.requestTimestamp(_time.now());
msg.fromSeqNo(from);
msg.msgCount(count);
log_out(msg);
}
uint64_t ILinkGW::send_party_details(const api::orderman::RoutingRecord& route) {
using namespace iLinkBinary;
auto msg = _buffer.frame<PartyDetailsDefinitionRequest518>(
// 2 repeating group header.
// 1 for party details and 1 for trade reg
// This seems unsafe but the api doesn't seem to want you to know how to size buffers ahead of time
2 * PartyDetailsDefinitionRequest518::NoPartyDetails::sbeHeaderSize() +
// N * size of each block
3 * PartyDetailsDefinitionRequest518::NoPartyDetails::sbeBlockLength() +
0 * PartyDetailsDefinitionRequest518::NoTrdRegPublications::sbeBlockLength()
);
msg.partyDetailsListReqID(0);
msg.sendingTimeEpoch(_time.now());
msg.listUpdateAction(ListUpdAct::Add);
msg.seqNum(next_seq());
// msg.putMemo("") -- not supported
if (route.smp_id().empty()) {
msg.selfMatchPreventionID(
PartyDetailsDefinitionRequest518::selfMatchPreventionIDNullValue());
}
else {
// CME needs the SMP_ID to be 12 characters or less
// after they to_string() the uint64
bts_assert_d(route.smp_id().size() == 8);
const uint64_t* psmp_id = reinterpret_cast<const uint64_t*>(&route.smp_id());
uint64_t smp_id = (*psmp_id) % (2UL<<39);
msg.selfMatchPreventionID(smp_id);
}
msg.cmtaGiveupCD(CmtaGiveUpCD::NULL_VALUE);
msg.custOrderCapacity(map_cust_cti(route.cti_code()));
msg.clearingAccountType(map_customer_or_firm(route.customer_or_firm()));
msg.selfMatchPreventionInstruction(map_smp_instruction(route.smp_instruction()));
msg.avgPxIndicator(AvgPxInd::NULL_VALUE);
msg.clearingTradePriceType(SLEDS::NULL_VALUE);
msg.custOrderHandlingInst(
static_cast<iLinkBinary::CustOrdHandlInst::Value>(
route.cust_order_handing_inst()[0]));
msg.executor(PartyDetailsDefinitionRequest518::executorNullValue());
msg.iDMShortCode(PartyDetailsDefinitionRequest518::iDMShortCodeNullValue());
auto details = msg.noPartyDetailsCount(3);
details.next();
details.partyDetailRole(PartyDetailRole::CustomerAccount);
details.putPartyDetailID(route.account());
details.next();
details.partyDetailRole(PartyDetailRole::ExecutingFirm);
// 004 in cert
details.putPartyDetailID(
std::string_view(route.sender_compid().c_str()+3, 3));
details.next();
details.partyDetailRole(PartyDetailRole::Operator);
details.putPartyDetailID(
std::string_view(route.sender_compid().c_str(), 3));
msg.noTrdRegPublicationsCount(0);
// In the future we may check for existing party details definitions and return that id
log_out(msg);
return 0;
}
bool needs_stop_px(api::orderman::NativeOrderType order_type) {
return order_type == api::orderman::NativeOrderType::NATIVE_ORDER_TYPE_STOP ||
order_type == api::orderman::NativeOrderType::NATIVE_ORDER_TYPE_STOP_LIMIT;
}
bool need_px(api::orderman::NativeOrderType order_type) {
return order_type != api::orderman::NativeOrderType::NATIVE_ORDER_TYPE_MARKET &&
order_type != api::orderman::NativeOrderType::NATIVE_ORDER_TYPE_MARKET_LIMIT &&
order_type != api::orderman::NativeOrderType::NATIVE_ORDER_TYPE_STOP;
}
void ILinkGW::send_order(const CreateOrderMsg& create) {
bts_assert_d(create.routing_record);
bts_assert_d(create.security);
bts_assert_d(create.security->has_glbx());
auto party = send_party_details(*create.routing_record);
auto msg = _buffer.frame<iLinkBinary::NewOrderSingle514>();
if (need_px(create.order_type)) { msg.price().mantissa(to_price9(create.price)); }
else { msg.price().mantissa(iLinkBinary::PRICENULL9::mantissaNullValue()); }
msg.orderQty(create.quantity.value());
msg.securityID(create.security->glbx().exchange_id());
msg.side(map_side(create.side));
msg.seqNum(next_seq());
msg.putSenderID(create.routing_record->operator_id());
encode_clorid(create.key, SecurityKey(create.security->id()), &_clorid_buffer);
msg.putClOrdID(_clorid_buffer);
msg.partyDetailsListReqID(party);
msg.orderRequestID(++_msg_count);
msg.sendingTimeEpoch(_time.now());
if (needs_stop_px(create.order_type)) { msg.stopPx().mantissa(to_price9(create.stop_px)); }
else { msg.stopPx().mantissa(iLinkBinary::PRICENULL9::mantissaNullValue()); }
msg.putLocation(create.routing_record->location());
msg.minQty(iLinkBinary::NewOrderSingle514::minQtyNullValue());
if (create.time_in_force != api::orderman::TimeInForce::TIME_IN_FORCE_IOC) {
msg.displayQty(create.display_quantity.value());
}
else { msg.displayQty(iLinkBinary::NewOrderSingle514::displayQtyNullValue()); }
if (create.time_in_force == api::orderman::TimeInForce::TIME_IN_FORCE_DATE) {
//TODO: # of days since jan 1 1970
msg.expireDate(18424);
}
else {
msg.expireDate(iLinkBinary::NewOrderSingle514::expireDateNullValue());
}
msg.ordType(map_order_type(create.order_type));
msg.timeInForce(map_time_in_force(create.time_in_force));
msg.manualOrderIndicator(map_manual_order_indicator(create.manual_order_indicator));
msg.execInst().clear();
msg.executionMode(iLinkBinary::ExecMode::NULL_VALUE);
msg.liquidityFlag(iLinkBinary::BooleanNULL::NULL_VALUE);
msg.managedOrder(iLinkBinary::BooleanNULL::NULL_VALUE);
msg.shortSaleType(iLinkBinary::ShortSaleType::NULL_VALUE);
_exe_parser.cache(create.security);
log_out(msg);
}
void ILinkGW::send_cancel_replace(const CancelReplaceOrderMsg& replace) {
const auto& create = replace.create_fields;
bts_assert_d(create.routing_record);
bts_assert_d(create.security);
bts_assert_d(create.security->has_glbx());
auto party = send_party_details(*create.routing_record);
auto msg = _buffer.frame<iLinkBinary::OrderCancelReplaceRequest515>();
msg.orderID(replace.exchange_order_id.value());
if (need_px(create.order_type)) { msg.price().mantissa(to_price9(create.price)); }
else { msg.price().mantissa(iLinkBinary::PRICENULL9::mantissaNullValue()); }
msg.orderQty(create.quantity.value());
msg.securityID(create.security->glbx().exchange_id());
msg.side(map_side(create.side));
msg.seqNum(next_seq());
msg.putSenderID(create.routing_record->operator_id());
encode_clorid(create.key, SecurityKey(create.security->id()), &_clorid_buffer);
msg.putClOrdID(_clorid_buffer);
msg.partyDetailsListReqID(party);
msg.orderRequestID(++_msg_count);
msg.sendingTimeEpoch(_time.now());
if (needs_stop_px(create.order_type)) { msg.stopPx().mantissa(to_price9(create.stop_px)); }
else { msg.stopPx().mantissa(iLinkBinary::PRICENULL9::mantissaNullValue()); }
msg.putLocation(create.routing_record->location());
msg.minQty(iLinkBinary::NewOrderSingle514::minQtyNullValue());
msg.displayQty(create.display_quantity.value());
msg.expireDate(iLinkBinary::NewOrderSingle514::expireDateNullValue());
msg.ordType(map_order_type(create.order_type));
msg.timeInForce(map_time_in_force(create.time_in_force));
msg.manualOrderIndicator(map_manual_order_indicator(create.manual_order_indicator));
msg.oFMOverride(iLinkBinary::OFMOverrideReq::Enabled);
msg.execInst().clear();
msg.executionMode(iLinkBinary::ExecMode::NULL_VALUE);
msg.liquidityFlag(iLinkBinary::BooleanNULL::NULL_VALUE);
msg.managedOrder(iLinkBinary::BooleanNULL::NULL_VALUE);
msg.shortSaleType(iLinkBinary::ShortSaleType::NULL_VALUE);
log_out(msg);
}
void ILinkGW::send_cancel(const CancelOrderMsg& cancel) {
bts_assert_d(cancel.routing_record);
bts_assert_d(cancel.security);
bts_assert_d(cancel.security->has_glbx());
auto party = send_party_details(*cancel.routing_record);
auto msg = _buffer.frame<iLinkBinary::OrderCancelRequest516>();
msg.orderID(cancel.exchange_order_id.value());
msg.partyDetailsListReqID(party);
msg.manualOrderIndicator(map_manual_order_indicator(cancel.manual_order_indicator));
msg.seqNum(next_seq());
msg.putSenderID(cancel.routing_record->operator_id());
encode_clorid(cancel.key, SecurityKey(cancel.security->id()), &_clorid_buffer);
msg.putClOrdID(_clorid_buffer);
msg.orderRequestID(++_msg_count);
msg.sendingTimeEpoch(_time.now());
msg.putLocation(cancel.routing_record->location());
msg.securityID(cancel.security->glbx().exchange_id());
msg.side(map_side(cancel.side));
msg.liquidityFlag(iLinkBinary::BooleanNULL::NULL_VALUE);
log_out(msg);
}
void ILinkGW::send_terminate(uint16_t code) {
LOG(iLink3, Info, "Terminate");
auto msg = _buffer.frame<iLinkBinary::Terminate507>();
msg.uUID(_session.uuid);
msg.requestTimestamp(_time.now());
msg.errorCodes(code);
log_out(msg);
}
void ILinkGW::flush(bool publish) {
_buffer.flush(_connection);
if (publish) publish_session_update();
}
const char* state_string(State s) {
switch(s) {
case State::INIT: return "INIT";
case State::CONNECTING: return "CONNECTING";
case State::NEGOTATING: return "NEGOTATING";
case State::ESTABLISHING: return "ESTABLISHING";
case State::RETRANSMITTING: return "RETRANSMITTING";
case State::READY: return "READY";
case State::ERROR: return "ERROR";
}
return "UNKNOWN";
}
log::CharPtrWrapper wstate_string(State s) { return wrap(state_string(s)); }
void ILinkGW::set_state(State s) {
if (s != _x_state) {
LOG(iLink3, Info, "ILinkGW {}: {}->{}",
_session.uuid, wstate_string(_x_state), wstate_string(s));
_x_state = s;
if (_on_state_change) _on_state_change(s);
}
}
//
// IConnectionHandler
void ILinkGW::on_connect_success() {
if (!_session) {
// If we have a 0 cme_seq this is a new session and we need to negotiate it
LOG(iLink3, Info, "Negotiating new iLink session. {}", _session.uuid);
set_state(State::NEGOTATING);
send_negotiate();
}
else {
// We only need to establish the current sequence number
LOG(iLink3, Info, "re-establishing existing iLink session. {}", _session.uuid);
_session.to_cme = std::max(_session.to_cme, 1u);
set_state(State::ESTABLISHING);
send_establish();
}
}
void ILinkGW::on_disconnect() {
LOG(iLink3, Error, "Disconnected.");
if (_config.failover_on_disconnect) {
LOG(iLink3, Error, "Attempting failover");
_connection.failover();
connect();
}
else {
set_state(State::ERROR);
}
}
void ILinkGW::enqueue_retransmit(uint32_t from, uint32_t to, uint64_t uuid) {
LOG(iLink3,Warn, "Prepare retransmit from: {} to: {}", from, to);
bts_assert(to >= from);
do {
// +1 because to/from are using an inclusive range
auto count = std::min(to - from + 1, Retransmit::MAX_RECOVERY);
_retransmit.push(Retransmit {
uuid,
from,
from + count - 1
});
from += count;
} while(from < to);
}
void ILinkGW::begin_retransmit() {
if (_retransmit.empty()) return;
auto& working = _retransmit.front();
// Don't pop the queue because we need to know when we're done
auto count = working.to - working.from + 1;
LOG(iLink3,Warn, "Sending retransmit for missing packets: from: {} to: {} count: {}", working.from, working.to, count);
bts_assert_d(count < Retransmit::MAX_RECOVERY);
send_retransmit_request(working.uuid, working.from, count);
}
void ILinkGW::on_retransmit_complete() {
// Replay is complete. Advance to go. Collect $200
_retransmit.pop();
LOG(iLink3,Warn,"Retransmit complete");
if (!_retransmit.empty()) {
// More replay to do...
begin_retransmit();
flush();
}
else {
// Replay is finished, transition to ready state.
// Since we're already established we dont' need to send anything
set_state(State::READY);
}
}
size_t ILinkGW::on_data(const std::string_view& data) {
return consume_messages(*this, data.data(), data.size(), dispatch_message<ILinkGW>);
}
void ILinkGW::handle(const iLinkBinary::NegotiationResponse501& msg) {
// If we're receiving a NegotiateResponse we just created a session
log_in(msg);
// NegotiationResponse indicates the session was created. CME sequence will be 1
_session.from_cme = 1;
publish_session_update();
// Even though the CME sends a previous uuid+sequence we can't act on
// that data right now since we aren't established. We don't have to remember it,
// though, because exactly the same data comes on the EstablishmentAck
// msg.previousUUID(), msg.previousSeqNo();
set_state(State::ESTABLISHING);
send_establish();
}
void ILinkGW::handle(const iLinkBinary::NegotiationReject502& msg) {
LOG(iLink3, Error, "Negotiate Reject: {} '{}'.",
msg.errorCodes(),
std::string(translate_negotiation_reject(msg.errorCodes())));
log_in(msg);
_connection.disconnect();
set_state(State::ERROR);
}
void ILinkGW::handle(const iLinkBinary::EstablishmentAck504& msg) {
// previous uuid+sequence
auto cme_prev_uuid = msg.previousUUID();
auto cme_prev_seq = msg.previousSeqNo();
if (cme_prev_seq != 0 && cme_prev_uuid != _session.uuid) {
// There was a previous session and we need to replay messages from it
// We *intend* to only have a single session each week except
// in the case of catastrophic failure. So If we log in and
// there is a previous UUID we can just replay it entirely.
// The other possibility is a session was created automatically
// to handle a fill from a GTC order from the previous week
enqueue_retransmit(1, cme_prev_seq, cme_prev_uuid);
}
// next sequence number from the current session may also be ahead
auto cme_current_seq = msg.nextSeqNo() - 1;
if (_session.from_cme < cme_current_seq) {
// If we're behind it indicates we missed messages while disconnected
enqueue_retransmit(_session.from_cme+1, cme_current_seq, msg.uUID());
}
_session.from_cme = cme_current_seq;
log_in(msg);
if (!_retransmit.empty()) {
send_sequence();
begin_retransmit();
flush();
set_state(State::RETRANSMITTING);
}
else {
send_sequence();
flush();
set_state(State::READY);
}
}
void ILinkGW::handle(const iLinkBinary::EstablishmentReject505& msg) {
LOG(iLink3, Error, "Establishment Reject: {} '{}'. NextSeq: {}.",
msg.errorCodes(),
std::string(translate_establish_reject(msg.errorCodes())),
msg.nextSeqNo());
_connection.disconnect();
log_in(msg);
set_state(State::ERROR);
}
void ILinkGW::handle(const iLinkBinary::Sequence506& msg) {
log_in(msg);
_session.from_cme = msg.nextSeqNo() - 1;
publish_session_update();
send_sequence();
flush();
}
void ILinkGW::handle(const iLinkBinary::Terminate507 &msg) {
// https://www.cmegroup.com/confluence/display/EPICSANDBOX/Terminate
LOG(iLink3, Error, "Terminated by exchange. Code: {} Reason: {} Text: {}",
msg.errorCodes(), wrap(msg.reason()),
wrap(translate_terminate(msg.errorCodes())));
if (msg.errorCodes() == 11 || msg.errorCodes() == 10) {
// This indicates our sequence number is too low. We will jump
// forward one at a time. That should eventually fix it.
LOG(iLink3, Error, "Will attempt to recover by advancing our sequence number");
_session.to_cme ++;
publish_session_update();
}
log_in(msg);
_connection.disconnect();
set_state(State::ERROR);
}
void ILinkGW::handle(const iLinkBinary::Retransmission509& msg) {
// Accepted Retransmit
log_in(msg);
}
void ILinkGW::handle(const iLinkBinary::RetransmitReject510& msg) {
LOG(iLink3, Error, "Retransmit requeste rejected. {}", msg.getReasonAsString());
log_in(msg);
set_state(State::ERROR);
}
void ILinkGW::handle(const iLinkBinary::NotApplied513& msg) {
log_in(msg);
send_sequence();
}
void ILinkGW::handle(const iLinkBinary::PartyDetailsDefinitionRequestAck519& msg) {
_exe_parser.set_account(msg);
handle_common(msg);
}
void ILinkGW::handle(const iLinkBinary::BusinessReject521& msg) {
LOG(iLink3, Error, "Business Reject: {} '{}'.",
msg.businessRejectReason(),
wrap(translate_business_reject_reason(msg.businessRejectReason())));
handle_common(msg);
// A business reject can de-sync the sequence number because it rejects
// the sequence number of the rejected message. Send a sequence message
// to tell the cme to advance.
send_sequence();
flush();
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportNew522& msg) {
handle_exe_report(msg);
handle_common(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportReject523& msg) {
LOG(iLink3, Error, "Execution report reject: {}", wrap(msg.text()));
handle_exe_report(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportElimination524& msg) {
handle_exe_report(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportTradeOutright525& msg) {
handle_exe_report(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportTradeSpread526& msg) {
handle_exe_report(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportTradeSpreadLeg527& msg) {
handle_exe_report(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportModify531& msg) {
handle_exe_report(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportStatus532& msg) {
handle_exe_report(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportCancel534& msg) {
handle_exe_report(msg);
}
void ILinkGW::handle(const iLinkBinary::OrderCancelReject535& msg) {
handle_common(msg);
// TODO: log
}
void ILinkGW::handle(const iLinkBinary::OrderCancelReplaceReject536& msg) {
handle_common(msg);
// TODO: log
}
void ILinkGW::handle(const iLinkBinary::ExecutionAck539&) {
// handle_common(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportTradeAddendumOutright548& msg) {
// Ignore trade correction/addendum messages for now.
// See GLBXExecutionGateway.cpp:139 for further details
handle_common(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportTradeAddendumSpread549& msg) {
// Ignore trade correction/addendum messages for now.
// See GLBXExecutionGateway.cpp:139 for further details
handle_common(msg);
}
void ILinkGW::handle(const iLinkBinary::ExecutionReportTradeAddendumSpreadLeg550& msg) {
// Ignore trade correction/addendum messages for now.
// See GLBXExecutionGateway.cpp:139 for further details
handle_common(msg);
}
}}} //namespace
+232
View File
@@ -0,0 +1,232 @@
#pragma once
#include <string>
#include <functional>
#include <cstdint>
#include <vector>
#include <queue>
#include "../IExecutionGateway.h"
#include "TimeKeeper.h"
#include "IL3Connection.h"
#include "IL3ConnectionHandler.h"
#include "generated/MessageHeader.h"
#include "IL3GeneratedFwd.h"
#include "IL3ExecutionReportParser.h"
#include "lib/orderman/actors/ilink3/RawMsg.h"
#include "lib/config/protos/jetfix.pb.h"
#define MID_SESSION_REPLAY
namespace bts {
namespace orderman {
class ExecutionReport;
namespace ilink3 {
struct Session {
uint64_t uuid;
// bts->cme
uint32_t to_cme;
// cme->bts
uint32_t from_cme;
operator bool const() { return from_cme; }
};
struct Config {
std::string cme_session; // NGG
std::string firm; // 004
bool failover_on_disconnect;
std::function<void(RawMessageDirection, RawMsg const&)> raw_message_logger;
};
enum class State {
INIT,
CONNECTING,
NEGOTATING,
ESTABLISHING,
RETRANSMITTING,
READY,
ERROR
};
const char* state_string(State s);
typedef std::function<void(State)> OnStateChange;
typedef std::function<void(const ExecutionReport*)> OnExecutionReport;
typedef std::function<void(const Session& s)> OnSessionChange;
typedef std::function<void(OrderKey,std::string const&)> OnCancelReject;
struct Retransmit {
static constexpr uint32_t MAX_RECOVERY = 2500;
uint64_t uuid;
uint32_t from;
uint32_t to;
};
class IL3MessageFramer;
// Does not allow re-entrance
class ILinkGW : IL3ConnectionHandler {
const Config _config;
State _x_state;
IL3MessageFramer& _buffer;
OnStateChange _on_state_change;
OnExecutionReport _on_exe_report;
OnSessionChange _on_session_change;
IL3Connection& _connection;
Session _session;
std::string _clorid_buffer;
uint32_t _msg_count;
TimeKeeper _time;
boost::object_pool<ExecutionReport> _pool;
IL3ExecutionReportParser _exe_parser;
std::queue<Retransmit> _retransmit;
public:
ILinkGW(
IL3Connection&,
IL3MessageFramer&,
md::SecurityOracle*,
const Session&,
const Config&,
config::JetFIX::Connection const &);
void connect();
void send_order(const CreateOrderMsg&);
void send_cancel_replace(const CancelReplaceOrderMsg&);
void send_cancel(const CancelOrderMsg&);
void send_terminate(uint16_t code=0);
void flush(bool publish=true);
void on_time() {
// Currently we just reply to a heartbeat with another heartbeat
// Probably better to track time and send them on demand
};
// state change
State state() { return _x_state; }
void subscribe_state(OnStateChange o) { _on_state_change = o; }
void subscribe_execution_reports(OnExecutionReport sub) {
_on_exe_report = sub;
}
void subscribe_session(OnSessionChange cb) { _on_session_change = cb; }
void subscribe_cancel_reject(OnCancelReject) {}
// Only used for certification
void send_sequence(bool lapsed=false);
private:
void send_negotiate();
void send_establish();
void send_retransmit_request(uint64_t uuid, uint32_t from, size_t count);
uint64_t send_party_details(const api::orderman::RoutingRecord&);
private:
void set_state(State);
uint32_t next_seq() {
_session.to_cme += 1;
return _session.to_cme-1;
}
void publish_session_update() { _on_session_change(_session); }
void on_connect_success() override;
void on_disconnect() override;
void enqueue_retransmit(uint32_t from, uint32_t to, uint64_t uuid);
void begin_retransmit();
void on_retransmit_complete();
template <class T>
static auto serialize(const T& msg) -> auto {
return [=]() -> auto {
RawMessageData result;
std::stringstream buffer;
buffer << msg;
result.json = buffer.str();
result.binary = std::string(msg.buffer() + msg.offset(), msg.decodeLength());
return result;
};
}
template <class T>
void log_in(const T& msg) {
_config.raw_message_logger(RawMessageDirection::INCOMING, serialize(msg));
}
template <class T>
void log_out(const T& msg) {
_config.raw_message_logger(RawMessageDirection::OUTGOING, serialize(msg));
}
//
// Message handlers
size_t on_data(const std::string_view&) override;
template <class T>
void handle_common(const T& msg) {
auto uuid = msg.uUID();
auto seq = msg.seqNum();
log_in(msg);
// Test if replay is copmlete
if (!_retransmit.empty() && _retransmit.front().to == seq) {
on_retransmit_complete();
return;
}
// Handle non-replay packet
if (uuid == _session.uuid) {
#ifdef MID_SESSION_REPLAY
// Gap detected during normal operation
auto expected = _session.from_cme + 1;
if (seq > expected) {
bool busy = !_retransmit.empty();
enqueue_retransmit(expected, seq-1, _session.uuid);
if (!busy) begin_retransmit();
flush();
}
#endif
// msg may be a replay message with a lower sequence number
if (msg.seqNum() > _session.from_cme) {
_session.from_cme = msg.seqNum();
publish_session_update();
}
}
}
template <class T>
void handle_exe_report(const T& msg) {
auto* report = _pool.construct();
bool result = _exe_parser.parse(msg, report);
if (result) {
_on_exe_report(report);
}
else { LOG(iLink3, Error, "Failed to parse error report."); }
handle_common(msg);
}
public:
void handle(const iLinkBinary::NegotiationResponse501&);
void handle(const iLinkBinary::NegotiationReject502&);
void handle(const iLinkBinary::EstablishmentAck504&);
void handle(const iLinkBinary::EstablishmentReject505&);
void handle(const iLinkBinary::Sequence506&);
void handle(const iLinkBinary::Terminate507&);
void handle(const iLinkBinary::Retransmission509&);
void handle(const iLinkBinary::RetransmitReject510&);
void handle(const iLinkBinary::NotApplied513&);
void handle(const iLinkBinary::PartyDetailsDefinitionRequestAck519&);
void handle(const iLinkBinary::BusinessReject521&);
void handle(const iLinkBinary::ExecutionReportNew522&);
void handle(const iLinkBinary::ExecutionReportReject523&);
void handle(const iLinkBinary::ExecutionReportElimination524&);
void handle(const iLinkBinary::ExecutionReportTradeOutright525&);
void handle(const iLinkBinary::ExecutionReportTradeSpread526&);
void handle(const iLinkBinary::ExecutionReportTradeSpreadLeg527&);
void handle(const iLinkBinary::ExecutionReportModify531&);
void handle(const iLinkBinary::ExecutionReportStatus532&);
void handle(const iLinkBinary::ExecutionReportCancel534&);
void handle(const iLinkBinary::OrderCancelReject535&);
void handle(const iLinkBinary::OrderCancelReplaceReject536&);
void handle(const iLinkBinary::ExecutionAck539&);
void handle(const iLinkBinary::ExecutionReportTradeAddendumOutright548&);
void handle(const iLinkBinary::ExecutionReportTradeAddendumSpread549&);
void handle(const iLinkBinary::ExecutionReportTradeAddendumSpreadLeg550&);
};
}}} //namespace
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <functional>
#include <string>
namespace bts {
namespace orderman {
namespace ilink3 {
enum class RawMessageDirection {INCOMING, OUTGOING};
struct RawMessageData {
std::string json;
std::string binary;
};
using RawMsg = std::function<RawMessageData(void)>;
}}}
@@ -0,0 +1,180 @@
#include "SessionStore.h"
#include "lib/jetfix/store/session_name.h"
#include "lib/orderman/actors/ilink3/ILinkGW.h"
#include "lib/orderman/orderman_utils/ExecutionReport.h"
#include "lib/utils/base64.hpp"
#include "lib/utils/bts_chrono.h"
#include "lib/utils/file_utils.h"
#include "lib/utils/thread_manager.h"
#include <boost/filesystem.hpp>
#include <nlohmann/json.hpp>
#include <tbb/concurrent_queue.h>
#include <thread>
namespace bts {
namespace orderman {
namespace ilink3 {
using Action = std::function<void()>;
static std::string base_store_path(std::string base_path,
std::string const &connection_name,
std::string const &session_name) {
if (base_path.empty())
base_path = os::bts_data_path();
boost::filesystem::path result = utils::normalize_data_path(base_path);
result /= "ilink3";
result /= connection_name;
result /= session_name;
if (!boost::filesystem::exists(result))
bts_assert(boost::filesystem::create_directories(result));
return result.string();
}
static std::string raw_msg_log_path(std::string const &store_path) {
boost::filesystem::path result = store_path;
result /= "raw_msgs";
return result.string();
}
static std::string session_path(std::string const &store_path) {
boost::filesystem::path result = store_path;
result /= "session";
return result.string();
}
static std::vector<ExecutionReport>
load_replay(md::SecurityOracle &, config::JetFIX::Connection const &cfg,
std::string const &path) {
std::vector<ExecutionReport> result;
if (boost::filesystem::exists(path)) {
std::ifstream f(path);
nlohmann::json j;
for (;;) {
while (!f.eof() && f.get() != '{')
;
if (f.eof())
break;
else {
f.unget();
f >> j;
if (j["direction"] == "<") {
auto ts = datetime::parse_FIX_timestamp(j["time"]);
if (!datetime::is_at_least_secs_old(ts,
cfg.seconds_to_replay())) {
}
}
}
}
}
return result;
}
static void save_raw_msg(std::ofstream &out, RawMessageDirection d,
RawMessageData const &msg) {
nlohmann::json j;
j["direction"] = d == RawMessageDirection::INCOMING ? "<" : ">";
j["time"] = datetime::FIX_timestamp(datetime::now());
j["msg_sbe"] = websocketpp::base64_encode(msg.binary);
try {
j["msg_json"] = nlohmann::json::parse(msg.json);
}
catch (...) {
LOG(iLink3, Error, "Skipping troublesome json encoded message: {}", msg.json);
j["msg_json"] = nlohmann::json {};
}
out << j << std::endl;
out.flush();
}
void save_session(std::string const &path, Session const &session) {
std::ofstream f(path);
f << session.uuid << " " << session.to_cme << " " << session.from_cme
<< std::endl;
}
Session load_session(jetfix::SessionName const &sn, std::string const &path) {
auto result = Session{sn.as_uint64_t, 1, 0};
if (boost::filesystem::exists(path)) {
std::ifstream f(path);
uint64_t dummy;
f >> dummy >> result.to_cme >> result.from_cme;
}
else
save_session(path, result);
return result;
}
struct SessionStore::PImpl {
PImpl(md::SecurityOracle &oracle, jetfix::SessionName const &session_name,
config::JetFIX::Connection const &cfg, std::string const &base_path)
: cfg(cfg), store_path(base_store_path(base_path, cfg.name(),
session_name.as_string)),
replay_messages(
load_replay(oracle, cfg, raw_msg_log_path(store_path))),
starting_session_descriptor(
load_session(session_name, session_path(store_path))),
raw_msg_store() {
raw_msg_store.open(raw_msg_log_path(store_path), std::ofstream::app);
}
const config::JetFIX::Connection cfg;
const std::string store_path;
const std::vector<ExecutionReport> replay_messages;
const Session starting_session_descriptor;
std::atomic<bool> done = false;
tbb::concurrent_queue<Action> event_queue;
std::thread storage_thread;
std::ofstream raw_msg_store;
};
SessionStore::SessionStore(md::SecurityOracle &oracle,
jetfix::SessionName const &session_name,
config::JetFIX::Connection const &cfg,
std::string base_path)
: me(new PImpl(oracle, session_name, cfg, base_path)) {
me->storage_thread = threading::make_thread_from_function(
"il3_store", [this]() { do_work(); });
}
std::vector<ExecutionReport> const &SessionStore::replay() const {
return me->replay_messages;
}
Session SessionStore::starting_session_descriptor() const {
return me->starting_session_descriptor;
}
void SessionStore::async_update_session(Session const &s) {
me->event_queue.push(
Action{[this, s]() { save_session(session_path(me->store_path), s); }});
}
void SessionStore::async_store_raw_msg(RawMessageDirection d,
RawMsg const &ms) {
me->event_queue.push(
Action{[this, d, ms]() { save_raw_msg(me->raw_msg_store, d, ms()); }});
}
void SessionStore::do_work() {
while (!me->done) {
Action a;
if (me->event_queue.try_pop(a))
a();
else
std::this_thread::sleep_for(100ms);
}
}
SessionStore::~SessionStore() {
me->done = true;
me->storage_thread.join();
}
} // namespace ilink3
} // namespace orderman
} // namespace bts
@@ -0,0 +1,40 @@
#pragma once
#include <memory>
#include <vector>
#include <functional>
#include "lib/config/protos/jetfix.pb.h"
#include "RawMsg.h"
// fwds
namespace bts {
namespace jetfix {struct SessionName;}
namespace md { class SecurityOracle;}
namespace orderman {class ExecutionReport;}
}
namespace bts {
namespace orderman {
namespace ilink3 {
struct Session;
class SessionStore {
public:
SessionStore(md::SecurityOracle &,
jetfix::SessionName const&session_name,
config::JetFIX::Connection const&,
std::string base_path="");
~SessionStore() ;
Session starting_session_descriptor() const;
std::vector<ExecutionReport> const &replay() const;
void async_update_session(Session const&) ;
void async_store_raw_msg(RawMessageDirection, RawMsg const&);
private:
void do_work();
struct PImpl;
std::unique_ptr<PImpl> me;
};
}}}
@@ -0,0 +1,25 @@
#pragma once
#include "lib/utils/datetime.h"
#include "lib/utils/TimeStamp.h"
namespace bts {
namespace orderman {
namespace ilink3 {
struct TimeKeeper {
uint64_t unix_time;
utils::TimeStamp start;
TimeKeeper() :
unix_time(datetime::unix_nano_now()),
start(utils::TimeStamp::now())
{}
uint64_t now() const {
auto now = utils::TimeStamp::now();
auto delta = now - start;
return unix_time + delta.microseconds();
}
};
}}} //namespace
@@ -0,0 +1,144 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_AVGPXIND_H_
#define _ILINKBINARY_AVGPXIND_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class AvgPxInd
{
public:
enum Value
{
NoAveragePricing = (std::uint8_t)0,
TradeispartofanAveragePriceGroupIdentifiedbytheAvgPxGrpID = (std::uint8_t)1,
TradeispartofaNotionalValueAveragePriceGroup = (std::uint8_t)3,
NULL_VALUE = (std::uint8_t)255
};
static AvgPxInd::Value get(const std::uint8_t value)
{
switch (value)
{
case 0: return NoAveragePricing;
case 1: return TradeispartofanAveragePriceGroupIdentifiedbytheAvgPxGrpID;
case 3: return TradeispartofaNotionalValueAveragePriceGroup;
case 255: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum AvgPxInd [E103]");
}
static const char* c_str(const AvgPxInd::Value value)
{
switch (value)
{
case NoAveragePricing: return "NoAveragePricing";
case TradeispartofanAveragePriceGroupIdentifiedbytheAvgPxGrpID: return "TradeispartofanAveragePriceGroupIdentifiedbytheAvgPxGrpID";
case TradeispartofaNotionalValueAveragePriceGroup: return "TradeispartofaNotionalValueAveragePriceGroup";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum AvgPxInd [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, AvgPxInd::Value m)
{
return os << AvgPxInd::c_str(m);
}
};
}
#endif
@@ -0,0 +1,141 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_BOOLEANFLAG_H_
#define _ILINKBINARY_BOOLEANFLAG_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class BooleanFlag
{
public:
enum Value
{
False = (std::uint8_t)0,
True = (std::uint8_t)1,
NULL_VALUE = (std::uint8_t)255
};
static BooleanFlag::Value get(const std::uint8_t value)
{
switch (value)
{
case 0: return False;
case 1: return True;
case 255: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum BooleanFlag [E103]");
}
static const char* c_str(const BooleanFlag::Value value)
{
switch (value)
{
case False: return "False";
case True: return "True";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum BooleanFlag [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, BooleanFlag::Value m)
{
return os << BooleanFlag::c_str(m);
}
};
}
#endif
@@ -0,0 +1,141 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_BOOLEANNULL_H_
#define _ILINKBINARY_BOOLEANNULL_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class BooleanNULL
{
public:
enum Value
{
False = (std::uint8_t)0,
True = (std::uint8_t)1,
NULL_VALUE = (std::uint8_t)255
};
static BooleanNULL::Value get(const std::uint8_t value)
{
switch (value)
{
case 0: return False;
case 1: return True;
case 255: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum BooleanNULL [E103]");
}
static const char* c_str(const BooleanNULL::Value value)
{
switch (value)
{
case False: return "False";
case True: return "True";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum BooleanNULL [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, BooleanNULL::Value m)
{
return os << BooleanNULL::c_str(m);
}
};
}
#endif
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,141 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_CLEARINGACCTTYPE_H_
#define _ILINKBINARY_CLEARINGACCTTYPE_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class ClearingAcctType
{
public:
enum Value
{
Customer = (std::uint8_t)0,
Firm = (std::uint8_t)1,
NULL_VALUE = (std::uint8_t)255
};
static ClearingAcctType::Value get(const std::uint8_t value)
{
switch (value)
{
case 0: return Customer;
case 1: return Firm;
case 255: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum ClearingAcctType [E103]");
}
static const char* c_str(const ClearingAcctType::Value value)
{
switch (value)
{
case Customer: return "Customer";
case Firm: return "Firm";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum ClearingAcctType [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, ClearingAcctType::Value m)
{
return os << ClearingAcctType::c_str(m);
}
};
}
#endif
@@ -0,0 +1,141 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_CMTAGIVEUPCD_H_
#define _ILINKBINARY_CMTAGIVEUPCD_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class CmtaGiveUpCD
{
public:
enum Value
{
GiveUp = (char)71,
SGXoffset = (char)83,
NULL_VALUE = (char)0
};
static CmtaGiveUpCD::Value get(const char value)
{
switch (value)
{
case 71: return GiveUp;
case 83: return SGXoffset;
case 0: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum CmtaGiveUpCD [E103]");
}
static const char* c_str(const CmtaGiveUpCD::Value value)
{
switch (value)
{
case GiveUp: return "GiveUp";
case SGXoffset: return "SGXoffset";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum CmtaGiveUpCD [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, CmtaGiveUpCD::Value m)
{
return os << CmtaGiveUpCD::c_str(m);
}
};
}
#endif
@@ -0,0 +1,153 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_CUSTORDHANDLINST_H_
#define _ILINKBINARY_CUSTORDHANDLINST_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class CustOrdHandlInst
{
public:
enum Value
{
FCMprovidedscreen = (char)67,
Otherprovidedscreen = (char)68,
FCMAPIorFIX = (char)71,
AlgoEngine = (char)72,
DeskElectronic = (char)87,
ClientElectronic = (char)89,
NULL_VALUE = (char)0
};
static CustOrdHandlInst::Value get(const char value)
{
switch (value)
{
case 67: return FCMprovidedscreen;
case 68: return Otherprovidedscreen;
case 71: return FCMAPIorFIX;
case 72: return AlgoEngine;
case 87: return DeskElectronic;
case 89: return ClientElectronic;
case 0: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum CustOrdHandlInst [E103]");
}
static const char* c_str(const CustOrdHandlInst::Value value)
{
switch (value)
{
case FCMprovidedscreen: return "FCMprovidedscreen";
case Otherprovidedscreen: return "Otherprovidedscreen";
case FCMAPIorFIX: return "FCMAPIorFIX";
case AlgoEngine: return "AlgoEngine";
case DeskElectronic: return "DeskElectronic";
case ClientElectronic: return "ClientElectronic";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum CustOrdHandlInst [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, CustOrdHandlInst::Value m)
{
return os << CustOrdHandlInst::c_str(m);
}
};
}
#endif
@@ -0,0 +1,147 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_CUSTORDERCAPACITY_H_
#define _ILINKBINARY_CUSTORDERCAPACITY_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class CustOrderCapacity
{
public:
enum Value
{
Membertradingfortheirownaccount = (std::uint8_t)1,
Clearingfirmtradingforitsproprietaryaccount = (std::uint8_t)2,
Membertradingforanothermember = (std::uint8_t)3,
Allother = (std::uint8_t)4,
NULL_VALUE = (std::uint8_t)255
};
static CustOrderCapacity::Value get(const std::uint8_t value)
{
switch (value)
{
case 1: return Membertradingfortheirownaccount;
case 2: return Clearingfirmtradingforitsproprietaryaccount;
case 3: return Membertradingforanothermember;
case 4: return Allother;
case 255: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum CustOrderCapacity [E103]");
}
static const char* c_str(const CustOrderCapacity::Value value)
{
switch (value)
{
case Membertradingfortheirownaccount: return "Membertradingfortheirownaccount";
case Clearingfirmtradingforitsproprietaryaccount: return "Clearingfirmtradingforitsproprietaryaccount";
case Membertradingforanothermember: return "Membertradingforanothermember";
case Allother: return "Allother";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum CustOrderCapacity [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, CustOrderCapacity::Value m)
{
return os << CustOrderCapacity::c_str(m);
}
};
}
#endif
@@ -0,0 +1,348 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_DATA_H_
#define _ILINKBINARY_DATA_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class DATA
{
private:
char *m_buffer = nullptr;
std::uint64_t m_bufferLength = 0;
std::uint64_t m_offset = 0;
std::uint64_t m_actingVersion = 0;
public:
enum MetaAttribute
{
EPOCH, TIME_UNIT, SEMANTIC_TYPE, PRESENCE
};
union sbe_float_as_uint_u
{
float fp_value;
std::uint32_t uint_value;
};
union sbe_double_as_uint_u
{
double fp_value;
std::uint64_t uint_value;
};
DATA() = default;
DATA(
char *buffer,
const std::uint64_t offset,
const std::uint64_t bufferLength,
const std::uint64_t actingVersion) :
m_buffer(buffer),
m_bufferLength(bufferLength),
m_offset(offset),
m_actingVersion(actingVersion)
{
if (SBE_BOUNDS_CHECK_EXPECT(((m_offset + -1) > m_bufferLength), false))
{
throw std::runtime_error("buffer too short for flyweight [E107]");
}
}
DATA(
char *buffer,
const std::uint64_t bufferLength,
const std::uint64_t actingVersion) :
DATA(buffer, 0, bufferLength, actingVersion)
{
}
DATA(
char *buffer,
const std::uint64_t bufferLength) :
DATA(buffer, 0, bufferLength, sbeSchemaVersion())
{
}
DATA &wrap(
char *buffer,
const std::uint64_t offset,
const std::uint64_t actingVersion,
const std::uint64_t bufferLength)
{
return *this = DATA(buffer, offset, bufferLength, actingVersion);
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t encodedLength() SBE_NOEXCEPT
{
return -1;
}
SBE_NODISCARD std::uint64_t offset() const SBE_NOEXCEPT
{
return m_offset;
}
SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT
{
return m_buffer;
}
SBE_NODISCARD char * buffer() SBE_NOEXCEPT
{
return m_buffer;
}
SBE_NODISCARD std::uint64_t bufferLength() const SBE_NOEXCEPT
{
return m_bufferLength;
}
SBE_NODISCARD std::uint64_t actingVersion() const SBE_NOEXCEPT
{
return m_actingVersion;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t sbeSchemaId() SBE_NOEXCEPT
{
return (std::uint16_t)8;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t sbeSchemaVersion() SBE_NOEXCEPT
{
return (std::uint16_t)5;
}
SBE_NODISCARD static const char * lengthMetaAttribute(const MetaAttribute metaAttribute) SBE_NOEXCEPT
{
switch (metaAttribute)
{
case MetaAttribute::PRESENCE: return "required";
default: return "";
}
}
static SBE_CONSTEXPR std::uint16_t lengthId() SBE_NOEXCEPT
{
return -1;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t lengthSinceVersion() SBE_NOEXCEPT
{
return 0;
}
SBE_NODISCARD bool lengthInActingVersion() SBE_NOEXCEPT
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
return m_actingVersion >= lengthSinceVersion();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
SBE_NODISCARD static SBE_CONSTEXPR std::size_t lengthEncodingOffset() SBE_NOEXCEPT
{
return 0;
}
static SBE_CONSTEXPR std::uint16_t lengthNullValue() SBE_NOEXCEPT
{
return SBE_NULLVALUE_UINT16;
}
static SBE_CONSTEXPR std::uint16_t lengthMinValue() SBE_NOEXCEPT
{
return (std::uint16_t)0;
}
static SBE_CONSTEXPR std::uint16_t lengthMaxValue() SBE_NOEXCEPT
{
return (std::uint16_t)65534;
}
static SBE_CONSTEXPR std::size_t lengthEncodingLength() SBE_NOEXCEPT
{
return 2;
}
SBE_NODISCARD std::uint16_t length() const SBE_NOEXCEPT
{
std::uint16_t val;
std::memcpy(&val, m_buffer + m_offset + 0, sizeof(std::uint16_t));
return SBE_LITTLE_ENDIAN_ENCODE_16(val);
}
DATA &length(const std::uint16_t value) SBE_NOEXCEPT
{
std::uint16_t val = SBE_LITTLE_ENDIAN_ENCODE_16(value);
std::memcpy(m_buffer + m_offset + 0, &val, sizeof(std::uint16_t));
return *this;
}
SBE_NODISCARD static const char * varDataMetaAttribute(const MetaAttribute metaAttribute) SBE_NOEXCEPT
{
switch (metaAttribute)
{
case MetaAttribute::PRESENCE: return "required";
default: return "";
}
}
static SBE_CONSTEXPR std::uint16_t varDataId() SBE_NOEXCEPT
{
return -1;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t varDataSinceVersion() SBE_NOEXCEPT
{
return 0;
}
SBE_NODISCARD bool varDataInActingVersion() SBE_NOEXCEPT
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
return m_actingVersion >= varDataSinceVersion();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
SBE_NODISCARD static SBE_CONSTEXPR std::size_t varDataEncodingOffset() SBE_NOEXCEPT
{
return 2;
}
static SBE_CONSTEXPR char varDataNullValue() SBE_NOEXCEPT
{
return (char)0;
}
static SBE_CONSTEXPR char varDataMinValue() SBE_NOEXCEPT
{
return (char)32;
}
static SBE_CONSTEXPR char varDataMaxValue() SBE_NOEXCEPT
{
return (char)126;
}
static SBE_CONSTEXPR std::size_t varDataEncodingLength() SBE_NOEXCEPT
{
return -1;
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& builder, DATA writer)
{
builder << '{';
builder << R"("length": )";
builder << +writer.length();
builder << '}';
return builder;
}
};
}
#endif
@@ -0,0 +1,159 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_DKREASON_H_
#define _ILINKBINARY_DKREASON_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class DKReason
{
public:
enum Value
{
UnknownSecurity = (char)65,
WrongSide = (char)66,
QuantityExceedsOrder = (char)67,
NoMatchingOrder = (char)68,
PriceExceedsLimit = (char)69,
CalculationDifference = (char)70,
NoMatchingExecutionReport = (char)71,
Other = (char)90,
NULL_VALUE = (char)0
};
static DKReason::Value get(const char value)
{
switch (value)
{
case 65: return UnknownSecurity;
case 66: return WrongSide;
case 67: return QuantityExceedsOrder;
case 68: return NoMatchingOrder;
case 69: return PriceExceedsLimit;
case 70: return CalculationDifference;
case 71: return NoMatchingExecutionReport;
case 90: return Other;
case 0: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum DKReason [E103]");
}
static const char* c_str(const DKReason::Value value)
{
switch (value)
{
case UnknownSecurity: return "UnknownSecurity";
case WrongSide: return "WrongSide";
case QuantityExceedsOrder: return "QuantityExceedsOrder";
case NoMatchingOrder: return "NoMatchingOrder";
case PriceExceedsLimit: return "PriceExceedsLimit";
case CalculationDifference: return "CalculationDifference";
case NoMatchingExecutionReport: return "NoMatchingExecutionReport";
case Other: return "Other";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum DKReason [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, DKReason::Value m)
{
return os << DKReason::c_str(m);
}
};
}
#endif
@@ -0,0 +1,366 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_DECIMAL32NULL_H_
#define _ILINKBINARY_DECIMAL32NULL_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class Decimal32NULL
{
private:
char *m_buffer = nullptr;
std::uint64_t m_bufferLength = 0;
std::uint64_t m_offset = 0;
std::uint64_t m_actingVersion = 0;
public:
enum MetaAttribute
{
EPOCH, TIME_UNIT, SEMANTIC_TYPE, PRESENCE
};
union sbe_float_as_uint_u
{
float fp_value;
std::uint32_t uint_value;
};
union sbe_double_as_uint_u
{
double fp_value;
std::uint64_t uint_value;
};
Decimal32NULL() = default;
Decimal32NULL(
char *buffer,
const std::uint64_t offset,
const std::uint64_t bufferLength,
const std::uint64_t actingVersion) :
m_buffer(buffer),
m_bufferLength(bufferLength),
m_offset(offset),
m_actingVersion(actingVersion)
{
if (SBE_BOUNDS_CHECK_EXPECT(((m_offset + 5) > m_bufferLength), false))
{
throw std::runtime_error("buffer too short for flyweight [E107]");
}
}
Decimal32NULL(
char *buffer,
const std::uint64_t bufferLength,
const std::uint64_t actingVersion) :
Decimal32NULL(buffer, 0, bufferLength, actingVersion)
{
}
Decimal32NULL(
char *buffer,
const std::uint64_t bufferLength) :
Decimal32NULL(buffer, 0, bufferLength, sbeSchemaVersion())
{
}
Decimal32NULL &wrap(
char *buffer,
const std::uint64_t offset,
const std::uint64_t actingVersion,
const std::uint64_t bufferLength)
{
return *this = Decimal32NULL(buffer, offset, bufferLength, actingVersion);
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t encodedLength() SBE_NOEXCEPT
{
return 5;
}
SBE_NODISCARD std::uint64_t offset() const SBE_NOEXCEPT
{
return m_offset;
}
SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT
{
return m_buffer;
}
SBE_NODISCARD char * buffer() SBE_NOEXCEPT
{
return m_buffer;
}
SBE_NODISCARD std::uint64_t bufferLength() const SBE_NOEXCEPT
{
return m_bufferLength;
}
SBE_NODISCARD std::uint64_t actingVersion() const SBE_NOEXCEPT
{
return m_actingVersion;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t sbeSchemaId() SBE_NOEXCEPT
{
return (std::uint16_t)8;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t sbeSchemaVersion() SBE_NOEXCEPT
{
return (std::uint16_t)5;
}
SBE_NODISCARD static const char * mantissaMetaAttribute(const MetaAttribute metaAttribute) SBE_NOEXCEPT
{
switch (metaAttribute)
{
case MetaAttribute::PRESENCE: return "optional";
default: return "";
}
}
static SBE_CONSTEXPR std::uint16_t mantissaId() SBE_NOEXCEPT
{
return -1;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t mantissaSinceVersion() SBE_NOEXCEPT
{
return 0;
}
SBE_NODISCARD bool mantissaInActingVersion() SBE_NOEXCEPT
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
return m_actingVersion >= mantissaSinceVersion();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
SBE_NODISCARD static SBE_CONSTEXPR std::size_t mantissaEncodingOffset() SBE_NOEXCEPT
{
return 0;
}
static SBE_CONSTEXPR std::int32_t mantissaNullValue() SBE_NOEXCEPT
{
return 2147483647;
}
static SBE_CONSTEXPR std::int32_t mantissaMinValue() SBE_NOEXCEPT
{
return -2147483647;
}
static SBE_CONSTEXPR std::int32_t mantissaMaxValue() SBE_NOEXCEPT
{
return 2147483647;
}
static SBE_CONSTEXPR std::size_t mantissaEncodingLength() SBE_NOEXCEPT
{
return 4;
}
SBE_NODISCARD std::int32_t mantissa() const SBE_NOEXCEPT
{
std::int32_t val;
std::memcpy(&val, m_buffer + m_offset + 0, sizeof(std::int32_t));
return SBE_LITTLE_ENDIAN_ENCODE_32(val);
}
Decimal32NULL &mantissa(const std::int32_t value) SBE_NOEXCEPT
{
std::int32_t val = SBE_LITTLE_ENDIAN_ENCODE_32(value);
std::memcpy(m_buffer + m_offset + 0, &val, sizeof(std::int32_t));
return *this;
}
SBE_NODISCARD static const char * exponentMetaAttribute(const MetaAttribute metaAttribute) SBE_NOEXCEPT
{
switch (metaAttribute)
{
case MetaAttribute::PRESENCE: return "optional";
default: return "";
}
}
static SBE_CONSTEXPR std::uint16_t exponentId() SBE_NOEXCEPT
{
return -1;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t exponentSinceVersion() SBE_NOEXCEPT
{
return 0;
}
SBE_NODISCARD bool exponentInActingVersion() SBE_NOEXCEPT
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
return m_actingVersion >= exponentSinceVersion();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
SBE_NODISCARD static SBE_CONSTEXPR std::size_t exponentEncodingOffset() SBE_NOEXCEPT
{
return 4;
}
static SBE_CONSTEXPR std::int8_t exponentNullValue() SBE_NOEXCEPT
{
return (std::int8_t)127;
}
static SBE_CONSTEXPR std::int8_t exponentMinValue() SBE_NOEXCEPT
{
return (std::int8_t)-127;
}
static SBE_CONSTEXPR std::int8_t exponentMaxValue() SBE_NOEXCEPT
{
return (std::int8_t)127;
}
static SBE_CONSTEXPR std::size_t exponentEncodingLength() SBE_NOEXCEPT
{
return 1;
}
SBE_NODISCARD std::int8_t exponent() const SBE_NOEXCEPT
{
std::int8_t val;
std::memcpy(&val, m_buffer + m_offset + 4, sizeof(std::int8_t));
return (val);
}
Decimal32NULL &exponent(const std::int8_t value) SBE_NOEXCEPT
{
std::int8_t val = (value);
std::memcpy(m_buffer + m_offset + 4, &val, sizeof(std::int8_t));
return *this;
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& builder, Decimal32NULL writer)
{
builder << '{';
builder << R"("mantissa": )";
builder << +writer.mantissa();
builder << ", ";
builder << R"("exponent": )";
builder << +writer.exponent();
builder << '}';
return builder;
}
};
}
#endif
@@ -0,0 +1,366 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_DECIMAL64NULL_H_
#define _ILINKBINARY_DECIMAL64NULL_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class Decimal64NULL
{
private:
char *m_buffer = nullptr;
std::uint64_t m_bufferLength = 0;
std::uint64_t m_offset = 0;
std::uint64_t m_actingVersion = 0;
public:
enum MetaAttribute
{
EPOCH, TIME_UNIT, SEMANTIC_TYPE, PRESENCE
};
union sbe_float_as_uint_u
{
float fp_value;
std::uint32_t uint_value;
};
union sbe_double_as_uint_u
{
double fp_value;
std::uint64_t uint_value;
};
Decimal64NULL() = default;
Decimal64NULL(
char *buffer,
const std::uint64_t offset,
const std::uint64_t bufferLength,
const std::uint64_t actingVersion) :
m_buffer(buffer),
m_bufferLength(bufferLength),
m_offset(offset),
m_actingVersion(actingVersion)
{
if (SBE_BOUNDS_CHECK_EXPECT(((m_offset + 9) > m_bufferLength), false))
{
throw std::runtime_error("buffer too short for flyweight [E107]");
}
}
Decimal64NULL(
char *buffer,
const std::uint64_t bufferLength,
const std::uint64_t actingVersion) :
Decimal64NULL(buffer, 0, bufferLength, actingVersion)
{
}
Decimal64NULL(
char *buffer,
const std::uint64_t bufferLength) :
Decimal64NULL(buffer, 0, bufferLength, sbeSchemaVersion())
{
}
Decimal64NULL &wrap(
char *buffer,
const std::uint64_t offset,
const std::uint64_t actingVersion,
const std::uint64_t bufferLength)
{
return *this = Decimal64NULL(buffer, offset, bufferLength, actingVersion);
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t encodedLength() SBE_NOEXCEPT
{
return 9;
}
SBE_NODISCARD std::uint64_t offset() const SBE_NOEXCEPT
{
return m_offset;
}
SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT
{
return m_buffer;
}
SBE_NODISCARD char * buffer() SBE_NOEXCEPT
{
return m_buffer;
}
SBE_NODISCARD std::uint64_t bufferLength() const SBE_NOEXCEPT
{
return m_bufferLength;
}
SBE_NODISCARD std::uint64_t actingVersion() const SBE_NOEXCEPT
{
return m_actingVersion;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t sbeSchemaId() SBE_NOEXCEPT
{
return (std::uint16_t)8;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t sbeSchemaVersion() SBE_NOEXCEPT
{
return (std::uint16_t)5;
}
SBE_NODISCARD static const char * mantissaMetaAttribute(const MetaAttribute metaAttribute) SBE_NOEXCEPT
{
switch (metaAttribute)
{
case MetaAttribute::PRESENCE: return "optional";
default: return "";
}
}
static SBE_CONSTEXPR std::uint16_t mantissaId() SBE_NOEXCEPT
{
return -1;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t mantissaSinceVersion() SBE_NOEXCEPT
{
return 0;
}
SBE_NODISCARD bool mantissaInActingVersion() SBE_NOEXCEPT
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
return m_actingVersion >= mantissaSinceVersion();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
SBE_NODISCARD static SBE_CONSTEXPR std::size_t mantissaEncodingOffset() SBE_NOEXCEPT
{
return 0;
}
static SBE_CONSTEXPR std::int64_t mantissaNullValue() SBE_NOEXCEPT
{
return 9223372036854775807L;
}
static SBE_CONSTEXPR std::int64_t mantissaMinValue() SBE_NOEXCEPT
{
return -9223372036854775807L;
}
static SBE_CONSTEXPR std::int64_t mantissaMaxValue() SBE_NOEXCEPT
{
return 9223372036854775807L;
}
static SBE_CONSTEXPR std::size_t mantissaEncodingLength() SBE_NOEXCEPT
{
return 8;
}
SBE_NODISCARD std::int64_t mantissa() const SBE_NOEXCEPT
{
std::int64_t val;
std::memcpy(&val, m_buffer + m_offset + 0, sizeof(std::int64_t));
return SBE_LITTLE_ENDIAN_ENCODE_64(val);
}
Decimal64NULL &mantissa(const std::int64_t value) SBE_NOEXCEPT
{
std::int64_t val = SBE_LITTLE_ENDIAN_ENCODE_64(value);
std::memcpy(m_buffer + m_offset + 0, &val, sizeof(std::int64_t));
return *this;
}
SBE_NODISCARD static const char * exponentMetaAttribute(const MetaAttribute metaAttribute) SBE_NOEXCEPT
{
switch (metaAttribute)
{
case MetaAttribute::PRESENCE: return "optional";
default: return "";
}
}
static SBE_CONSTEXPR std::uint16_t exponentId() SBE_NOEXCEPT
{
return -1;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t exponentSinceVersion() SBE_NOEXCEPT
{
return 0;
}
SBE_NODISCARD bool exponentInActingVersion() SBE_NOEXCEPT
{
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare"
#endif
return m_actingVersion >= exponentSinceVersion();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
}
SBE_NODISCARD static SBE_CONSTEXPR std::size_t exponentEncodingOffset() SBE_NOEXCEPT
{
return 8;
}
static SBE_CONSTEXPR std::int8_t exponentNullValue() SBE_NOEXCEPT
{
return (std::int8_t)127;
}
static SBE_CONSTEXPR std::int8_t exponentMinValue() SBE_NOEXCEPT
{
return (std::int8_t)-127;
}
static SBE_CONSTEXPR std::int8_t exponentMaxValue() SBE_NOEXCEPT
{
return (std::int8_t)127;
}
static SBE_CONSTEXPR std::size_t exponentEncodingLength() SBE_NOEXCEPT
{
return 1;
}
SBE_NODISCARD std::int8_t exponent() const SBE_NOEXCEPT
{
std::int8_t val;
std::memcpy(&val, m_buffer + m_offset + 8, sizeof(std::int8_t));
return (val);
}
Decimal64NULL &exponent(const std::int8_t value) SBE_NOEXCEPT
{
std::int8_t val = (value);
std::memcpy(m_buffer + m_offset + 8, &val, sizeof(std::int8_t));
return *this;
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& builder, Decimal64NULL writer)
{
builder << '{';
builder << R"("mantissa": )";
builder << +writer.mantissa();
builder << ", ";
builder << R"("exponent": )";
builder << +writer.exponent();
builder << '}';
return builder;
}
};
}
#endif
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,141 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_EXECACKSTATUS_H_
#define _ILINKBINARY_EXECACKSTATUS_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class ExecAckStatus
{
public:
enum Value
{
Accepted = (std::uint8_t)1,
Rejected = (std::uint8_t)2,
NULL_VALUE = (std::uint8_t)255
};
static ExecAckStatus::Value get(const std::uint8_t value)
{
switch (value)
{
case 1: return Accepted;
case 2: return Rejected;
case 255: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum ExecAckStatus [E103]");
}
static const char* c_str(const ExecAckStatus::Value value)
{
switch (value)
{
case Accepted: return "Accepted";
case Rejected: return "Rejected";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum ExecAckStatus [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, ExecAckStatus::Value m)
{
return os << ExecAckStatus::c_str(m);
}
};
}
#endif
@@ -0,0 +1,518 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_EXECINST_H_
#define _ILINKBINARY_EXECINST_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class ExecInst
{
private:
char *m_buffer = nullptr;
std::uint64_t m_bufferLength = 0;
std::uint64_t m_offset = 0;
std::uint64_t m_actingVersion = 0;
public:
enum MetaAttribute
{
EPOCH, TIME_UNIT, SEMANTIC_TYPE, PRESENCE
};
union sbe_float_as_uint_u
{
float fp_value;
std::uint32_t uint_value;
};
union sbe_double_as_uint_u
{
double fp_value;
std::uint64_t uint_value;
};
ExecInst() = default;
ExecInst(
char *buffer,
const std::uint64_t offset,
const std::uint64_t bufferLength,
const std::uint64_t actingVersion) :
m_buffer(buffer),
m_bufferLength(bufferLength),
m_offset(offset),
m_actingVersion(actingVersion)
{
if (SBE_BOUNDS_CHECK_EXPECT(((m_offset + 1) > m_bufferLength), false))
{
throw std::runtime_error("buffer too short for flyweight [E107]");
}
}
ExecInst(
char *buffer,
const std::uint64_t bufferLength,
const std::uint64_t actingVersion) :
ExecInst(buffer, 0, bufferLength, actingVersion)
{
}
ExecInst(
char *buffer,
const std::uint64_t bufferLength) :
ExecInst(buffer, 0, bufferLength, sbeSchemaVersion())
{
}
ExecInst &wrap(
char *buffer,
const std::uint64_t offset,
const std::uint64_t actingVersion,
const std::uint64_t bufferLength)
{
return *this = ExecInst(buffer, offset, bufferLength, actingVersion);
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint64_t encodedLength() SBE_NOEXCEPT
{
return 1;
}
SBE_NODISCARD std::uint64_t offset() const SBE_NOEXCEPT
{
return m_offset;
}
SBE_NODISCARD const char * buffer() const SBE_NOEXCEPT
{
return m_buffer;
}
SBE_NODISCARD char * buffer() SBE_NOEXCEPT
{
return m_buffer;
}
SBE_NODISCARD std::uint64_t bufferLength() const SBE_NOEXCEPT
{
return m_bufferLength;
}
SBE_NODISCARD std::uint64_t actingVersion() const SBE_NOEXCEPT
{
return m_actingVersion;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t sbeSchemaId() SBE_NOEXCEPT
{
return (std::uint16_t)8;
}
SBE_NODISCARD static SBE_CONSTEXPR std::uint16_t sbeSchemaVersion() SBE_NOEXCEPT
{
return (std::uint16_t)5;
}
ExecInst &clear()
{
std::uint8_t zero = 0;
std::memcpy(m_buffer + m_offset, &zero, sizeof(std::uint8_t));
return *this;
}
SBE_NODISCARD bool isEmpty() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return 0 == val;
}
SBE_NODISCARD std::uint8_t rawValue() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return val;
}
ExecInst &rawValue(std::uint8_t value)
{
std::memcpy(m_buffer + m_offset, &value, sizeof(std::uint8_t));
return *this;
}
static bool aON(const std::uint8_t bits)
{
return (bits & (1u << 0u)) != 0;
}
static std::uint8_t aON(const std::uint8_t bits, const bool value)
{
return value ? static_cast<std::uint8_t>(bits | (1u << 0u)) : static_cast<std::uint8_t>(bits & ~(1u << 0u));
}
SBE_NODISCARD bool aON() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return ((val) & (1u << 0u)) != 0;
}
ExecInst &aON(const bool value)
{
std::uint8_t bits;
std::memcpy(&bits, m_buffer + m_offset, sizeof(std::uint8_t));
bits = (value ? static_cast<std::uint8_t>((bits) | (1u << 0u)) : static_cast<std::uint8_t>((bits) & ~(1u << 0u)));
std::memcpy(m_buffer + m_offset, &bits, sizeof(std::uint8_t));
return *this;
}
static bool oB(const std::uint8_t bits)
{
return (bits & (1u << 1u)) != 0;
}
static std::uint8_t oB(const std::uint8_t bits, const bool value)
{
return value ? static_cast<std::uint8_t>(bits | (1u << 1u)) : static_cast<std::uint8_t>(bits & ~(1u << 1u));
}
SBE_NODISCARD bool oB() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return ((val) & (1u << 1u)) != 0;
}
ExecInst &oB(const bool value)
{
std::uint8_t bits;
std::memcpy(&bits, m_buffer + m_offset, sizeof(std::uint8_t));
bits = (value ? static_cast<std::uint8_t>((bits) | (1u << 1u)) : static_cast<std::uint8_t>((bits) & ~(1u << 1u)));
std::memcpy(m_buffer + m_offset, &bits, sizeof(std::uint8_t));
return *this;
}
static bool nH(const std::uint8_t bits)
{
return (bits & (1u << 2u)) != 0;
}
static std::uint8_t nH(const std::uint8_t bits, const bool value)
{
return value ? static_cast<std::uint8_t>(bits | (1u << 2u)) : static_cast<std::uint8_t>(bits & ~(1u << 2u));
}
SBE_NODISCARD bool nH() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return ((val) & (1u << 2u)) != 0;
}
ExecInst &nH(const bool value)
{
std::uint8_t bits;
std::memcpy(&bits, m_buffer + m_offset, sizeof(std::uint8_t));
bits = (value ? static_cast<std::uint8_t>((bits) | (1u << 2u)) : static_cast<std::uint8_t>((bits) & ~(1u << 2u)));
std::memcpy(m_buffer + m_offset, &bits, sizeof(std::uint8_t));
return *this;
}
static bool reserved1(const std::uint8_t bits)
{
return (bits & (1u << 3u)) != 0;
}
static std::uint8_t reserved1(const std::uint8_t bits, const bool value)
{
return value ? static_cast<std::uint8_t>(bits | (1u << 3u)) : static_cast<std::uint8_t>(bits & ~(1u << 3u));
}
SBE_NODISCARD bool reserved1() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return ((val) & (1u << 3u)) != 0;
}
ExecInst &reserved1(const bool value)
{
std::uint8_t bits;
std::memcpy(&bits, m_buffer + m_offset, sizeof(std::uint8_t));
bits = (value ? static_cast<std::uint8_t>((bits) | (1u << 3u)) : static_cast<std::uint8_t>((bits) & ~(1u << 3u)));
std::memcpy(m_buffer + m_offset, &bits, sizeof(std::uint8_t));
return *this;
}
static bool reserved2(const std::uint8_t bits)
{
return (bits & (1u << 4u)) != 0;
}
static std::uint8_t reserved2(const std::uint8_t bits, const bool value)
{
return value ? static_cast<std::uint8_t>(bits | (1u << 4u)) : static_cast<std::uint8_t>(bits & ~(1u << 4u));
}
SBE_NODISCARD bool reserved2() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return ((val) & (1u << 4u)) != 0;
}
ExecInst &reserved2(const bool value)
{
std::uint8_t bits;
std::memcpy(&bits, m_buffer + m_offset, sizeof(std::uint8_t));
bits = (value ? static_cast<std::uint8_t>((bits) | (1u << 4u)) : static_cast<std::uint8_t>((bits) & ~(1u << 4u)));
std::memcpy(m_buffer + m_offset, &bits, sizeof(std::uint8_t));
return *this;
}
static bool reserved3(const std::uint8_t bits)
{
return (bits & (1u << 5u)) != 0;
}
static std::uint8_t reserved3(const std::uint8_t bits, const bool value)
{
return value ? static_cast<std::uint8_t>(bits | (1u << 5u)) : static_cast<std::uint8_t>(bits & ~(1u << 5u));
}
SBE_NODISCARD bool reserved3() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return ((val) & (1u << 5u)) != 0;
}
ExecInst &reserved3(const bool value)
{
std::uint8_t bits;
std::memcpy(&bits, m_buffer + m_offset, sizeof(std::uint8_t));
bits = (value ? static_cast<std::uint8_t>((bits) | (1u << 5u)) : static_cast<std::uint8_t>((bits) & ~(1u << 5u)));
std::memcpy(m_buffer + m_offset, &bits, sizeof(std::uint8_t));
return *this;
}
static bool reserved4(const std::uint8_t bits)
{
return (bits & (1u << 6u)) != 0;
}
static std::uint8_t reserved4(const std::uint8_t bits, const bool value)
{
return value ? static_cast<std::uint8_t>(bits | (1u << 6u)) : static_cast<std::uint8_t>(bits & ~(1u << 6u));
}
SBE_NODISCARD bool reserved4() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return ((val) & (1u << 6u)) != 0;
}
ExecInst &reserved4(const bool value)
{
std::uint8_t bits;
std::memcpy(&bits, m_buffer + m_offset, sizeof(std::uint8_t));
bits = (value ? static_cast<std::uint8_t>((bits) | (1u << 6u)) : static_cast<std::uint8_t>((bits) & ~(1u << 6u)));
std::memcpy(m_buffer + m_offset, &bits, sizeof(std::uint8_t));
return *this;
}
static bool reserved5(const std::uint8_t bits)
{
return (bits & (1u << 7u)) != 0;
}
static std::uint8_t reserved5(const std::uint8_t bits, const bool value)
{
return value ? static_cast<std::uint8_t>(bits | (1u << 7u)) : static_cast<std::uint8_t>(bits & ~(1u << 7u));
}
SBE_NODISCARD bool reserved5() const
{
std::uint8_t val;
std::memcpy(&val, m_buffer + m_offset, sizeof(std::uint8_t));
return ((val) & (1u << 7u)) != 0;
}
ExecInst &reserved5(const bool value)
{
std::uint8_t bits;
std::memcpy(&bits, m_buffer + m_offset, sizeof(std::uint8_t));
bits = (value ? static_cast<std::uint8_t>((bits) | (1u << 7u)) : static_cast<std::uint8_t>((bits) & ~(1u << 7u)));
std::memcpy(m_buffer + m_offset, &bits, sizeof(std::uint8_t));
return *this;
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& builder, ExecInst writer)
{
builder << '[';
bool atLeastOne = false;
if (writer.aON())
{
builder << R"("aON")";
atLeastOne = true;
}
if (writer.oB())
{
if (atLeastOne)
{
builder << ",";
}
builder << R"("oB")";
atLeastOne = true;
}
if (writer.nH())
{
if (atLeastOne)
{
builder << ",";
}
builder << R"("nH")";
atLeastOne = true;
}
if (writer.reserved1())
{
if (atLeastOne)
{
builder << ",";
}
builder << R"("reserved1")";
atLeastOne = true;
}
if (writer.reserved2())
{
if (atLeastOne)
{
builder << ",";
}
builder << R"("reserved2")";
atLeastOne = true;
}
if (writer.reserved3())
{
if (atLeastOne)
{
builder << ",";
}
builder << R"("reserved3")";
atLeastOne = true;
}
if (writer.reserved4())
{
if (atLeastOne)
{
builder << ",";
}
builder << R"("reserved4")";
atLeastOne = true;
}
if (writer.reserved5())
{
if (atLeastOne)
{
builder << ",";
}
builder << R"("reserved5")";
}
builder << ']';
return builder;
}
};
}
#endif
@@ -0,0 +1,141 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_EXECMODE_H_
#define _ILINKBINARY_EXECMODE_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class ExecMode
{
public:
enum Value
{
Aggressive = (char)65,
Passive = (char)80,
NULL_VALUE = (char)0
};
static ExecMode::Value get(const char value)
{
switch (value)
{
case 65: return Aggressive;
case 80: return Passive;
case 0: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum ExecMode [E103]");
}
static const char* c_str(const ExecMode::Value value)
{
switch (value)
{
case Aggressive: return "Aggressive";
case Passive: return "Passive";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum ExecMode [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, ExecMode::Value m)
{
return os << ExecMode::c_str(m);
}
};
}
#endif
@@ -0,0 +1,162 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_EXECREASON_H_
#define _ILINKBINARY_EXECREASON_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class ExecReason
{
public:
enum Value
{
MarketExchangeOption = (std::uint8_t)8,
CancelledNotBest = (std::uint8_t)9,
CancelOnDisconnect = (std::uint8_t)100,
SelfMatchPreventionOldestOrderCancelled = (std::uint8_t)103,
CancelOnGlobexCreditControlsViolation = (std::uint8_t)104,
CancelFromFirmsoft = (std::uint8_t)105,
CancelFromRiskManagementAPI = (std::uint8_t)106,
SelfMatchPreventionNewestOrderCancelled = (std::uint8_t)107,
Cancelduetovolquotedoptionorderrestedqtylessthanminordersize = (std::uint8_t)108,
NULL_VALUE = (std::uint8_t)255
};
static ExecReason::Value get(const std::uint8_t value)
{
switch (value)
{
case 8: return MarketExchangeOption;
case 9: return CancelledNotBest;
case 100: return CancelOnDisconnect;
case 103: return SelfMatchPreventionOldestOrderCancelled;
case 104: return CancelOnGlobexCreditControlsViolation;
case 105: return CancelFromFirmsoft;
case 106: return CancelFromRiskManagementAPI;
case 107: return SelfMatchPreventionNewestOrderCancelled;
case 108: return Cancelduetovolquotedoptionorderrestedqtylessthanminordersize;
case 255: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum ExecReason [E103]");
}
static const char* c_str(const ExecReason::Value value)
{
switch (value)
{
case MarketExchangeOption: return "MarketExchangeOption";
case CancelledNotBest: return "CancelledNotBest";
case CancelOnDisconnect: return "CancelOnDisconnect";
case SelfMatchPreventionOldestOrderCancelled: return "SelfMatchPreventionOldestOrderCancelled";
case CancelOnGlobexCreditControlsViolation: return "CancelOnGlobexCreditControlsViolation";
case CancelFromFirmsoft: return "CancelFromFirmsoft";
case CancelFromRiskManagementAPI: return "CancelFromRiskManagementAPI";
case SelfMatchPreventionNewestOrderCancelled: return "SelfMatchPreventionNewestOrderCancelled";
case Cancelduetovolquotedoptionorderrestedqtylessthanminordersize: return "Cancelduetovolquotedoptionorderrestedqtylessthanminordersize";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum ExecReason [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, ExecReason::Value m)
{
return os << ExecReason::c_str(m);
}
};
}
#endif
@@ -0,0 +1,141 @@
/* Generated SBE (Simple Binary Encoding) message codec */
#ifndef _ILINKBINARY_EXECTYPTRDCXL_H_
#define _ILINKBINARY_EXECTYPTRDCXL_H_
#if defined(SBE_HAVE_CMATH)
/* cmath needed for std::numeric_limits<double>::quiet_NaN() */
# include <cmath>
# define SBE_FLOAT_NAN std::numeric_limits<float>::quiet_NaN()
# define SBE_DOUBLE_NAN std::numeric_limits<double>::quiet_NaN()
#else
/* math.h needed for NAN */
# include <math.h>
# define SBE_FLOAT_NAN NAN
# define SBE_DOUBLE_NAN NAN
#endif
#if __cplusplus >= 201103L
# define SBE_CONSTEXPR constexpr
# define SBE_NOEXCEPT noexcept
#else
# define SBE_CONSTEXPR
# define SBE_NOEXCEPT
#endif
#if __cplusplus >= 201402L
# define SBE_CONSTEXPR_14 constexpr
#else
# define SBE_CONSTEXPR_14
#endif
#if __cplusplus >= 201703L
# include <string_view>
# define SBE_NODISCARD [[nodiscard]]
#else
# define SBE_NODISCARD
#endif
#if !defined(__STDC_LIMIT_MACROS)
# define __STDC_LIMIT_MACROS 1
#endif
#include <cstdint>
#include <cstring>
#include <iomanip>
#include <limits>
#include <ostream>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
#if defined(WIN32) || defined(_WIN32)
# define SBE_BIG_ENDIAN_ENCODE_16(v) _byteswap_ushort(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) _byteswap_ulong(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) _byteswap_uint64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
# define SBE_BIG_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) (v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) (v)
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define SBE_LITTLE_ENDIAN_ENCODE_16(v) __builtin_bswap16(v)
# define SBE_LITTLE_ENDIAN_ENCODE_32(v) __builtin_bswap32(v)
# define SBE_LITTLE_ENDIAN_ENCODE_64(v) __builtin_bswap64(v)
# define SBE_BIG_ENDIAN_ENCODE_16(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_32(v) (v)
# define SBE_BIG_ENDIAN_ENCODE_64(v) (v)
#else
# error "Byte Ordering of platform not determined. Set __BYTE_ORDER__ manually before including this file."
#endif
#if defined(SBE_NO_BOUNDS_CHECK)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (false)
#elif defined(_MSC_VER)
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (exp)
#else
# define SBE_BOUNDS_CHECK_EXPECT(exp,c) (__builtin_expect(exp,c))
#endif
#define SBE_NULLVALUE_INT8 (std::numeric_limits<std::int8_t>::min)()
#define SBE_NULLVALUE_INT16 (std::numeric_limits<std::int16_t>::min)()
#define SBE_NULLVALUE_INT32 (std::numeric_limits<std::int32_t>::min)()
#define SBE_NULLVALUE_INT64 (std::numeric_limits<std::int64_t>::min)()
#define SBE_NULLVALUE_UINT8 (std::numeric_limits<std::uint8_t>::max)()
#define SBE_NULLVALUE_UINT16 (std::numeric_limits<std::uint16_t>::max)()
#define SBE_NULLVALUE_UINT32 (std::numeric_limits<std::uint32_t>::max)()
#define SBE_NULLVALUE_UINT64 (std::numeric_limits<std::uint64_t>::max)()
namespace iLinkBinary {
class ExecTypTrdCxl
{
public:
enum Value
{
TradeCorrection = (char)71,
TradeCancel = (char)72,
NULL_VALUE = (char)0
};
static ExecTypTrdCxl::Value get(const char value)
{
switch (value)
{
case 71: return TradeCorrection;
case 72: return TradeCancel;
case 0: return NULL_VALUE;
}
throw std::runtime_error("unknown value for enum ExecTypTrdCxl [E103]");
}
static const char* c_str(const ExecTypTrdCxl::Value value)
{
switch (value)
{
case TradeCorrection: return "TradeCorrection";
case TradeCancel: return "TradeCancel";
case NULL_VALUE: return "NULL_VALUE";
}
throw std::runtime_error("unknown value for enum ExecTypTrdCxl [E103]:");
}
template<typename CharT, typename Traits>
friend std::basic_ostream<CharT, Traits>& operator << (
std::basic_ostream<CharT, Traits>& os, ExecTypTrdCxl::Value m)
{
return os << ExecTypTrdCxl::c_str(m);
}
};
}
#endif
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
Loaded 100 of 248 files, more files were not shown because too many files have changed in this diff. Show more