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