Compare commits

..
2 Commits
Author SHA1 Message Date
John Colvin e9fdbc2acd ui (refactor): Consolidate (Repeat)Button colors to one class
The only difference between a RepeatButton and a regular Button is in
the click-behavior (they should look identical).
2022-12-12 11:47:20 -05:00
John Colvin a50e0cfc26 fix: Add a couple null checks 2022-12-12 11:01:01 -05:00
226 changed files with 7426 additions and 9698 deletions

No files matched your search

-18
View File
@@ -7,24 +7,6 @@
"commands": [
"dotnet-format"
]
},
"fable": {
"version": "4.0.0-theta-018",
"commands": [
"fable"
]
},
"fantomas": {
"version": "5.2.2",
"commands": [
"fantomas"
]
},
"fake-cli": {
"version": "6.0.0",
"commands": [
"fake"
]
}
}
}
-1
View File
@@ -106,7 +106,6 @@ else()
add_custom_target(server_layout ALL DEPENDS ${CMAKE_BINARY_DIR}/server)
install(DIRECTORY "${CMAKE_BINARY_DIR}/server/plugins" DESTINATION bin)
install(FILES "${CMAKE_SOURCE_DIR}/externals/linux/lib/${CMAKE_BUILD_TYPE}/libACE-5.7.5.so" DESTINATION bin)
install(FILES "${CMAKE_SOURCE_DIR}/externals/linux/lib/${CMAKE_BUILD_TYPE}/libOnixS.IceImpactMulticastPriceFeedHandlerCpp.so.3.16.0.0" DESTINATION bin)
install(FILES "${CMAKE_SOURCE_DIR}/externals/src/emumba/sparkd.lic" DESTINATION bin)
+12 -32
View File
@@ -1,10 +1,10 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32922.545
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_api", "src\client\spark_api\spark_api.csproj", "{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libspark", "build\src\lib\libspark.vcxproj", "{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libspark", "build\src\lib\libspark.vcxproj", "{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spark", "src\client\spark\Spark.csproj", "{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}"
EndProject
@@ -14,15 +14,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_core", "src\client\sp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_sdk", "src\client\spark_sdk\spark_sdk.csproj", "{6963C314-83C4-4667-B0D0-C2F7AE208C29}"
ProjectSection(ProjectDependencies) = postProject
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25} = {FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40} = {9FA60215-26AF-3EB7-AB89-D4F4B126EF40}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_test", "src\client\spark_test\spark_test.csproj", "{ECD78CC5-138F-4809-A764-2358C2AC2E82}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_websocket", "src\client\spark_websocket\spark_websocket.csproj", "{3201359D-C071-4089-9EDE-B04D759F1508}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_api_server", "src\client\spark_api_server\spark_api_server.csproj", "{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -39,14 +35,14 @@ Global
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|x64.Build.0 = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.Build.0 = Release|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.Debug|x64.ActiveCfg = Debug|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.Debug|x64.Build.0 = Debug|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.Release|x64.ActiveCfg = Release|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.Release|x64.Build.0 = Release|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{FDC3A021-386E-3A2C-A7EB-CBE94A95BE25}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}.Debug|x64.ActiveCfg = Debug|x64
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}.Debug|x64.Build.0 = Debug|x64
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}.MinSizeRel|x64.Build.0 = MinSizeRel|x64
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}.Release|x64.ActiveCfg = Release|x64
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}.Release|x64.Build.0 = Release|x64
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{9FA60215-26AF-3EB7-AB89-D4F4B126EF40}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x64.ActiveCfg = Debug|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x64.Build.0 = Debug|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.MinSizeRel|x64.ActiveCfg = Release|x64
@@ -87,22 +83,6 @@ Global
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Release|x64.Build.0 = Release|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.RelWithDebInfo|x64.Build.0 = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|x64.ActiveCfg = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|x64.Build.0 = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|x64.ActiveCfg = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|x64.Build.0 = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|x64.ActiveCfg = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|x64.Build.0 = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|x64.Build.0 = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|x64.ActiveCfg = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|x64.Build.0 = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|x64.ActiveCfg = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|x64.Build.0 = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|x64.ActiveCfg = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|x64.Build.0 = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+53 -55
View File
@@ -1,55 +1,53 @@
<Project>
<PropertyGroup>
<ComputerSpecificConfig>..\..\tools\override\$(computername).props</ComputerSpecificConfig>
<SparkRoot>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)\..\..))</SparkRoot>
<SourceRoot>$([System.IO.Path]::GetFullPath($(SparkRoot)\src))</SourceRoot>
<Externals>$(SparkRoot)\externals\windows</Externals>
<DepotName>$([System.IO.Path]::GetFileName($([System.IO.Path]::GetFullPath($(SparkRoot)))))</DepotName>
<ErrorReport>None</ErrorReport>
<Prefer32Bit>False</Prefer32Bit>
<Deterministic>true</Deterministic>
<EnableDefaultContentItems>False</EnableDefaultContentItems>
<ShowMissingItemTypes>false</ShowMissingItemTypes>
<Configuration Condition="'$(configuration)'==''">Debug</Configuration>
<EnablePreviewFeatures>true</EnablePreviewFeatures>
<LangVersion>11</LangVersion>
</PropertyGroup>
<PropertyGroup Label="Output">
<BaseOutputPath>$(SparkRoot)\build\$(Configuration)</BaseOutputPath>
<OutputPath>$(BaseOutputPath)\bin</OutputPath>
<BaseIntermediateOutputPath>$(BaseOutputPath)\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseOutputPath)\obj\$(MSBuildProjectName)</IntermediateOutputPath>
<ProtoOutputPath>$(BaseOutputPath)\obj\$(MSBuildProjectName)</ProtoOutputPath>
<GenDir>$(BaseOutputPath)\gen\$(MSBuildProjectName)</GenDir>
</PropertyGroup>
<Import
Project="$(ComputerSpecificConfig)"
Condition="Exists($(ComputerSpecificConfig))" />
<PropertyGroup Label="ProtoBuf">
<ProtocPluginBase>$(SparkRoot)\src\lib\api\service_compiler</ProtocPluginBase>
<protoc>$(Externals)\bin\protoc.exe</protoc>
<protogen>$(Externals)\bin\protogen.exe</protogen>
</PropertyGroup>
<ItemDefinitionGroup>
<Proto2></Proto2>
<Proto3>
<OutBase>$(IntermediateOutputPath)\gen\%(relativedir)</OutBase>
<OutCS>%(OutBase)%(FileName).cs</OutCS>
<OutCSClient>%(OutBase)%(FileName).client.pb.cs</OutCSClient>
<OutCSServer>%(OutBase)%(FileName).server.pb.cs</OutCSServer>
<OutCSImmutable>%(OutBase)%(FileName).immutable.pb.cs</OutCSImmutable>
<CompileOptions></CompileOptions>
</Proto3>
<Proto3Excel>
<OutBase>$(IntermediateOutputPath)\gen\%(relativedir)</OutBase>
<OutCSExcel>%(OutBase)%(FileName).excel.pb.cs</OutCSExcel>
<CompileOptions></CompileOptions>
</Proto3Excel>
</ItemDefinitionGroup>
</Project>
<Project>
<PropertyGroup>
<ComputerSpecificConfig>..\..\tools\override\$(computername).props</ComputerSpecificConfig>
<SparkRoot>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)\..\..))</SparkRoot>
<SourceRoot>$([System.IO.Path]::GetFullPath($(SparkRoot)\src))</SourceRoot>
<Externals>$(SparkRoot)\externals\windows</Externals>
<DepotName>$([System.IO.Path]::GetFileName($([System.IO.Path]::GetFullPath($(SparkRoot)))))</DepotName>
<ErrorReport>None</ErrorReport>
<Prefer32Bit>False</Prefer32Bit>
<Deterministic>true</Deterministic>
<EnableDefaultContentItems>False</EnableDefaultContentItems>
<ShowMissingItemTypes>false</ShowMissingItemTypes>
<Configuration Condition="'$(configuration)'==''">Debug</Configuration>
<EnablePreviewFeatures>true</EnablePreviewFeatures>
</PropertyGroup>
<PropertyGroup Label="Output">
<BaseOutputPath>$(SparkRoot)\build\$(Configuration)</BaseOutputPath>
<OutputPath>$(BaseOutputPath)\bin</OutputPath>
<BaseIntermediateOutputPath>$(BaseOutputPath)\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<IntermediateOutputPath>$(BaseOutputPath)\obj\$(MSBuildProjectName)</IntermediateOutputPath>
<GenDir>$(BaseOutputPath)\gen\$(MSBuildProjectName)</GenDir>
</PropertyGroup>
<Import
Project="$(ComputerSpecificConfig)"
Condition="Exists($(ComputerSpecificConfig))" />
<PropertyGroup Label="ProtoBuf">
<ProtocPluginBase>$(SparkRoot)\src\lib\api\service_compiler</ProtocPluginBase>
<protoc>$(Externals)\bin\protoc.exe</protoc>
<protogen>$(Externals)\bin\protogen.exe</protogen>
</PropertyGroup>
<ItemDefinitionGroup>
<Proto2></Proto2>
<Proto3>
<OutBase>$(IntermediateOutputPath)\gen\%(relativedir)</OutBase>
<OutCS>%(OutBase)%(FileName).cs</OutCS>
<OutCSClient>%(OutBase)%(FileName).client.pb.cs</OutCSClient>
<OutCSServer>%(OutBase)%(FileName).server.pb.cs</OutCSServer>
<OutCSImmutable>%(OutBase)%(FileName).immutable.pb.cs</OutCSImmutable>
<CompileOptions></CompileOptions>
</Proto3>
<Proto3Excel>
<OutBase>$(IntermediateOutputPath)\gen\%(relativedir)</OutBase>
<OutCSExcel>%(OutBase)%(FileName).excel.pb.cs</OutCSExcel>
<CompileOptions></CompileOptions>
</Proto3Excel>
</ItemDefinitionGroup>
</Project>
@@ -3,6 +3,7 @@ namespace mbts.spark {
using bts.api;
using bts.api.analytics;
using bts.collections;
using bts.reactive;
using bts.utils;
using mbts;
@@ -17,7 +18,6 @@ namespace mbts.spark {
using Spark.Core;
using Spark.Core.Collections;
using Spark.Core.Disposables;
using Spark.Core.Reactive;
using Spark.ViewModel.Commands;
using System;
@@ -43,7 +43,6 @@ namespace mbts.spark {
readonly ObservableHashSet<AnalyticsExpirationParametersRowVM> _selected_rows = new();
readonly DeferrableAction _raise_selected_rows_changed;
readonly IRaiseCanExecuteChangedCommand _set_driver_to_nearest_exp_cmd;
IList<string>? _pending_selected_symbols;
AnalyticsExpirationParametersMap? _parameter_map;
(ICommand cmd, IDisposable can_exe_sub)? _smart_copy_roll_target_to_selection_cmd;
@@ -66,7 +65,9 @@ namespace mbts.spark {
_is_dirty = backing(nameof(is_dirty), () => rows.Any(r => r.is_dirty));
if (startup_data is not null) {
_pending_selected_symbols = startup_data.selected_symbols;
if (!startup_data.selected_symbols.is_null_or_empty()) {
selected_symbols.AddRange(startup_data.selected_symbols);
}
auto_copy_rolls_is_checked = startup_data.auto_copy_rolls_is_checked;
auto_copy_rates_is_checked = startup_data.auto_copy_rates_is_checked;
}
@@ -296,8 +297,8 @@ namespace mbts.spark {
symbols.sync_with(_parameters.Select(p => p.security.symbol).Distinct().Ordered());
using var _ = _sync_visible_rows.defer();
if (is_first_update) {
selected_symbols.sync_with(_pending_selected_symbols?.Intersect(symbols) ?? symbols);
_pending_selected_symbols = null;
// select all symbols on first update
selected_symbols.sync_with(symbols);
}
}
@@ -1,120 +0,0 @@
namespace mbts.spark {
using bts;
using bts.api;
using mbts;
using mbts.analytics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
// For each vs, it sends the vol surface calc request (_do_periodic_auto_fit)
// and then commits the response
public class SingleVolSurfaceAutoFitSource : IDisposable {
private readonly ThreadedBlackboard _bb;
private readonly int _vs_id;
private readonly ITag<VolSurfaceInput> _vs_input_tag;
private readonly ITag<VolSurfaceCalculationResponse> _vs_calc_response_tag;
private DateTime _last_req_time = DateTime.MinValue;
private TimeSpan _req_period = TimeSpan.MaxValue;
private int _req_id = 0;
public SingleVolSurfaceAutoFitSource(int vs_id, ThreadedBlackboard bb) {
_bb = bb;
_vs_id = vs_id;
_vs_input_tag = SparkTags.VolSurfaceCommittedInputTag(vs_id);
_vs_calc_response_tag = SparkTags.VolSurfaceAutoCalculationResponseTag(vs_id);
_bb.subscribe(_vs_input_tag);
_bb.subscribe(_vs_calc_response_tag);
_bb.subscribe(SparkTags.CurrentUser);
_bb.data_callback += _on_bb_data;
_bb.timer_callback += _on_bb_timer;
}
private void _on_bb_data(object tag, object data) {
if (tag.Equals(_vs_input_tag))
_possibly_autofit();
else if (tag.Equals(_vs_calc_response_tag)) {
VolSurfaceCalculationResponse calc_resp = data as VolSurfaceCalculationResponse;
bts.Log.Gen.info($"SingleVolSurfaceAutoFitSource._on_bb_data vs_id: {_vs_id} " +
$"received calculation response");
_bb.post(SparkTags.VolSurfaceCommitTag(_vs_id),
calc_resp.volsurface_calculation_output.volsurface_input);
}
}
private bool _user_has_vs_control() {
VolSurfaceInput vs_input = _bb.read_state(_vs_input_tag);
string current_user = _bb.read_state(SparkTags.CurrentUser).name;
return vs_input != null &&
vs_input.surface_settings.core_settings.vs_manager == current_user;
}
private void _on_bb_timer() {
_possibly_autofit();
}
private void _possibly_autofit() {
var auto_fit_period = _get_auto_fit_periodic();
if (!auto_fit_period.HasValue)
return;
if (DateTime.Now - _last_req_time <= auto_fit_period)
return;
if (!_user_has_vs_control())
return;
// auto fit here
bts.Log.Gen.info($"SingleVolSurfaceAutoFitSource vs_id: {_vs_id} requesting fit " +
$"last_req_time: {_last_req_time} period: {auto_fit_period.Value}");
_send_request();
}
private Nullable<TimeSpan> _get_auto_fit_periodic() {
VolSurfaceInput vs_input = _bb.read_state(_vs_input_tag);
if (vs_input == null)
return null;
var fit_settings =
VolSurfaceDataFunctions.get_market_fit_settings(vs_input.surface_settings);
if (fit_settings == null)
return null;
var auto_fit_setting = fit_settings.vs_auto_fit_settings;
if (auto_fit_setting == null)
return null;
if (auto_fit_setting.auto_fit_region == VolSurfaceEnums.VolCurveFitRegion.None)
return null;
var time_based_fit_setting = auto_fit_setting.time_based_settings;
if (time_based_fit_setting == null)
return null;
if (!time_based_fit_setting.period_seconds.HasValue)
return null;
return TimeSpan.FromSeconds(time_based_fit_setting.period_seconds.Value);
}
private void _send_request() {
VolSurfaceInput vs_input = _bb.read_state(_vs_input_tag);
if (vs_input == null)
return;
VolCurveMarketFitAction mf_action = new VolCurveMarketFitAction(
VolCurveMarketFitAction.ActionType.FitWholeCurve, null, false);
VolCurveAction vc_action = new VolCurveAction(mf_action);
IDictionary<VolSurfaceExpiration, VolCurveAction> action_map =
vs_input.surface_parameters.curve_parameters_map.ToDictionary(
i => i.Item1,
i => vc_action
);
VolSurfaceCalculationRequest req = new VolSurfaceCalculationRequest(vs_input,
_req_id++, action_map, true, true);
_last_req_time = DateTime.Now;
_bb.post(SparkTags.VolSurfaceAutoCalculationRequestTag(_vs_id), req);
}
#region IDisposable
public void Dispose() {
_bb.data_callback -= _on_bb_data;
_bb.timer_callback -= _on_bb_timer;
}
#endregion
}
}
@@ -63,9 +63,9 @@ namespace mbts.spark {
vs_input, vs_nonvol_data.contracts, aux_data_map);
_timer.stop();
var tag_str = tag == null ? "Null" : tag.ToString();
// bts.Log.Gen.info($"SingleVolSurfaceCommittedOutputRetriever._recompute_and_publish " +
// $"vs_id: {_vs_id} time:{_timer.lastIntervalTime} ms tag:{tag_str} " +
// $"tid:{_tid()}"); //output: {vs_output.log_string()}*/");
bts.Log.Gen.info($"SingleVolSurfaceCommittedOutputRetriever._recompute_and_publish " +
$"vs_id: {_vs_id} time:{_timer.lastIntervalTime} ms tag:{tag_str} " +
$"tid:{_tid()}"); //output: {vs_output.log_string()}*/");
_logger.log(_log_id, _log_id, _timer.lastIntervalTime);
_bb.post(_out_bb_computed_vol_tag, vs_output);
}
@@ -4,7 +4,6 @@
using bts.api.analytics;
using mbts.analytics;
using mbts.ui;
using Spark.Core.Protobuf;
@@ -14,7 +13,6 @@
using System.Linq;
using System.Reactive.Linq;
using System.Threading;
using System.Windows;
// For a single VolSurface this class
// 1. Listents to commmits and calls the service to persist data
@@ -26,6 +24,7 @@
private readonly ITag<VolSurfaceInput> _in_bb_committ_tag;
private readonly AnalyticsService _analytics_service;
private readonly HighPerformanceTimer _timer = new HighPerformanceTimer();
private readonly string _user;
private readonly List<IDisposable> _disposables = new List<IDisposable>();
private IDictionary<UInt64, VolSurfaceInputSnapshot> _snp_shot_map = new
Dictionary<UInt64, VolSurfaceInputSnapshot>();
@@ -36,10 +35,10 @@
volsurface_id));
_volsurface_id = volsurface_id;
_bb = threaded_bb;
_user = "TEST_USER"; // TODO
_in_bb_committ_tag = SparkTags.VolSurfaceCommitTag(volsurface_id);
_analytics_service = analytics_service;
_bb.subscribe(_in_bb_committ_tag);
_bb.subscribe(SparkTags.CurrentUser);
_bb.data_callback += _on_bb_data;
var vs_sub = _analytics_service.subscribei_volsurfaces()
.ObserveOn(SynchronizationContext.Current)
@@ -55,10 +54,8 @@
private void _on_vss(bts.api.core.Update<VolSurfaceEntryImmutable, UInt64> update) {
IEnumerable<VolSurfaceEntryImmutable> all_vss = update.all;
var this_vs_vss = all_vss.Where(vs => vs.VsId == _volsurface_id);
bts.Log.Gen.info(
$"SingleVolSurfaceGateway._on_vss vs_count: {this_vs_vss.Count()} " +
$"all: {update.all.Count()} added: {update.added.Count()} " +
$"updated: {update.changed.Count()} removed: {update.removed.Count()}");
bts.Log.Gen.info(String.Format("SingleVolSurfaceGateway._on_vss count:{0} vs_count:{1}",
all_vss.Count(), this_vs_vss.Count()));
if (this_vs_vss.Count() == 0) {
return;
}
@@ -86,39 +83,22 @@
static VolSurfaceInput _to_vs_input(VolSurfaceEntryImmutable vs) =>
ProtobufSerializationHelper.deserialize<VolSurfaceInput>(vs.Volsurface.ToByteArray());
// private void _show_save_error(string message) {
// BTSMessageBox.Show(message, "Vol Save Error", BTSMessageBoxButtons.OK);
// }
private void _on_bb_data(object tag, object data) {
if (_in_bb_committ_tag.Equals(tag)) {
try {
_timer.start();
VolSurfaceInput vs_input = data as VolSurfaceInput;
var user_tup = _bb.read_state(SparkTags.CurrentUser);
string current_user = user_tup.name;
string vs_manager = vs_input.surface_settings.core_settings.vs_manager;
if (current_user != vs_manager) {
string msg = $"User {current_user} does not have the permission to save vols. " +
$"Permission can be obtained via the grid context menu item 'Acquire ownership from {vs_manager}'";
BTSMessageBox.Show(msg, "Vol Save Error", BTSMessageBoxButtons.OK);
return;
}
_sanitize_input(ref vs_input);
vs_input = VolSurfaceDataFunctions.unset_driver_overrides(vs_input);
VolSurfaceUtilityFunctions.save_volsurface(vs_input, _analytics_service, current_user);
vs_input.saver_login = _user;
VolSurfaceUtilityFunctions.save_volsurface(vs_input, _analytics_service, _user);
_timer.stop();
Log.Gen.info(String.Format(
"SingleVolSurfaceGateway._on_bb_data Time to commit volsurface {0} {1} msecs",
_volsurface_id, _timer.lastIntervalTime));
var archived_theos = _get_theos();
if (archived_theos != null) {
_timer.start();
if (archived_theos != null)
_analytics_service.archive_theos(archived_theos);
_timer.stop();
Log.Gen.info($"SingleVolSurfaceGateway._on_bb_data archiving theos size: " +
$"{archived_theos.SecTheo.Count} time: {_timer.lastIntervalTime} msecs");
}
} catch (Exception ex) {
Log.Gen.warn(ex.ToString());
_bb.post(SparkTags.MessageDisplayTag,
@@ -36,11 +36,7 @@ namespace mbts.spark {
new SingleVolSurfaceDataSource(SingleVolSurfaceDataSource.SymbolListType.Committed, _vs_id, _bb,
a_syms => new SingleVolSurfaceCommittedOutputRetriever(_vs_id, _bb, a_syms)),
new SingleVolSurfaceDataSource(SingleVolSurfaceDataSource.SymbolListType.Combined, _vs_id, _bb,
a_syms => new SingleVolSurfaceRequestCalculator(
SingleVolSurfaceRequestCalculator.RequestType.UI, _vs_id, a_syms, _bb)),
new SingleVolSurfaceDataSource(SingleVolSurfaceDataSource.SymbolListType.Combined, _vs_id, _bb,
a_syms => new SingleVolSurfaceRequestCalculator(
SingleVolSurfaceRequestCalculator.RequestType.AUTO, _vs_id, a_syms, _bb)),
a_syms => new SingleVolSurfaceRequestCalculator(_vs_id, a_syms, _bb)),
new SingleVolSurfaceMarketImpliedVolSource(_vs_id, _bb),
// new SingleVolSurfaceTheoSource(_vs_id, _bb),
// TODO: suspending heatmaps for now (12/24/21)
@@ -48,7 +44,6 @@ namespace mbts.spark {
// server work that can optionally be done on the client
new SingleVolSurfaceDataSource (SingleVolSurfaceDataSource.SymbolListType.Committed, _vs_id, _bb,
a_syms => new SingleVolSurfaceInterpGreeksPublisher (_vs_id, _bb, a_syms)),
new SingleVolSurfaceAutoFitSource(_vs_id, _bb),
};
}
@@ -75,7 +75,7 @@ namespace mbts.spark {
var exp_price_map = OptionDriverPriceMap.get_vs_price_map(
all_sym_price_map, (s) => _option_symbols.Contains(s));
if (sc_data != null && vs_nonvol_input != null && exp_price_map != null) {
bts.Log.Gen.diag($"SingleVolSurfaceNonVolDataSource vs_id:{_vs_id} " +
bts.Log.Gen.info($"SingleVolSurfaceNonVolDataSource vs_id:{_vs_id} " +
"publishing VolSurfaceNonVolData");
_bb.post(_out_bb_vs_nonvol_data_tag,
new VolSurfaceNonVolData(
@@ -18,16 +18,10 @@ namespace mbts.spark {
// Pubs :
// 1. Calc Resp
public class SingleVolSurfaceRequestCalculator : IDisposable {
public enum RequestType {
UI = 0,
AUTO
}
private readonly RequestType _request_type = RequestType.UI;
private readonly int _vs_id;
private readonly HashSet<string> _symbols;
private readonly ThreadedBlackboard _bb;
private readonly ITag<VolSurfaceCalculationRequest> _in_bb_request_tag;
private readonly ITag<VolSurfaceCalculationRequest> _in_bb_auto_request_tag;
private readonly ITag<VolSurfaceNonVolData> _in_bb_nonvol_data_tag;
private readonly ITag<VolSurfaceStandardTime> _in_bb_vs_standard_time_tag;
private readonly ITag<VolSurfaceEnums.MarketSide> _in_bb_market_impliedvol_side_tag;
@@ -36,22 +30,18 @@ namespace mbts.spark {
/// data
private VolSurfaceOutput _last_output;
public SingleVolSurfaceRequestCalculator(RequestType request_type,
int vs_id, IEnumerable<string> symbols,
public SingleVolSurfaceRequestCalculator(int vs_id, IEnumerable<string> symbols,
ThreadedBlackboard threaded_bb) {
bts.Log.Gen.info($"SingleVolSurfaceRequestCalculator cons vs_id: {vs_id} request_type: {request_type}");
_request_type = request_type;
bts.Log.Gen.info($"SingleVolSurfaceRequestCalculator cons vs_id: {vs_id}");
_vs_id = vs_id;
_symbols = new HashSet<string>(symbols);
_bb = threaded_bb;
_in_bb_request_tag = SparkTags.VolSurfaceCalculationRequestTag(vs_id);
_in_bb_auto_request_tag = SparkTags.VolSurfaceAutoCalculationRequestTag(vs_id);
_in_bb_nonvol_data_tag = SparkTags.VolSurfaceNonVolDataTag(vs_id);
_in_bb_vs_standard_time_tag = SparkTags.VolSurfaceStandardTimeTag(vs_id);
_in_bb_market_impliedvol_side_tag = SparkTags.VolSurfaceMarketImpliedVolSide(vs_id);
_in_bb_dirty_tag = SparkTags.VolSurfaceDirtyStateTag(vs_id);
_bb.subscribe(_in_bb_request_tag);
_bb.subscribe(_in_bb_auto_request_tag);
_bb.subscribe(_in_bb_nonvol_data_tag);
_bb.subscribe(_in_bb_vs_standard_time_tag);
_bb.subscribe(_in_bb_vs_standard_time_tag);
@@ -61,21 +51,11 @@ namespace mbts.spark {
}
private void _on_bb_data(object tag, object data) {
switch (_request_type) {
case RequestType.UI: {
if (_in_bb_request_tag.Equals(tag) || _in_bb_dirty_tag.Equals(tag))
_recompute_and_publish(true);
else if (_in_bb_nonvol_data_tag.Equals(tag) || _in_bb_vs_standard_time_tag.Equals(tag))
_recompute_and_publish(false);
break;
}
case RequestType.AUTO: {
if (tag.Equals(_in_bb_auto_request_tag)) {
_serve_auto_request();
}
break;
}
}
if (_in_bb_request_tag.Equals(tag) || _in_bb_dirty_tag.Equals(tag))
_recompute_and_publish(true);
else if (_in_bb_nonvol_data_tag.Equals(tag) || _in_bb_vs_standard_time_tag.Equals(tag))
_recompute_and_publish(false);
}
private void _recompute_and_publish(bool is_new_request) {
@@ -100,7 +80,7 @@ namespace mbts.spark {
nonvol_data.driver_price_map,
vs_standard_time, true);
IDictionary<VolSurfaceExpiration, VolCurveAction> action_map =
_post_process_action(_bb, _vs_id, effective_req, aux_data_map);
_post_process_action(effective_req, aux_data_map);
_last_output = GeneralVolSurfaceCalculator.compute(effective_req.volsurface_input,
nonvol_data.contracts,
aux_data_map,
@@ -109,49 +89,16 @@ namespace mbts.spark {
effective_req.cascade_up,
effective_req.cascade_down);
_timer.stop();
bts.Log.Gen.info($"SingleVolSurfaceRequestCalculator._recompute_and_publish vs_id: {_vs_id} " +
$"time: {_timer.lastIntervalTime}");
bts.Log.Gen.info($"SingleVolSurfaceRequestCalculator._recompute_and_publish time: " +
$"{_timer.lastIntervalTime}");
_bb.post(SparkTags.VolSurfaceCalculationResponseTag(_vs_id),
new VolSurfaceCalculationResponse(_last_output, effective_req.request_id));
}
}
}
private void _serve_auto_request() {
bts.Log.Gen.info($"SingleVolSurfaceRequestCalculator._serve_auto_request " +
$"vs_id: {_vs_id} auto request received");
bool is_dirty = _bb.read_state(_in_bb_dirty_tag, false);
VolSurfaceNonVolData nonvol_data = _bb.read_state(_in_bb_nonvol_data_tag);
VolSurfaceStandardTime vs_standard_time = _bb.read_state(_in_bb_vs_standard_time_tag);
VolSurfaceCalculationRequest auto_req = _bb.read_state(_in_bb_auto_request_tag);
if (is_dirty || nonvol_data == null || vs_standard_time == null || auto_req == null) {
return;
}
_timer.start();
IDictionary<VolSurfaceExpiration, VolSurfaceExpirationAuxiliaryData> aux_data_map =
VolSurfaceUtilityFunctions.compute_aux_data(auto_req.volsurface_input,
nonvol_data.input,
nonvol_data.driver_price_map,
vs_standard_time, true);
IDictionary<VolSurfaceExpiration, VolCurveAction> action_map =
_post_process_action(_bb, _vs_id, auto_req, aux_data_map);
var vs_output = GeneralVolSurfaceCalculator.compute(auto_req.volsurface_input,
nonvol_data.contracts,
aux_data_map,
action_map,
null,
auto_req.cascade_up,
auto_req.cascade_down);
_timer.stop();
bts.Log.Gen.info($"SingleVolSurfaceRequestCalculator._serve_auto_request vs_id: {_vs_id} " +
$"time: {_timer.lastIntervalTime}");
_bb.post(SparkTags.VolSurfaceAutoCalculationResponseTag(_vs_id),
new VolSurfaceCalculationResponse(vs_output, auto_req.request_id));
}
/// Computes the impl vol if the action is fit to market
private static IDictionary<VolSurfaceExpiration, VolCurveAction> _post_process_action(
ThreadedBlackboard bb, int vs_id,
private IDictionary<VolSurfaceExpiration, VolCurveAction> _post_process_action(
VolSurfaceCalculationRequest req,
IDictionary<VolSurfaceExpiration, VolSurfaceExpirationAuxiliaryData> aux_data_map) {
IDictionary<VolSurfaceExpiration, VolCurveAction> rv = req.action_map;
@@ -162,7 +109,7 @@ namespace mbts.spark {
VolCurveAction rep_action = rv.ElementAt(0).Value;
if (rep_action.action_type == VolCurveAction.ActionType.FitToMarket) {
IDictionary<VolSurfaceExpiration, VolCurveMarketImpliedVolData> impl_vol_map =
_fill_in_implied_vols(bb, vs_id, req.volsurface_input, req.action_map, aux_data_map,
_fill_in_implied_vols(req.volsurface_input, req.action_map, aux_data_map,
req.cascade_up, req.cascade_down);
rv = impl_vol_map.ToDictionary(kv => kv.Key, kv => new VolCurveAction(
new VolCurveMarketFitAction(rep_action.market_fit_action.fit_action, kv.Value,
@@ -172,8 +119,7 @@ namespace mbts.spark {
return rv;
}
private static IDictionary<VolSurfaceExpiration, VolCurveMarketImpliedVolData> _fill_in_implied_vols(
ThreadedBlackboard bb, int vs_id,
private IDictionary<VolSurfaceExpiration, VolCurveMarketImpliedVolData> _fill_in_implied_vols(
VolSurfaceInput vs_inp,
IDictionary<VolSurfaceExpiration, VolCurveAction> action_map,
IDictionary<VolSurfaceExpiration, VolSurfaceExpirationAuxiliaryData> aux_data_map,
@@ -194,15 +140,15 @@ namespace mbts.spark {
applicable_exps = applicable_exps.Where(vs_exp => master_exps.Contains(vs_exp));
VolSurfaceEnums.MarketSide impliedvol_side =
SingleVolSurfaceMarketImpliedVolSource._get_market_impliedvol_side(bb, vs_id);
SingleVolSurfaceMarketImpliedVolSource._get_market_impliedvol_side(_bb, _vs_id);
foreach (VolSurfaceExpiration vs_exp in applicable_exps) {
VolSurfaceExpiration md_exp;
VolCurveMarketImpliedVolData exp_impl_data =
VolSurfaceCoreFunctions.compute_implied_vols(vs_inp, vs_exp, aux_data_map,
arg_vs_exp => SingleVolSurfaceMarketImpliedVolSource.get_option_bbo(bb, arg_vs_exp),
arg_vs_exp => SingleVolSurfaceMarketImpliedVolSource.get_option_bbo(_bb, arg_vs_exp),
impliedvol_side,
SingleVolSurfaceMarketImpliedVolSource._ignore_market_implied_vol_source_settings(
bb, vs_id),
_bb, _vs_id),
out md_exp);
rv[vs_exp] = exp_impl_data;
}
@@ -81,7 +81,7 @@ namespace mbts.analytics {
output.Add(symbol, symbol_data);
}
IReadOnlyDictionary<string, TData> ro_output = output;
bts.Log.Gen.diag($"SymbolAggregationPublisher._on_timer publishing " +
bts.Log.Gen.info($"SymbolAggregationPublisher._on_timer publishing " +
$"tag: {_out_tag} sz: {ro_output.Count}");
_bb.post(_out_tag, ro_output);
}
@@ -270,7 +270,6 @@ namespace mbts.spark {
new mbts.analytics.VolSurfaceNonVolInput(exp_param_map.exp_map.ToDictionary()));
} else if (_in_bb_req_vol.Equals(tag)) {
ClientArchivedVolRequest client_req = _bb.read_state(_in_bb_req_vol);
bts.Log.Ui.info($"VolSurfaceBusManager._on_bb_update ClientArchivedVolRequest: {client_req.ToString()}");
ArchivedTheoRetrieval ret = client_req.ret;
if (ret == null || ret.SecTup == null) {
bts.Log.Ui.warn($"VolSurfaceBusManager malformed ArchivedTheoRetrieval");
@@ -5,7 +5,6 @@ using bts.api;
using bts.collections;
using System.Linq;
using bts.api.orderman;
using bts.api.analytics;
using bts;
namespace mbts.spark {
@@ -24,8 +23,6 @@ namespace mbts.spark {
_order_service = order_service;
_bb.subscribe(SparkTags.AllInterpGreeks);
_bb.subscribe(SparkTags.SystemContractsTag);
_bb.subscribe(SparkTags.CurrentUser);
_bb.subscribe(SparkTags.VolSurfaceUsageTag);
_bb.data_callback += _on_data;
}
@@ -58,32 +55,10 @@ namespace mbts.spark {
return rv;
}
private IReadOnlyDictionary<string, OptionTheoInterpolationData>
_filter_for_publish(IReadOnlyDictionary<string, OptionTheoInterpolationData> all_theos) {
HashSet<string> syms = new HashSet<string>();
VolSurfaceUsageListImmutable usage = _bb.read_state(SparkTags.VolSurfaceUsageTag);
string current_user = _bb.read_state(SparkTags.CurrentUser).name;
foreach (var u in usage.UsageList) {
VolSurfaceInput vs_input =
_bb.read_state(SparkTags.VolSurfaceCommittedInputTag(u.VsId));
if (vs_input != null) {
if (vs_input.surface_settings.core_settings.vs_manager ==
current_user) {
syms.Add(u.SymbolName);
}
}
}
return
all_theos.Where(kv => syms.Contains(kv.Key)).ToDictionary(kv => kv.Key, kv => kv.Value);
}
private void _publish_data() {
SystemContractData sc_data = _bb.read_state(SparkTags.SystemContractsTag, null);
IReadOnlyDictionary<string, OptionTheoInterpolationData> all_theos =
_bb.read_state(SparkTags.AllInterpGreeks, null);
all_theos = _filter_for_publish(all_theos);
// find the symbol vs vs_id, get the committed vs, see if it is
// owned by the current user, and only then publish it
IReadOnlyDictionary<string, OptionDriverPriceMap> all_drivers =
_bb.read_state(SparkTags.AllOptionDriverBBOTag, null);
if (sc_data == null || all_theos == null || all_drivers == null)
@@ -26,13 +26,12 @@ namespace mbts.spark {
_refresh = new(_is_dirty.refresh);
_committed_value.Changed += on_committed_changed;
_candidate_value.Changed += on_candidate_changed;
if (column.type.is_editable()) {
_is_dirty.Changed += (o, n) => {
Log.Ui.info(
$"VolSurface '{expiration}.{column}' is_dirty changed to {n}. " +
$"commited: {committed_value}; candidate: {candidate_value}");
};
}
_is_dirty.Changed += (o, n) => {
Log.assert(o != n);
Log.Ui.info(
$"VolSurface '{expiration}.{column}' is_dirty changed to {n}. " +
$"commited: {committed_value}; candidate: {candidate_value}");
};
void on_committed_changed(object? oldval, object? newval) =>
_is_dirty.refresh();
@@ -29,7 +29,6 @@ namespace mbts.spark.VolSurface {
class VolSurfaceGridVM : DisposableViewModelBase {
readonly VolSurfaceVM _parent;
readonly UserTuple _user;
readonly ObservableCollection<VolSurfaceDisplayGridExpiration> _expirations = new();
readonly DeferrableAction _invalidate_rows;
readonly ColumnsModel _columns_model;
@@ -42,12 +41,10 @@ namespace mbts.spark.VolSurface {
VolSurfaceVM vm,
VolSurfaceDisplayModel model,
ISet<string> hidden_columns,
ISet<VolSurfaceExpiration> hidden_expirations,
UserTuple user) {
ISet<VolSurfaceExpiration> hidden_expirations) {
Log.notnull(hidden_columns);
Log.notnull(hidden_expirations);
_parent = vm;
_user = user;
this.model = model;
_columns_model = new(create_exp_column_view());
_hidden_columns = hidden_columns;
@@ -86,7 +83,7 @@ namespace mbts.spark.VolSurface {
_columns_model);
VolSurfaceRowVM row_factory(VolSurfaceDisplayGridExpiration exp) =>
new(this, exp, _user);
new(this, exp);
IDisposable connect_row(VolSurfaceRowVM row) {
row.request_calculate += request_recalc;
@@ -1,6 +1,5 @@
#nullable enable
namespace mbts.spark {
using bts;
using bts.collections;
using mbts.spark.VolSurface;
@@ -10,7 +9,6 @@ namespace mbts.spark {
using mbts.ui.utility;
using Spark.Core.Disposables;
using Spark.Core.Reactive;
using System;
using System.Collections.Generic;
@@ -24,10 +22,6 @@ namespace mbts.spark {
readonly VolSurfaceGridVM _parent;
readonly Property<VolSurfaceColumn?> _column;
readonly Property<DIYGridSuperHeaderVM?> _super_header;
readonly UserTuple _user;
readonly Property<bool> _is_open;
readonly DelegateProperty<string> _vs_manager;
readonly List<IDisposable> _resources = new();
ICommand? _revert_cmd;
ICommand? _shift_selection_cmd;
@@ -40,29 +34,21 @@ namespace mbts.spark {
ICommand? _copy_all_to_clipboard_cmd;
ICommand? _smart_copy_rolls_rates_cmd;
ICommand? _import_csv_cmd;
ObservantCommand? _acquire_ownership_cmd;
public VolSurfaceRowContextMenuVM(VolSurfaceGridVM parent, VolSurfaceRowVM row, UserTuple user) {
public VolSurfaceRowContextMenuVM(VolSurfaceGridVM parent, VolSurfaceRowVM row) {
_parent = parent;
_row = row;
_user = user;
_column = backing<VolSurfaceColumn?>(nameof(column));
_super_header = backing<DIYGridSuperHeaderVM?>(nameof(super_header));
_vs_manager = backing(
nameof(vs_manager),
() => _parent.model.get_active_settings()?.core_settings?.vs_manager ?? string.Empty);
_is_open = backing(nameof(is_open), false);
_resources.AddRange(
_dispose = Disposable.Create(
_column.invalidate_others_on_change(nameof(column_name)),
_super_header.invalidate_others_on_change(nameof(group_name)),
_is_open.Subscribe(_ => _vs_manager.refresh()),
_parent.visible_rows.ObserveSelf()
.BufferLatest(TimeSpan.FromSeconds(1))
.OnDispatcher()
.Subscribe(_ => sync_symbols()));
_dispose = Disposable.Create(() => _resources.DisposeAll(true));
void sync_symbols() {
var visible_exps = _parent.visible_rows.Map(r => r.expiration.symbol);
symbols.sync_with_models(
@@ -178,34 +164,6 @@ namespace mbts.spark {
_parent.model.csv_importing_enabled,
null);
public ICommand acquire_ownership_cmd {
get {
if (_acquire_ownership_cmd is null) {
_acquire_ownership_cmd = new(
() => {
var settings = _parent.model.get_active_settings();
if (settings is null) {
Log.Ui.error("Unable to acquire volsurface ownership: settings are null.");
return;
}
settings.core_settings.vs_manager = _user.name;
_parent.model.set_candidate_settings(settings);
});
_resources.Add(_vs_manager.observe_current(true)
.Subscribe(SelectorObserver.builder(_acquire_ownership_cmd).wrap<string>(
curr => curr != _user.name)));
}
return _acquire_ownership_cmd;
}
}
public bool is_open {
get => _is_open.Value;
set => _is_open.set(value);
}
public string vs_manager => _vs_manager.Value;
VolSurfaceDisplayGridColumn _assert_model() =>
column?.model ?? throw new InvalidOperationException();
@@ -1,7 +1,5 @@
#nullable enable
namespace mbts.spark.VolSurface {
using bts;
using mbts.ui;
using mbts.ui.controls;
using mbts.ui.shell;
@@ -18,16 +16,14 @@ namespace mbts.spark.VolSurface {
readonly VolSurfaceGridVM _parent;
readonly VolSurfaceDisplayGridExpiration _exp;
readonly Dictionary<string, CellData> _cells = new();
readonly UserTuple _user;
readonly DeferrableAction _request_calculate;
VolSurfaceRowContextMenuVM? _context_menu;
bool _is_selected;
public VolSurfaceRowVM(VolSurfaceGridVM parent, VolSurfaceDisplayGridExpiration exp, UserTuple user) {
public VolSurfaceRowVM(VolSurfaceGridVM parent, VolSurfaceDisplayGridExpiration exp) {
_parent = parent;
_exp = exp;
_user = user;
_request_calculate = new(() => request_calculate?.Invoke());
_dispose = Disposable.Create(() => {
_cells.Values.DisposeAll();
@@ -53,7 +49,7 @@ namespace mbts.spark.VolSurface {
}
public VolSurfaceRowContextMenuVM context_menu =>
_context_menu ??= new(_parent, this, _user);
_context_menu ??= new(_parent, this);
public VolSurfaceCellVM get_cell(VolSurfaceDisplayGridColumn column) =>
_cells.GetOrAdd(column.unique_col_name, _ => _create_cell(column)).vm;
@@ -1,89 +0,0 @@
#nullable enable
namespace mbts.spark {
using bts.api.domain;
using mbts.analytics;
using mbts.ui.shell;
using mbts.ui.utility;
using System;
using System.Collections.Generic;
using VolCurveFitRegion = analytics.VolSurfaceEnums.VolCurveFitRegion;
public class VolSurfaceAutoFitSettingsVM : DisposableViewModelBase {
readonly Property<VolCurveFitRegion> _fit_region;
readonly Property<uint?> _period_secs;
readonly Property<double?> _driver_points_moved;
readonly Property<double?> _atm_points_moved;
readonly Property<bool> _is_auto_fit_enabled;
public VolSurfaceAutoFitSettingsVM() {
_fit_region = backing(nameof(fit_region), VolCurveFitRegion.None);
_is_auto_fit_enabled = backing(
nameof(is_auto_fit_enabled),
_fit_region.observe_current(true),
r => r != VolCurveFitRegion.None);
_period_secs = backing<uint?>(nameof(period_secs), 10);
_driver_points_moved = backing<double?>(nameof(driver_points_moved));
_atm_points_moved = backing<double?>(nameof(atm_points_moved));
_fit_region.Changed += (o, n) => RaisePropertyChanged(nameof(is_auto_fit_enabled));
}
public IEnumerable<VolCurveFitRegion> fit_regions =>
EnumHelper.get_values<VolCurveFitRegion>();
public VolCurveFitRegion fit_region {
get => _fit_region.Value;
set => _fit_region.set(value);
}
public bool is_auto_fit_enabled => _is_auto_fit_enabled.Value;
public uint? period_secs {
get => _period_secs.Value;
set => _period_secs.set(value);
}
public double? driver_points_moved {
get => _driver_points_moved.Value;
set => _driver_points_moved.set(value);
}
public TickDisplaySettingsImmutable? driver_points_display =>
user.settings.TickFactors.pennies.to_api_tick_display_settingsi();
public double? atm_points_moved {
get => _atm_points_moved.Value;
set => _atm_points_moved.set(value);
}
public TickDisplaySettingsImmutable? atm_points_display =>
user.settings.TickFactors.pennies.to_api_tick_display_settingsi();
public void load_from(VolSurfaceAutoFitSettings value) {
fit_region = value?.auto_fit_region ?? VolCurveFitRegion.None;
period_secs = value?.time_based_settings?.period_seconds;
driver_points_moved = value?.driver_move_based_settings?.points_moved;
atm_points_moved = value?.atm_implied_vol_based_settings?.points_moved;
}
public void assign_to(VolSurfaceAutoFitSettings value) {
if (value is null) {
throw new ArgumentNullException(nameof(value));
}
value.auto_fit_region = fit_region;
value.time_based_settings = new() {
period_seconds = period_secs
};
value.driver_move_based_settings = new() {
points_moved = driver_points_moved
};
value.atm_implied_vol_based_settings = new() {
points_moved = atm_points_moved
};
}
}
}
@@ -96,7 +96,7 @@ namespace mbts.spark {
get => _core_settings.font_weight_override;
set {
using var _ = detect_property_change();
_core_settings.with(font_weight_override: value.HasValue ? new(value) : null);
_core_settings.with(font_weight_override: value.HasValue ? new NullableFontWeightProto(value) : null);
}
}
@@ -40,7 +40,6 @@ namespace mbts.spark {
vol_model_cubic_spline_vm.load_from(settings.spline_model_settings);
vol_model_dual_quadratic_vm.load_from(settings.dualquadratic_model_settings);
vol_path_parabolic_vm.load_from(settings.core_settings.volpath_settings.parabolic_vol_path_settings);
auto_fit_vm.load_from(settings.core_settings.market_fit_settings.vs_auto_fit_settings);
init_rotation_vms(call_rotations, _core_settings.call_rotation.strike_vol_movement_pairs);
init_rotation_vms(put_rotations, _core_settings.put_rotation.strike_vol_movement_pairs);
@@ -106,7 +105,6 @@ namespace mbts.spark {
}).ToList();
_core_settings.strangle.strike_vol_movement_pairs = strangles.SelectMany(r => new[] { Tuple.Create(r.target_put_strike, r.put_move), Tuple.Create(r.target_call_strike, r.call_move) }).ToList();
_core_settings.atm_shift.atm_strike_vol_movement = atm_shifts.Count == 1 ? atm_shifts[0].move : 0;
auto_fit_vm.assign_to(_core_settings.market_fit_settings.vs_auto_fit_settings);
commit(_settings);
}
@@ -235,7 +233,23 @@ namespace mbts.spark {
}
}
public VolSurfaceAutoFitSettingsVM auto_fit_vm { get; } = new();
public bool enable_auto_fit {
get => _core_settings.market_fit_settings.enable_auto_fit;
set {
using var _ = detect_property_change();
_core_settings.market_fit_settings.enable_auto_fit = value;
}
}
public VolSurfaceEnums.VolCurveFitRegion auto_fit_region {
get => _core_settings.market_fit_settings.auto_fit_region;
set { _core_settings.market_fit_settings.auto_fit_region = value; }
}
public double auto_fit_time_ms {
get => _core_settings.market_fit_settings.auto_fit_time_ms;
set { _core_settings.market_fit_settings.auto_fit_time_ms = value; }
}
public bool auto_decay_vol_time {
get => _core_settings.time_settings.time_mode == VolSurfaceEnums.VolSurfaceTimeMode.AutoDecay;
+2 -10
View File
@@ -1,6 +1,5 @@
#nullable enable
namespace mbts.spark {
using bts;
using bts.api;
using bts.collections;
@@ -28,7 +27,6 @@ namespace mbts.spark {
readonly IBus _bus;
readonly string _request_id = Guid.NewGuid().ToString();
readonly VolSurfaceDisplayModel _model;
readonly UserTuple _user;
readonly IRaiseCanExecuteChangedCommand _revert_cmd;
readonly IRaiseCanExecuteChangedCommand _commit_cmd;
readonly IDialogCommand _main_settings_cmd;
@@ -40,16 +38,10 @@ namespace mbts.spark {
bool _ignore_implied_vol_settings;
public VolSurfaceVM(
VolSurfaceDisplayModel model,
int id,
IBus bus,
VolSurfaceWindowSettings startup_data,
UserTuple user
) {
VolSurfaceDisplayModel model, int id, IBus bus, VolSurfaceWindowSettings startup_data) {
_model = model;
_vs_id = id;
_bus = bus;
_user = user;
macro_actions = new VolSurfaceMacroActionsVM(_model);
globals = new VolSurfaceGlobalParameterVM(_model);
@@ -57,7 +49,7 @@ namespace mbts.spark {
_grid_settings = startup_data.macro_grid_settings ?? new VolSurfaceMacroGridSettings();
var hidden_exps_set = startup_data.hidden_exps.empty_if_null().ToHashSet();
grid = new VolSurfaceGridVM(
this, _model, _grid_settings.hidden_cols(), hidden_exps_set, _user);
this, _model, _grid_settings.hidden_cols(), hidden_exps_set);
grid.on_selection_changed += _on_grid_selection_changed;
_model.publish_grid_settings(_grid_settings);
@@ -145,7 +145,7 @@ namespace mbts {
!(x == y);
public override string ToString() =>
$"{security_tuple} {SecurityFormatter.format_expiration(expiration)}";
$"{security_tuple} {expiration.ToShortDateString()}";
}
[ProtoContract]
@@ -4,11 +4,13 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mbts.analytics {
namespace mbts.analytics
{
/// These are the VolSurface settings that are common
/// to any Vol Model
[ProtoBuf.ProtoContract(Name = "VolSurfaceCoreSettings")]
public class VolSurfaceCoreSettings {
public class VolSurfaceCoreSettings
{
[ProtoBuf.ProtoMember(1)]
public string vol_surface_name;
[ProtoBuf.ProtoMember(2)]
@@ -85,7 +87,5 @@ namespace mbts.analytics {
get => _time_settings ??= new();
set => _time_settings = value;
}
[ProtoBuf.ProtoMember(240)]
public string vs_manager { get; set; } = string.Empty;
}
}
@@ -75,7 +75,6 @@ namespace mbts.analytics {
if (core_settings.market_fit_settings == null) {
core_settings.market_fit_settings = new VolSurfaceMarketFitSettings();
}
core_settings.market_fit_settings.vs_auto_fit_settings ??= new();
if (core_settings.time_settings == null) {
core_settings.time_settings = new VolSurfaceTimeSettings();
}
@@ -141,7 +141,6 @@ namespace mbts.analytics
public enum VolCurveFitRegion
{
None,
ATM,
All
}
@@ -231,4 +230,4 @@ namespace mbts.analytics
USE_CALENDAR_FOR_BUSINESS
}
}
}
}
@@ -4,9 +4,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mbts.analytics {
namespace mbts.analytics
{
[ProtoBuf.ProtoContract(Name = "VolSurfaceMarketFitSettings")]
public class VolSurfaceMarketFitSettings {
public class VolSurfaceMarketFitSettings
{
/// use one sided market or not
[ProtoBuf.ProtoMember(10)]
public bool ignore_one_sided_markets;
@@ -20,44 +22,19 @@ namespace mbts.analytics {
public double graph_update_period_ms = 2500;
/// If this is set to true a regression curve is drawn
/// and the vol model adheres to that
[ProtoBuf.ProtoMember(50)]
[ProtoBuf.ProtoMember(50)]
public bool use_weighted_regression_fit = false;
[ProtoBuf.ProtoMember(55)]
public uint regression_order = 4;
[ProtoBuf.ProtoMember(90)]
public VolSurfaceAutoFitSettings vs_auto_fit_settings { get; set; }
}
[ProtoBuf.ProtoContract(Name = "VolSurfaceAutoFitSettings")]
public class VolSurfaceAutoFitSettings {
// each of these settings can be enabled independently. if they are enabled
// then any of them being true will result in an autmatic fit
[ProtoBuf.ProtoContract(Name = "TimeBasedSettings")]
public class TimeBasedSettings {
[ProtoBuf.ProtoMember(10)]
public uint? period_seconds { get; set; }
}
[ProtoBuf.ProtoContract(Name = "DriverMoveBasedSettings")]
public class DriverMoveBasedSettings {
[ProtoBuf.ProtoMember(10)]
public double? points_moved { get; set; }
}
[ProtoBuf.ProtoContract(Name = "ATMImpliedVolBasedSettings")]
public class ATMImpliedVolBasedSettings {
[ProtoBuf.ProtoMember(20)]
public double? points_moved { get; set; }
// we can do price terms moved as well
}
[ProtoBuf.ProtoMember(5)]
public VolSurfaceEnums.VolCurveFitRegion auto_fit_region;
[ProtoBuf.ProtoMember(10)]
public TimeBasedSettings time_based_settings = null;
[ProtoBuf.ProtoMember(20)]
public DriverMoveBasedSettings driver_move_based_settings = null;
[ProtoBuf.ProtoMember(30)]
public ATMImpliedVolBasedSettings atm_implied_vol_based_settings = null;
/// The system auto fits and saves vols if this is
/// set to true
[ProtoBuf.ProtoMember(60)]
public bool enable_auto_fit = false;
/// If enable_auto_fit = true, this governs
/// how often the system auto-fits
[ProtoBuf.ProtoMember(70)]
public double auto_fit_time_ms = 30000;
[ProtoBuf.ProtoMember(80)]
public VolSurfaceEnums.VolCurveFitRegion auto_fit_region = VolSurfaceEnums.VolCurveFitRegion.ATM;
}
}
@@ -475,7 +475,6 @@ namespace mbts.analytics {
public static ResultMessage save_volsurface(
VolSurfaceInput vs_input, AnalyticsService service, string user = "") {
vs_input.saver_login = user;
vs_input.surface_settings.core_settings.vs_manager = user;
// convert to VolSurfaceEntry
var to_save = new VolSurfaceEntry();
var serialized_vs = ProtobufSerializationHelper.serialize(vs_input);
@@ -596,7 +595,7 @@ namespace mbts.analytics {
_greek_getter(g)(t, is_call);
public static IDictionary<double, IEnumerable<Theos>> hash_strikes(IEnumerable<Theos> theos) =>
theos.Map(t => t.strike);
theos.Map(t => t.strike);
static Func<Theos, bool, double> _greek_getter(VolSurfaceGreeks g) =>
g switch {
@@ -88,8 +88,8 @@ namespace mbts.analytics {
public void set_driver_price(
IDictionary<VolSurfaceExpiration, double> driver_price_map) {
// Log.Gen.info($"VolSurfaceInterpGreeksProducer.set_driver_price " +
// $"vs_id: {_vs_id} exp_count: {driver_price_map.Count}");
Log.Gen.info($"VolSurfaceInterpGreeksProducer.set_driver_price " +
$"vs_id: {_vs_id} exp_count: {driver_price_map.Count}");
_driver_price_map = new Dictionary<VolSurfaceExpiration, double>(driver_price_map);
_compute_and_fire(InputType.DriverPrice);
}
+1 -4
View File
@@ -135,10 +135,7 @@ namespace bts {
var meta = _security_metadata.get(smd.security);
if (meta.HasValue) {
exch_secs[smd.id] = new(
smd.security,
smd.md,
meta.Value.HasPriceDisplay ? meta.Value.PriceDisplay : null,
meta.Value.HasQuantityDisplay ? meta.Value.QuantityDisplay : null);
smd.security, smd.md, meta.Value.PriceDisplay, meta.Value.QuantityDisplay);
}
}
_bus.post(SparkTags.ServerSecuritiesTag, exch_secs);
+1 -1
View File
@@ -62,7 +62,7 @@ namespace bts {
}
private void _on_server_sec_map(IReadOnlyDictionary<uint, SecurityMD> sec_map) {
//_log_options(sec_map);
_log_options(sec_map);
bts.Log.Gen.info(String.Format("MergedMDDaemon._on_server_sec_map sz: {0}", sec_map.Count()));
_server_sec_map = new Dictionary<uint, SecurityMD>(sec_map);
_merge_and_post();
@@ -56,7 +56,7 @@ namespace mbts.spark {
r => new ReportImmutable?(r),
r => r?.Id ?? throw new ArgumentNullException(nameof(r)));
_window_factories = new() {
new VolSurfaceWindowFactory(this, bus, user.Value),
new VolSurfaceWindowFactory(this, bus),
new AnalyticsExpirationParametersWindowFactory(this, bus),
new SlideReportWindowFactory(this, bus, reports_demuxer.subscribe),
new ComboReportWindowFactory(this, bus, reports_demuxer.subscribe),
@@ -793,106 +793,70 @@
Grid.Row="5"
Grid.Column="1"
Grid.ColumnSpan="4"
DataContext="{Binding auto_fit_vm}"
Header="Auto Fit"
Margin="0,5,0,0"
Padding="5">
Padding="5"
IsEnabled="False">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox
Grid.ColumnSpan="2" Content="Enabled" IsChecked="{Binding enable_auto_fit}" />
<TextBlock Grid.Row="1" Text="Region" Margin="16,5,0,0">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger
Binding="{Binding enable_auto_fit}"
Value="False">
<Setter
Property="Foreground"
Value="Gray" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<TextBlock Grid.Row="0" Text="Fit Region" />
<ComboBox
Grid.Row="0"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="8,0,0,0"
VerticalAlignment="Center"
ItemsSource="{Binding fit_regions}"
SelectedItem="{Binding fit_region}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={x:Static shell:VolSurfaceSettingsEditor.AutoFitRegionDisplayTextConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock
Grid.Row="1"
Margin="0,5,0,0"
Text="Every" />
<c:TickUpDownNullableUInt32
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Minimum="30"
Margin="8,0,0,0"
Width="60"
Value="{Binding period_secs}"
IsEnabled="{Binding is_auto_fit_enabled}" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
HorizontalAlignment="Left"
Margin="3,5,0,0"
Text="secs" />
Margin="12,0,0,0"
HorizontalAlignment="Stretch"
ItemsSource="{Binding auto_fit_region_choices}"
SelectedValue="{Binding auto_fit_region}"
IsEnabled="{Binding enable_auto_fit}" />
<TextBlock
Grid.Row="2"
Margin="0,5,0,0"
Text="When Driver moves" />
<c:TickUpDownNullableDouble
<TextBlock Grid.Row="2" Text="Fit Time" Margin="16,5,0,0">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding enable_auto_fit}" Value="False">
<Setter Property="Foreground" Value="Gray" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<c:TextBoxDouble
Grid.Row="2"
Grid.Column="1"
ToolTipService.ShowOnDisabled="True"
c:TextBoxEx.Suffix="ms"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="8,0,0,0"
Width="60"
Value="{Binding driver_points_moved}"
Increment="0.01"
TickDisplaySettings="{Binding driver_points_display}"
IsEnabled="False"
ToolTip="Not yet supported (coming soon)" />
<TextBlock
Grid.Row="2"
Grid.Column="2"
HorizontalAlignment="Left"
Margin="3,5,0,0"
Text="%" />
<TextBlock
Grid.Row="3"
Margin="0,5,0,0"
Text="When ATM moves" />
<c:TickUpDownNullableDouble
Grid.Row="3"
Grid.Column="1"
ToolTipService.ShowOnDisabled="True"
HorizontalAlignment="Left"
Margin="8,0,0,0"
Width="60"
Value="{Binding atm_points_moved}"
Increment="0.01"
TickDisplaySettings="{Binding atm_points_display}"
IsEnabled="False"
ToolTip="Not yet supported (coming soon)" />
<TextBlock
Grid.Row="3"
Grid.Column="2"
HorizontalAlignment="Left"
Margin="3,5,0,0"
Text="%" />
Margin="12,5,0,0"
IsEnabled="{Binding enable_auto_fit}"
Value="{Binding auto_fit_time_ms}"
Template="{StaticResource SuffixTemplate}" />
</Grid>
</GroupBox>
</Grid>
@@ -1,20 +1,9 @@
#nullable enable
namespace mbts.ui.shell {
using mbts.analytics;
using mbts.ui.converters;
using System.Windows;
using System.Windows.Data;
partial class VolSurfaceSettingsEditor : Window {
public VolSurfaceSettingsEditor() =>
InitializeComponent();
public static IValueConverter AutoFitRegionDisplayTextConverter =>
ValueConverter.create<VolSurfaceEnums.VolCurveFitRegion, string>(fr =>
fr switch {
VolSurfaceEnums.VolCurveFitRegion.None => "Disabled",
_ => fr.ToString()
});
}
}
@@ -262,7 +262,7 @@
IsDragAdornerEnabled="False"
ContextMenuOpening="_on_context_menu_opening">
<c:DIYGrid.ContextMenu>
<ContextMenu IsOpen="{Binding is_open}">
<ContextMenu>
<MenuItem
Header="Populate Empty Expirations"
Command="{Binding populate_empty_exps_cmd}" />
@@ -413,11 +413,6 @@
</MenuItem.ItemContainerStyle>
</MenuItem>
<MenuItem Header="Import CSV..." Command="{Binding import_csv_cmd}" />
<MenuItem Command="{Binding acquire_ownership_cmd}">
<MenuItem.Header>
<TextBlock Text="{Binding vs_manager, StringFormat='Acquire ownership from \'{0}\''}" />
</MenuItem.Header>
</MenuItem>
</ContextMenu>
</c:DIYGrid.ContextMenu>
<c:DIYGrid.RowStyle>
@@ -122,7 +122,7 @@
}
var mouse_pos = Mouse.GetPosition(this);
if (!this.ChildAtPoint<VolSurfaceRowView>(mouse_pos, out var row)) {
cm.SetCurrentValue(ContextMenu.IsOpenProperty, false);
cm.IsOpen = false;
return;
}
var cgs = g.GetColumnGeometry().ToList();
@@ -1,5 +1,4 @@
namespace mbts.spark {
using bts;
using bts.api;
using bts.spark;
@@ -15,20 +14,14 @@
public const string WINDOW_TYPE = "VolSurface";
readonly VolSurfaceWindowSettings _startup_data;
readonly UserTuple _user;
VolSurfaceVM _vm;
VolSurfaceView _view;
public VolSurfaceWindow(
VolSurfaceWindowFactory factory,
IBus bus,
string vs_name,
VolSurfaceWindowSettings startup_data,
UserTuple user
) : base(vs_name, bus, factory, Icons.vol_surface) {
VolSurfaceWindowFactory factory, IBus bus, string vs_name, VolSurfaceWindowSettings startup_data) :
base(vs_name, bus, factory, Icons.vol_surface) {
_startup_data = startup_data ?? throw new ArgumentNullException(nameof(startup_data));
_user = user;
this.vs_name = vs_name;
_dispose = Disposable.Create(() => Disposable.dispose(ref _vm));
}
@@ -44,7 +37,7 @@
public override UIElement Content => _view;
public void thread_init() {
_vm = new VolSurfaceVM(new (vs_id, _bus, true), vs_id, _bus, _startup_data, _user);
_vm = new VolSurfaceVM(new VolSurfaceDisplayModel(vs_id, _bus, true), vs_id, _bus, _startup_data);
_view = new VolSurfaceView {
DataContext = _vm
};
@@ -1,5 +1,4 @@
namespace mbts.spark {
using bts;
using bts.api;
using bts.shell;
@@ -11,12 +10,10 @@ namespace mbts.spark {
class VolSurfaceWindowFactory : ShellWindowFactory<VolSurfaceWindowSettings> {
readonly IBus _bus;
readonly UserTuple _user;
public VolSurfaceWindowFactory(IShellModule module, IBus bus, UserTuple user)
public VolSurfaceWindowFactory(IShellModule module, IBus bus)
: base(module, "VolSurface") {
_bus = bus;
_user = user;
_dispose = bus.subscribe(SparkTags.ShowVolSurface).OnDispatcher().Subscribe(
async state => _bus.post(SparkTags.ShowWindow, await _create(state)));
}
@@ -25,7 +22,7 @@ namespace mbts.spark {
_create(state);
async Task<IShellWindow> _create(VolSurfaceWindowSettings state) =>
new VolSurfaceWindow(this, _bus, await _lookup_vs_name(state.id), state, _user);
new VolSurfaceWindow(this, _bus, await _lookup_vs_name(state.id), state);
async Task<string> _lookup_vs_name(int vs_id) {
var (vol_surfaces, success) = await _bus.subscribe(SparkTags.VolSurfaceListTag).FirstAsyncTask(TimeSpan.FromSeconds(2));
@@ -31,7 +31,7 @@
_window_factories = new() {
new MarketViewWindowFactory(
this, bus, settings_hub, orders_model, position_model, sec_meta_store),
new OptionsViewWindowFactory(this, orders_model, bus),
new OptionsViewWindowFactory(this, bus),
new TimeAndSalesWindowFactory(this, bus, consumer, settings_hub, orders_model.security_auxiliary_model),
};
@@ -79,12 +79,10 @@ namespace bts.shell.market_view {
var ask_col_index = columns.FindIndex(x => x.id == MarketViewWindowFactory.col_id(Columns.Ask));
if (bid_col_index > -1 && ask_col_index > -1) {
if (!columns[bid_col_index].background_color_override.HasValue) {
columns[bid_col_index] = columns[bid_col_index].with(
background_color_override: new(BTSColors.MarketData.bid));
columns[bid_col_index] = columns[bid_col_index].with(background_color_override: new NullableColorProto(BTSColors.MarketData.bid.value));
}
if (!columns[ask_col_index].background_color_override.HasValue) {
columns[ask_col_index] = columns[ask_col_index].with(
background_color_override: new(BTSColors.MarketData.ask));
columns[ask_col_index] = columns[ask_col_index].with(background_color_override: new NullableColorProto(BTSColors.MarketData.ask.value));
}
}
// and enable background color upgrade
@@ -70,13 +70,11 @@ namespace bts.shell {
bool applied = false;
if (bid_col_index > -1 && ask_col_index > -1) {
if (!columns[bid_col_index].background_color_override.HasValue) {
columns[bid_col_index] = columns[bid_col_index].with(
background_color_override: new(BTSColors.MarketData.bid));
columns[bid_col_index] = columns[bid_col_index].with(background_color_override: new NullableColorProto(BTSColors.MarketData.bid.value));
applied = true;
}
if (!columns[ask_col_index].background_color_override.HasValue) {
columns[ask_col_index] = columns[ask_col_index].with(
background_color_override: new(BTSColors.MarketData.ask));
columns[ask_col_index] = columns[ask_col_index].with(background_color_override: new NullableColorProto(BTSColors.MarketData.ask.value));
applied = true;
}
}
@@ -10,14 +10,12 @@ namespace mbts.spark {
class OptionsViewWindowFactory : ShellWindowFactory<OptionsViewSettings> {
readonly IBus _bus;
readonly NMSheetAllTaskingDataSource _tasking_datasource;
public OptionsViewWindowFactory(IShellModule module, OrdersModel orders_model, IBus bus)
public OptionsViewWindowFactory(IShellModule module, IBus bus)
: base(module, OptionsViewWindow.WINDOW_TYPE) {
_bus = bus;
_dispose = bus.subscribe(SparkTags.show_default_options_view).OnDispatcher().Subscribe(
sc => _bus.post(SparkTags.ShowWindow, _create(OptionsViewSettings.Default(sc))));
_tasking_datasource = new NMSheetAllTaskingDataSource(orders_model, bus);
}
public override Task<IShellWindow> load(OptionsViewSettings state) =>
@@ -176,11 +176,10 @@
</usp:DataGridParameterCellTemplateConverter.QuantityMeasureTemplate>
</usp:DataGridParameterCellTemplateConverter>
<Style x:Key="ExpanderToggleButton" TargetType="ToggleButton">
<Setter Property="Foreground" Value="{u:BTSColor ExecutionStrategy.expander_foreground}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid Background="{u:BTSColor ExecutionStrategy.expander_background}">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="12" />
<ColumnDefinition/>
@@ -191,7 +190,7 @@
HorizontalAlignment="Center"
Margin="0,5,0,0"
SnapsToDevicePixels="False"
Stroke="{u:BTSColor ExecutionStrategy.arrow_background}"
Stroke="#77333333"
StrokeThickness="2"
VerticalAlignment="Top"
/>
@@ -200,7 +199,6 @@
ContentSource="{TemplateBinding Content}"
Margin="3,0,0,0"
/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
@@ -213,7 +211,7 @@
<Setter Property="Stroke" TargetName="arrow" Value="Black"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Stroke" TargetName="arrow" Value="{u:BTSColor ExecutionStrategy.arrow_background_selected}"/>
<Setter Property="Stroke" TargetName="arrow" Value="#FF707070"/>
<Setter Property="Foreground" Value="Gray"/>
</Trigger>
</ControlTemplate.Triggers>
@@ -280,8 +278,7 @@
<ColumnDefinition/>
</SelectiveScrollingGrid.ColumnDefinitions>
<DataGridRowHeader
Foreground="{u:BTSColor ExecutionStrategy.expander_foreground}"
Background="{u:BTSColor ExecutionStrategy.data_grid_row_header_background}"
Background="Transparent"
Padding="{Binding section_count, Converter={StaticResource RowHeaderGroupIndentConverter}}"
FontWeight="{Binding font_weight, FallbackValue={u:FontWeight Normal}}"
SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
@@ -320,17 +317,9 @@
<Style x:Key="DataGridRowStyle" TargetType="DataGridRow">
<Setter Property="BorderThickness" Value="1,0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="{u:BTSColor ExecutionStrategy.alternate_column_background}"/>
<Setter Property="Template" Value="{StaticResource DataGridRowTemplate}"/>
<Setter Property="usp:ExecutionStrategyEditor.RowHasErrors" Value="{Binding has_errors}"/>
<Style.Triggers>
<Trigger Property="ListBox.AlternationIndex" Value="1">
<Setter Property="Background" Value="{u:BTSColor ExecutionStrategy.data_grid_background}"/>
</Trigger>
<!-- <Trigger Property="ListBox.AlternationIndex" Value="2">
<Setter Property="Background" Value="LightBlue"/>
<Setter Property="Foreground" Value="Navy"/>
</Trigger> -->
<DataTrigger Binding="{Binding read_only}" Value="True">
<Setter Property="TextElement.Foreground" Value="{u:BTSColor UI.input_disabled_text_dark}"/>
<Setter Property="ToolTip">
@@ -57,7 +57,7 @@ namespace mbts.spark {
main_vm.rows.AddRange(parsed_synths.Select(ps => {
var sec = ps.result;
var r = new SyntheticImportRowVM(orders_model.admin_model.user.id, used_names.Contains) {
tick_factors = TickUtils.get_regional_ticks(sec.immutable()).low_tick,
tick_factors = TickUtils.get_regional_ticks(sec.ContractSpec).low_tick,
name = sec.Synthetic.Name,
parsed_synth = ps
};
@@ -56,7 +56,7 @@ namespace mbts.spark {
public SyntheticEditorVM(SpreaderModel model, SecurityImmutable synthetic, ExecutionStrategyImmutable strategy, IObservable<bool> security_has_working_orders)
: this(synthetic, strategy, false) {
ExceptionAssert.InvalidOperation.That(synthetic.Id != 0, "This constructor may only be used for already-existing synthetic securities (id must be non-zero).");
_tick_factors = TickUtils.get_regional_ticks(synthetic).low_tick;
_tick_factors = TickUtils.get_regional_ticks(synthetic.ContractSpec).low_tick;
if (TickUtils.is_integer_tick(synthetic.ContractSpec)) {
_use_fractional_ticks = false;
_integer_tick_size = DoubleHelper.to_optional_int32(synthetic.ContractSpec.LowTick) ?? 0;
@@ -112,7 +112,7 @@ namespace mbts.spark {
_set_ticks_automatically = false;
_set_quantities_automatically = false;
_set_price_mults_automatically = false;
_tick_factors = TickUtils.get_regional_ticks(_synthetic.immutable()).low_tick;
_tick_factors = TickUtils.get_regional_ticks(_synthetic.ContractSpec).low_tick;
} else {
_deduce_name();
_deduce_ticks();
@@ -411,7 +411,7 @@ namespace mbts.spark {
}
void _deduce_ticks() {
_tick_factors = TickUtils.deduce_ticks(leg_tuples.Select(l => l.leg.Security.immutable()));
_tick_factors = TickUtils.deduce_ticks(leg_tuples.Select(l => l.leg.Security.ContractSpec));
RaisePropertyChanged(nameof(tick_factors));
}
@@ -371,7 +371,6 @@
<usp:AlgoEditorView
DataContext="{Binding selected_definition}"
Background="Transparent"
Foreground="{u:BTSColor UI.default_text}"
BorderBrush="{Binding algo_root, Converter={StaticResource OrderTypeBrushConverter}}"
Padding="12,8" />
</ScrollViewer>
@@ -79,7 +79,7 @@ namespace Spark.Trading {
meta.Value.Value.PriceDisplay : Security.Defaults.price_display_settingsi;
if (security.HasValue) {
rv = rv.with(
tick_factors: security.Value.tick_factors().to_api_tick_factors());
tick_factors: security.spec_or_default().tick_factors().to_api_tick_factors());
}
return rv;
}
@@ -410,13 +410,13 @@ namespace mbts.spark {
day_change = new DaySettings {
// (neutral)
font = _default_font,
background_color = Colors.Transparent.to_uint(),
background_color = Colors.Transparent.rgb_color(),
// negative
negative_font_color = Colors.White.to_uint(),
negative_background_color = Colors.Red.to_uint(),
negative_font_color = Colors.White.rgb_color(),
negative_background_color = Colors.Red.rgb_color(),
// positive
positive_font_color = Colors.White.to_uint(),
positive_background_color = Colors.Green.to_uint()
positive_font_color = Colors.White.rgb_color(),
positive_background_color = Colors.Green.rgb_color()
},
session_low = _default_item,
session_high = _default_item,
@@ -431,8 +431,8 @@ namespace mbts.spark {
public static LadderPanelPricePointSettings tt_default {
get {
var rv = historic_default;
rv.day_change.background_color = Color.FromRgb(113, 201, 69).to_uint();
rv.day_change.font.font_color = Colors.Black.to_uint();
rv.day_change.background_color = Color.FromRgb(113, 201, 69).rgb_color();
rv.day_change.font.font_color = Colors.Black.rgb_color();
return rv;
}
}
@@ -484,7 +484,7 @@ namespace mbts.spark {
static ItemSettings _default_item =>
new ItemSettings {
font = _default_font,
background_color = Colors.Transparent.to_uint()
background_color = Colors.Transparent.rgb_color()
};
[ProtoContract]
@@ -97,7 +97,7 @@ namespace mbts.spark {
security_key = use_self_security ? null : selected_security_key,
price_type = _selected_price_type,
display = new LadderMarketBreakLine {
color = color.to_uint(),
color = color.rgb_color(),
show = show,
refresh_mode = refresh_mode
}
@@ -27,7 +27,7 @@ namespace mbts.spark {
class LadderOrderVM : DisposableViewModelBase {
static readonly Color _colorbg = Colors.White;
static readonly Color _darkbg = Color.FromRgb(0xbf, 0xbf, 0xbf);
static readonly Brush _color_bg_brush = _colorbg.to_uint().rgb_brush();
static readonly Brush _color_bg_brush = _colorbg.rgb_color().rgb_brush();
readonly LadderVM _owner;
readonly double _real_price;
@@ -228,7 +228,7 @@ namespace mbts.spark {
if (_orders.TryGetValue(order.Key, out var opm)) {
algo_studio_abbreviation = (opm.meta?.abbreviation).is_null_or_empty() ?
_abbreviate_algo(opm.algo) : opm.meta?.abbreviation ?? string.Empty;
border = opm.meta?.badge_color?.to_uint().rgb_brush() ?? border;
border = opm.meta?.badge_color?.rgb_color().rgb_brush() ?? border;
}
algo_type = order.order_type().is_bts_algo_type() ?
order.order_type() : CustomOrderDefinition.CustomOneofCase.None;
@@ -241,7 +241,7 @@ namespace mbts.spark {
}
public OrderBookVM? create_orderbook_vm() {
var ticks = _owner.spec.count_ticks(real_price);
var ticks = _owner.spec.full_ticks_from_zero(real_price);
if (!ticks.HasValue) {
return null;
}
@@ -42,13 +42,13 @@ namespace mbts.spark {
public LadderPanelPricePointSettings.ItemSettings create() =>
new LadderPanelPricePointSettings.ItemSettings {
font = new FontParamsProto {
font_color = font_color.to_uint(),
font_color = font_color.rgb_color(),
font_size = font_size,
typeface = new(
font_family.name() ?? TextUtils.StandardFontFamilyName,
font_weight.ToOpenTypeWeight())
},
background_color = background_color.to_uint(),
background_color = background_color.rgb_color(),
show_label = show_label
};
@@ -111,11 +111,11 @@ namespace mbts.spark {
show_label = base_settings.show_label,
background_color = base_settings.background_color,
// negative
negative_font_color = negative_font_color.to_uint(),
negative_background_color = negative_background_color.to_uint(),
negative_font_color = negative_font_color.rgb_color(),
negative_background_color = negative_background_color.rgb_color(),
// positive
positive_font_color = positive_font_color.to_uint(),
positive_background_color = positive_background_color.to_uint()
positive_font_color = positive_font_color.rgb_color(),
positive_background_color = positive_background_color.rgb_color()
};
}
}
@@ -191,7 +191,7 @@ namespace mbts.spark {
void increment_ticks_per_row() {
var tpr = ticks_per_row;
for (uint i = 1; i < 100; i++) {
var new_tpr = TickUtils.fit_ticks_per_row_to_dollars(security, ticks_per_row + i);
var new_tpr = TickUtils.fit_ticks_per_row_to_dollars(security.ContractSpec, ticks_per_row + i);
if (new_tpr != tpr) {
ticks_per_row = new_tpr;
break;
@@ -201,7 +201,7 @@ namespace mbts.spark {
void decrement_ticks_per_row() {
var tpr = ticks_per_row;
for (uint i = 1; i < tpr; i++) {
var new_tpr = TickUtils.fit_ticks_per_row_to_dollars(security, tpr - i);
var new_tpr = TickUtils.fit_ticks_per_row_to_dollars(security.ContractSpec, tpr - i);
if (new_tpr != tpr) {
ticks_per_row = new_tpr;
break;
@@ -239,8 +239,7 @@ namespace mbts.spark {
// since settings profiles may be shared among ladders
// of different securities/tick sizes, the ticks per row setting
// may need to be rounded to a number that is a factor of $1.00
public uint? rounded_ticks_per_row =>
TickUtils.fit_ticks_per_row_to_dollars(_security, ticks_per_row);
public uint? rounded_ticks_per_row => TickUtils.fit_ticks_per_row_to_dollars(_security.ContractSpec, ticks_per_row);
public MarketSizeDisplayVM size_display { get; } = new MarketSizeDisplayVM();
public SimpleGridSettingsVM mini_ob { get; } = new SimpleGridSettingsVM(OrderBookGridSettingsManager.hard_column_flags);
@@ -701,8 +700,8 @@ namespace mbts.spark {
font_weight = font_weight.ToOpenTypeWeight(),
width = width,
show = show,
foreground = foreground.to_uint(),
background = background.to_uint()
foreground = foreground.rgb_color(),
background = background.rgb_color()
};
}
}
@@ -99,7 +99,7 @@ namespace mbts.spark {
IReadOnlyDictionary<uint, OrderSecurity> _cache = DictionaryHelper.empty<uint, OrderSecurity>();
ImmutableDictionary<AlgoKey, LadderFavoriteAlgoMetadata> _favorite_algo_metadata_map =
ImmutableDictionary<AlgoKey, LadderFavoriteAlgoMetadata>.Empty;
RegionalTickFactors? _spec;
ContractSpecificationImmutable? _spec;
LadderVM(
IBus bus,
@@ -243,9 +243,10 @@ namespace mbts.spark {
var orders_source = settings.Select(s => s.ticks_per_row).DistinctUntilChanged()
.SelectSeries(tpr => {
var spec = TickUtils.multiply_tick_size(security.regional_ticks(), tpr);
var spec = TickUtils.multiply_tick_size(security.ContractSpec, tpr);
var price_comp = Comparer<double>.Create((a, b) =>
Comparer<long?>.Default.Compare(spec.count_ticks(a), spec.count_ticks(b)));
Comparer<int?>.Default.Compare(
spec.full_ticks_from_zero(a), spec.full_ticks_from_zero(b)));
return _order_price_source(model.orders, price_comp, p => TickUtils.normalize_price(spec, p));
});
_day_change.Changed += (o, n) => RaisePropertyChanged(
@@ -393,10 +394,9 @@ namespace mbts.spark {
}
public SecurityImmutable security => _model.security;
public RegionalTickFactors spec => _spec ?? (
public ContractSpecificationImmutable spec => _spec ?? (
_spec = TickUtils.multiply_tick_size(
security.regional_ticks(), current_settings?.ticks_per_row ?? 1))
?? RegionalTickFactors.Default;
security.ContractSpec, current_settings?.ticks_per_row ?? 1)).Value;
public double display_quantity_divisor { get; }
public LadderSettings current_settings { get; private set; }
@@ -826,7 +826,7 @@ namespace mbts.spark {
if (!price.is_real()) {
msg = "not a real number";
} else if (settlement.is_real()) {
var ticks_from_settle = security.tickdiff(price, settlement);
var ticks_from_settle = security.ContractSpec.tickdiff(price, settlement);
if (ticks_from_settle.HasValue) {
var max_cross = (current_settings?.ladder_order_limits?.max_settlement_cross_ticks)
.as_nullable();
@@ -858,7 +858,7 @@ namespace mbts.spark {
} else {
ulong _ = 0;
_model.md.get_bbo(ref _, out var bid, out var ask);
var mid = TickUtils.mid_tick(security.regional_ticks(), bid.price, ask.price);
var mid = TickUtils.mid_tick(security.ContractSpec, bid.price, ask.price);
_day_change.set(mid - md.settlement_price);
}
_volume.set(volume);
@@ -32,8 +32,6 @@ using System.Windows.Media.Animation;
using System.Windows.Threading;
namespace mbts.spark {
using RegionalTickFactors = user.settings.RegionalTickFactors;
partial class LadderGridHost : Control {
static readonly int _initial_row_count;
static readonly bool _show_scrollbar;
@@ -85,6 +83,7 @@ namespace mbts.spark {
bool _price_dirty = false, _piq_dirty = false;
LadderPriceList _price_list = new() {
length = _initial_row_count,
spec = Security.Defaults.ContractSpecificationImmutable
};
LadderPriceList _pending_price_list = null;
IComparer<double> _price_comparer;
@@ -385,16 +384,16 @@ namespace mbts.spark {
Column[] _columns { get; set; } = Array.Empty<Column>();
IEnumerable<Column> _visible_columns => _columns.Where(c => c.settings.show);
RegionalTickFactors _spec_backing;
RegionalTickFactors _spec {
ContractSpecificationImmutable? _spec_backing;
ContractSpecificationImmutable _spec {
get {
if (_spec_backing is not null) {
return _spec_backing;
if (_spec_backing.HasValue) {
return _spec_backing.Value;
} else if (_vm != null) {
_spec_backing = TickUtils.multiply_tick_size(security.regional_ticks(), _settings?.ticks_per_row ?? 1);
return _spec_backing;
_spec_backing = TickUtils.multiply_tick_size(security.ContractSpec, _settings?.ticks_per_row ?? 1);
return _spec_backing.Value;
}
return RegionalTickFactors.Default;
return Security.Defaults.ContractSpecificationImmutable;
}
}
@@ -448,15 +447,6 @@ namespace mbts.spark {
return _price_list.high_tick + tick_diff;
}
public bool scroll_to_tick(long tick) {
if (tick > int.MaxValue) {
Log.Ui.error(
$"Unable to scroll to tick {tick} because it exceeds int.MaxValue");
return false;
}
return scroll_to_tick((int)tick);
}
public bool scroll_to_tick(int tick) {
if (_vm is null || _settings is null || _scroll_viewer is null) {
return false;
@@ -470,23 +460,21 @@ namespace mbts.spark {
// The scrollbar's vertical offset won't change. Find the 'top tick' that will put the
// target `tick` in the center of the viewport.
checked {
var top_tick = (int)_get_target_top_tick(tick);
if (_settings.animate_recenter) {
var anim = new Int32Animation {
From = (int)_price_list.high_tick,
To = top_tick,
Duration = TimeSpan.FromSeconds(0.15)
};
var sb = new Storyboard();
sb.Children.Add(anim);
Storyboard.SetTarget(anim, this);
Storyboard.SetTargetProperty(anim, new PropertyPath(TopTickProperty));
sb.Begin();
} else {
_set_scrollbar_range(high_tick: top_tick);
_refresh_prices();
}
var top_tick = (int)_get_target_top_tick(tick);
if (_settings.animate_recenter) {
var anim = new Int32Animation {
From = _price_list.high_tick,
To = top_tick,
Duration = TimeSpan.FromSeconds(0.15)
};
var sb = new Storyboard();
sb.Children.Add(anim);
Storyboard.SetTarget(anim, this);
Storyboard.SetTargetProperty(anim, new PropertyPath(TopTickProperty));
sb.Begin();
} else {
_set_scrollbar_range(high_tick: top_tick);
_refresh_prices();
}
return true;
}
@@ -756,12 +744,12 @@ namespace mbts.spark {
internal double price_for_point(Point point) =>
_price_for_row(_row_for_point(point));
static uint? _size_from_row(int row, IList<double> price_list, NativePriceSize[] depth, RegionalTickFactors spec) {
static uint? _size_from_row(int row, IList<double> price_list, NativePriceSize[] depth, ContractSpecificationImmutable spec) {
if (price_list == null || depth == null) return null;
else return row <= price_list.Count ? _size_from_price(price_list[row], depth, spec) : null;
}
static uint? _size_from_price(double price, NativePriceSize[] depth, RegionalTickFactors spec) {
static uint? _size_from_price(double price, NativePriceSize[] depth, ContractSpecificationImmutable spec) {
if (!double.IsNaN(price) && depth.TryGetFirst(nps => spec.tick_equals(price, nps.price), out NativePriceSize result))
return result.size;
return null;
@@ -1111,16 +1099,10 @@ namespace mbts.spark {
Log.assert(_price_dirty);
_price_list = new LadderPriceList {
length = _initial_row_count,
security = security
spec = security.ContractSpec
};
var mid_tick = security.tickdiff(_mkt_break_lines.origin, 0) ?? 0;
if (mid_tick > int.MaxValue) {
Log.Ui.error(
$"Unable to set scrollbar range about mid_tick {mid_tick}: " +
$"tick count exceeds int.MaxValue");
} else {
_set_scrollbar_range(high_tick: (int)mid_tick + (_price_list.Count << 1));
}
var mid_tick = security.ContractSpec.tickdiff(_mkt_break_lines.origin, 0) ?? 0;
_set_scrollbar_range(high_tick: mid_tick + (_price_list.Count << 1));
_price_dirty = true;
}
if (_price_dirty) {
@@ -1199,12 +1181,12 @@ namespace mbts.spark {
_price_list, _vm.md.settlement_price,
_settings.net_change == LadderSettings.NetChangeTerms.Ticks,
_settings.row_height, _settings.price_column,
_spec);
security.ContractSpec);
} else {
LadderRender.render_prices(
_price_vis_tup.visual, _price_vis_tup.glyph_context,
_price_list, _settings.row_height,
_settings.price_column, _spec,
_settings.price_column, security.ContractSpec,
_settings.price_display_format);
}
}
@@ -1359,7 +1341,7 @@ namespace mbts.spark {
return;
if (_price_list is null) {
_price_list = new LadderPriceList {
security = security
spec = security.ContractSpec
};
}
_price_list.reset(null, null, _initial_row_count);
@@ -1443,7 +1425,7 @@ namespace mbts.spark {
_pending_scroll_to_origin |= _settings == null;
_invalidate_spec();
if (_price_list != null) {
_price_list.security = security;
_price_list.spec = _spec;
}
_bid_vis_tup.glyph_context = glyph_context(s.bid_column);
_ask_vis_tup.glyph_context = glyph_context(s.ask_column);
@@ -1,11 +1,9 @@
using bts.api;
namespace mbts.spark {
using RegionalTickFactors = user.settings.RegionalTickFactors;
class LadderPriceLineViewAdapter {
public static double bid_line(
double bid, double ask, double settlement, RegionalTickFactors spec) {
double bid, double ask, double settlement, ContractSpecificationImmutable? spec) {
return TickUtils.normalize_price(spec, impl());
double impl() {
if (!double.IsNaN(bid)) {
@@ -19,7 +17,7 @@ namespace mbts.spark {
}
public static double ask_line(
double bid, double ask, double settlement, RegionalTickFactors spec) {
double bid, double ask, double settlement, ContractSpecificationImmutable? spec) {
return TickUtils.normalize_price(spec, impl());
double impl() {
if (!double.IsNaN(ask)) {
@@ -33,7 +31,7 @@ namespace mbts.spark {
}
public static double mid_line(
double bid, double ask, double settlement, RegionalTickFactors spec) {
double bid, double ask, double settlement, ContractSpecificationImmutable? spec) {
return TickUtils.normalize_price(spec, impl());
double impl() {
if (double.IsNaN(bid)) {
@@ -45,16 +43,16 @@ namespace mbts.spark {
if (double.IsNaN(ask)) {
return bid;
}
if (spec is not null) {
return TickUtils.mid_tick(spec, bid, ask);
if (spec.HasValue) {
return TickUtils.mid_tick(spec.Value, bid, ask);
}
return bid;
}
}
static double _try_tick_down(RegionalTickFactors spec, double value) {
if (spec is not null) {
return spec.tickdown(value);
static double _try_tick_down(ContractSpecificationImmutable? spec, double value) {
if (spec.HasValue) {
return spec.Value.tickdown(value);
}
return value;
}
@@ -1,5 +1,4 @@
using bts.api;
using bts.utils;
using mbts.utils;
@@ -9,78 +8,52 @@ using System.Collections.Generic;
using System.Collections.Specialized;
namespace mbts.spark {
using RegionalTickFactors = user.settings.RegionalTickFactors;
public class LadderPriceList : IReadOnlyList<double>, IList<double>, INotifyCollectionChanged, IEquatable<LadderPriceList> {
const long _MAX_LENGTH = int.MaxValue;
long _length;
long _high_tick;
SecurityImmutable? _security;
RegionalTickFactors _regional_tick_backing;
RegionalTickFactors _regional_tick =>
_regional_tick_backing ??= TickUtils.get_regional_ticks(_security);
int _length;
int _high_tick;
public LadderPriceList() { }
public LadderPriceList(LadderPriceList other) {
_length = other._length;
_high_tick = other._high_tick;
_security = other._security;
spec = other.spec;
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
public SecurityImmutable? security {
get => _security;
set {
if (value == _security) {
return;
}
_security = value;
_regional_tick_backing = null;
}
}
public ContractSpecificationImmutable spec { get; set; }
public long high_tick {
public int high_tick {
get => _high_tick;
set => _high_tick = value;
}
public long low_tick {
public int low_tick {
get => high_tick - length;
set => reset(null, value, null);
}
public double start {
get => _regional_tick.tickup<double>(0, (uint)high_tick);
set => high_tick = _regional_tick.tickdiff(value, 0) ?? high_tick;
get => spec.tickup(0, high_tick);
set => high_tick = spec.tickdiff(value, 0) ?? high_tick;
}
public long length {
public int length {
get => _length;
set {
if (value < 0 || value > _MAX_LENGTH) {
throw new ArgumentException(
$"Value 'v' must be >= 0 and < {_MAX_LENGTH} (actually {value})");
if (value < 0) {
throw new ArgumentException($"Value must be >= 0 (actually {value})");
}
_length = value;
}
}
public int Count {
get {
checked {
return (int)length;
}
}
}
public int Count => (int)length;
public bool IsReadOnly => false;
public double this[int idx] {
get => _regional_tick.tick<double>(0, high_tick - idx);
get => spec.tickup(0, high_tick - idx);
set => throw new NotSupportedException();
}
@@ -94,13 +67,11 @@ namespace mbts.spark {
GetEnumerator();
public int IndexOf(double item) {
var idx = _regional_tick.tickdiff(start, item) ?? -1;
var idx = spec.tickdiff(start, item) ?? -1;
if (idx < 0 || idx >= length) {
return -1;
}
checked {
return (int)idx;
}
return idx;
}
public void Insert(int index, double item) =>
@@ -167,15 +138,15 @@ namespace mbts.spark {
}
}
public void reset(long? high_tick = null, long? low_tick = null, long? length = null) {
public void reset(int? high_tick = null, int? low_tick = null, int? length = null) {
if (!high_tick.HasValue && !low_tick.HasValue && !length.HasValue) {
return;
}
if (length.HasValue && length.Value < 0) {
throw new ArgumentException("Must be >= 0", nameof(length));
}
long new_high_tick = 0;
long new_length = 0;
int new_high_tick = 0;
int new_length = 0;
if (high_tick.HasValue) {
new_high_tick = high_tick.Value;
if (low_tick.HasValue) {
@@ -209,7 +180,8 @@ namespace mbts.spark {
other != null &&
_high_tick == other._high_tick &&
_length == other._length &&
_regional_tick.safe_equals(other._regional_tick);
spec.LowTick.Equals(other.spec.LowTick) &&
spec.PriceBreak.Equals(other.spec.PriceBreak);
public override bool Equals(object obj) =>
Equals(obj as LadderPriceList);
@@ -217,10 +189,13 @@ namespace mbts.spark {
public override int GetHashCode() =>
HashCode.Combine(_high_tick, _length);
double _tick_to_price(long tick) =>
_regional_tick.tick<double>(0, tick);
double _tick_to_price(int tick) =>
spec.tickup(0, tick);
void _add_tick(long tick) {
int? _price_to_tick(double price) =>
spec.tickdiff(price, 0);
void _add_tick(int tick) {
int idx;
if (length == 0) {
_high_tick = tick;
@@ -229,9 +204,7 @@ namespace mbts.spark {
_high_tick = tick;
idx = 0;
} else if (tick == low_tick - 1) {
checked {
idx = (int)length;
}
idx = length;
} else {
throw new ArgumentException($"Must be == {nameof(high_tick)} ({high_tick}) + 1, or == {nameof(low_tick)} ({low_tick}) - 1)");
}
@@ -239,7 +212,7 @@ namespace mbts.spark {
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, _tick_to_price(tick), idx));
}
void _remove_tick(long tick) {
void _remove_tick(int tick) {
if (length == 0) {
throw new InvalidOperationException("Cannot remove tick because length is 0");
}
@@ -248,9 +221,7 @@ namespace mbts.spark {
_high_tick--;
idx = 0;
} else if (tick == low_tick) {
checked {
idx = (int)(length - 1);
}
idx = length - 1;
} else {
throw new ArgumentException(
$"Can only remove {nameof(low_tick)} ({low_tick}) or " +
@@ -9,7 +9,6 @@ using mbts.ui;
using mbts.ui.controls;
using mbts.ui.utility.text;
using Spark.Core;
using Spark.Core.Disposables;
using System;
@@ -20,8 +19,6 @@ using System.Windows;
using System.Windows.Media;
namespace mbts.spark {
using RegionalTickFactors = user.settings.RegionalTickFactors;
static class BadgeRender {
// IMPORTANT: the return values for this method MUST BE IN SYNC with the "format" method, else "measure_height" and "LadderRender.measure_row_height" will be broken.
static int _line_count_for_style(LadderSettings.BadgeStyle badge_style) => badge_style == LadderSettings.BadgeStyle.Alternate ? 2 : 1;
@@ -76,16 +73,6 @@ namespace mbts.spark {
}
public static int index_of(IList<double> prices, double price, IComparer<double> comparer, bool relative_idx) {
for (int i = 1; i < prices.Count; i++) {
Log.assert(prices[i - 1] > prices[i]);
var c = comparer.Compare(prices[i - 1], prices[i]);
if (c >= 0) {
c = comparer.Compare(prices[i - 1], prices[i]);
} else {
c = comparer.Compare(prices[i - 1], prices[i]);
}
Log.assert(c < 0);
}
var idx = CollectionHelper.binary_search(prices, price, comparer);
if (relative_idx && idx < 0) {
idx = ~idx;
@@ -108,13 +95,30 @@ namespace mbts.spark {
settings.font_size, settings.width, row_height, HorizontalAlignment.Right,
-4, VerticalAlignment.Center, row * row_height, true);
public static GlyphRun[] format_prices(IList<double> prices, double reference_price, bool format_in_tick_terms, double row_height, LadderColumnSettings settings, GlyphContext glyph_context, RegionalTickFactors spec) {
public static IList<double> gen_prices(double mid, int row_count, ContractSpecificationImmutable spec) {
bool is_odd = row_count % 2 == 1;
var result = new double[row_count];
int range = row_count / 2;
int middle = row_count / 2;
result[middle] = mid;
double up = mid, down = mid;
// Starting from the middle iterate out to the edges
for (int x = 1; x <= range; ++x) {
up = spec.tickup(up);
down = spec.tickdown(down);
result[middle - x] = up;
result[middle + x] = down;
}
return result;
}
public static GlyphRun[] format_prices(IList<double> prices, double reference_price, bool format_in_tick_terms, double row_height, LadderColumnSettings settings, GlyphContext glyph_context, ContractSpecificationImmutable spec) {
var result = new GlyphRun[prices.Count];
Parallel.For(0, prices.Count, i =>
result[i] = format_text(spec.format(prices[i] - reference_price, format_in_tick_terms), i, row_height, settings, glyph_context));
return result;
}
public static GlyphRun[] format_prices(IList<double> prices, double row_height, LadderColumnSettings settings, GlyphContext glyph_context, RegionalTickFactors spec, LadderSettings.PriceDisplayFormat price_display_format) {
public static GlyphRun[] format_prices(IList<double> prices, double row_height, LadderColumnSettings settings, GlyphContext glyph_context, ContractSpecificationImmutable spec, LadderSettings.PriceDisplayFormat price_display_format) {
var result = new GlyphRun[prices.Count];
Parallel.For(0, prices.Count, i =>
result[i] = format_text(spec.format(prices[i]), i, row_height, settings, glyph_context, price_display_format));
@@ -139,12 +143,12 @@ namespace mbts.spark {
bool format_in_tick_terms,
double row_height,
LadderColumnSettings settings,
RegionalTickFactors tick) {
ContractSpecificationImmutable spec) {
if (price_list.IsNullOrEmpty()) {
return;
}
render_prices(
price, glyph_context, price_list, row_height, settings, tick,
price, glyph_context, price_list, row_height, settings, spec,
wrt_price, format_in_tick_terms);
}
@@ -154,12 +158,12 @@ namespace mbts.spark {
IList<double> dprices,
double row_height,
LadderColumnSettings settings,
RegionalTickFactors tick,
ContractSpecificationImmutable spec,
double wrt_price,
bool format_in_tick_terms) {
var foreground = settings.foreground.rgb_brush();
//var background = new SolidColorBrush(settings.background.rgb_color());
var fprices = format_prices(dprices, wrt_price, format_in_tick_terms, row_height, settings, glyph_context, tick);
var fprices = format_prices(dprices, wrt_price, format_in_tick_terms, row_height, settings, glyph_context, spec);
using (var dc = price.RenderOpen())
using (_draw_with_clip(dc, settings, row_height, dprices.Count)) {
//dc.DrawRectangle(background, null, new Rect(0, 0, settings.width, row_count * row_height));
@@ -174,11 +178,11 @@ namespace mbts.spark {
IList<double> dprices,
double row_height,
LadderColumnSettings settings,
RegionalTickFactors tick,
ContractSpecificationImmutable spec,
LadderSettings.PriceDisplayFormat price_display_format) {
var foreground = settings.foreground.rgb_brush();
//var background = new SolidColorBrush(settings.background.rgb_color());
var fprices = format_prices(dprices, row_height, settings, glyph_context, tick, price_display_format);
var fprices = format_prices(dprices, row_height, settings, glyph_context, spec, price_display_format);
using (var dc = price.RenderOpen())
using (_draw_with_clip(dc, settings, row_height, dprices.Count)) {
//dc.DrawRectangle(background, null, new Rect(0, 0, settings.width, row_count * row_height));
@@ -211,7 +215,7 @@ namespace mbts.spark {
IList<double> prices,
NativePriceSize[] rungs,
double row_height,
RegionalTickFactors spec,
ContractSpecificationImmutable spec,
LadderColumnSettings settings,
Func<NativePriceSize, string> fmt,
bool lighten_market_cells,
@@ -244,18 +248,17 @@ namespace mbts.spark {
direct_size: aggr.direct_size + rung.direct_size,
implied_size: aggr.implied_size + rung.implied_size),
rung => {
var ticks = spec.count_ticks(rung.price);
//spec.round_to_tick(rung.price);
var ticks = spec.full_ticks_from_zero(rung.price);
return ticks.HasValue ? spec.tickup(0, ticks.Value) : rung.price;
});
foreach (var rung in row_tick_groups) {
//double price = spec.round_to_tick(rung.price);
var ticks = spec.count_ticks(rung.price);
var ticks = spec.full_ticks_from_zero(rung.price);
var price = ticks.HasValue ? spec.tickup(0, ticks.Value) : rung.price;
// prices are in descending order, so get diff from curr_price - price
var tick_diff = spec.tickdiff(curr_price, price).assert_value();
checked {
curr_index += (int)tick_diff;
}
int tick_diff = spec.tickdiff_unchecked(curr_price, price);
curr_index += tick_diff;
curr_price = price;
if (curr_index >= 0 && curr_index < prices.Count) {
if (market_cell_background_brush != null)
@@ -275,7 +278,7 @@ namespace mbts.spark {
IList<double> prices,
IEnumerable<VolumeAtPriceLevelImmutable> data,
double row_height,
RegionalTickFactors spec,
ContractSpecificationImmutable spec,
VolumeColumnSettings settings,
int last_index,
string last_size_and_direction,
@@ -368,7 +371,7 @@ namespace mbts.spark {
public delegate void RenderCell<T>(DrawingContext dc, int row, T data_item);
static void _render_cells<T>(DrawingVisual dv, double row_height, IEnumerable<(double price, T value)> data, LadderColumnSettings settings, IList<double> prices, RegionalTickFactors spec, RenderCell<T> render_cell) {
static void _render_cells<T>(DrawingVisual dv, double row_height, IEnumerable<(double price, T value)> data, LadderColumnSettings settings, IList<double> prices, ContractSpecificationImmutable spec, RenderCell<T> render_cell) {
using (var dc = dv.RenderOpen())
using (_draw_with_clip(dc, settings, row_height, prices.Count)) {
if (data.is_null_or_empty())
@@ -379,11 +382,8 @@ namespace mbts.spark {
if (double.IsNaN(price))
continue;
// prices are in descending order, so get diff from curr_price - price
var tick_diff = spec.tickdiff(curr_price, price) ?? 0;
Log.assert(
tick_diff > (int.MaxValue - curr_index),
$"Unable to index ladder row for price {price}: tick count exceeds int.MaxValue");
curr_index += (int)tick_diff;
int tick_diff = spec.tickdiff(curr_price, price) ?? 0;
curr_index += tick_diff;
curr_price = price;
if (curr_index >= 0 && curr_index < prices.Count) {
render_cell(dc, curr_index, value);
@@ -409,7 +409,7 @@ namespace mbts.spark {
IList<double> prices,
IEnumerable<(double price, uint piq)> pvp,
double row_height,
RegionalTickFactors spec,
ContractSpecificationImmutable spec,
LadderColumnSettings settings,
Func<uint, string> fmt_value) {
//
@@ -425,10 +425,8 @@ namespace mbts.spark {
foreach (var entry in pvp) {
double price = entry.price;
// prices are in descending order, so get diff from curr_price - price
var tick_diff = spec.tickdiff(curr_price, price).assert_value();
checked {
curr_index += (int)tick_diff;
}
int tick_diff = spec.tickdiff_unchecked(curr_price, price);
curr_index += tick_diff;
curr_price = price;
if (curr_index >= 0 && curr_index < prices.Count) {
var gr = format_text(fmt_value(entry.piq), curr_index, row_height, settings, glyph_context);
@@ -31,12 +31,10 @@
ItemsSource="{Binding rows_view}"
MinRowHeight="17"
RowHeaderWidth="22"
Background="{u:BTSColor ManualFills.background}"
>
<!--Row Header Style-->
<DataGrid.RowHeaderStyle>
<Style TargetType="DataGridRowHeader">
<Setter Property="Background" Value="transparent"/>
<Setter Property="Content" Value="{Binding}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
@@ -125,12 +123,8 @@
<!--Row Style-->
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="{u:BTSColor Grid.default_row_background}"/>
<Setter Property="IsSelected" Value="{Binding is_selected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Style.Triggers>
<Trigger Property="DataGridRow.AlternationIndex" Value="1">
<Setter Property="Background" Value="{u:BTSColor Grid.alternate_row_background}"/>
</Trigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Background" Value="{StaticResource SelectedRowBackground}"/>
</DataTrigger>
@@ -73,7 +73,7 @@ namespace Spark.Trading {
meta.Value.Value.PriceDisplay : Security.Defaults.price_display_settingsi;
if (security.HasValue) {
rv = rv.with(
tick_factors: security.Value.regional_ticks().low_tick.to_api_tick_factors());
tick_factors: security.spec_or_default().tick_factors().to_api_tick_factors());
}
return rv;
}
@@ -891,7 +891,7 @@ namespace mbts.spark {
};
root_bd.SetBinding(
Border.BackgroundProperty, new Binding(nameof(background_brush)) { Source = this });
return root_bd;
return button;
}
}
@@ -769,7 +769,7 @@ namespace mbts.spark {
return;
}
var price_display = TickUtils.get_tick(row.security, price ?? 0).to_api_tick_display_settingsi();
var price_display = row.contract_spec?.tick_factors()?.to_api_tick_display_settingsi();
var update_desc = OrderUtils.update_description(
row.order, price, quantity, price_display, row.quantity_display_settings);
Log.Ui.info(
@@ -179,7 +179,8 @@ namespace mbts.spark {
using var _ = detect_property_changes(
nameof(spec),
nameof(display_quantity_divisor),
nameof(quantity_display));
nameof(quantity_display),
nameof(unit_quantity));
_security_md = value;
bbo.security_md = value;
_payup_bid_cmd.RaiseCanExecuteChanged();
@@ -209,6 +210,9 @@ namespace mbts.spark {
}
}
public double unit_quantity =>
(security?.ContractSpec)?.tick_factors()?.tick_unit_frac() ?? 1;
public AlgoDefinitionVM algo_vm { get; }
public IReadOnlyObservableCollection<AlgoParamRowVM> param_rows { get; }
public BBOVM bbo { get; }
@@ -231,7 +231,7 @@ namespace bts.shell {
sorting_criteria,
_vm.anchors,
filters,
state.grid.with(columns: cols, background: _vm.grid_background_color.to_uint()),
state.grid.with(columns: cols, background: _vm.grid_background_color.rgb_color()),
calc_type,
_vm.header_row_display,
menu_display: _menu_display_vm?.create());
@@ -68,10 +68,10 @@ namespace bts.shell.pnl {
typeface = new TypefaceProto(
cell_appearance.font_family?.name(),
(cell_appearance.font_weight ?? FontWeights.Normal).ToOpenTypeWeight()),
font_color = cell_appearance.foreground?.to_uint() ?? 0,
font_color = cell_appearance.foreground?.rgb_color() ?? 0,
font_size = cell_appearance.font_size,
},
background = cell_appearance.background?.to_uint()
background = cell_appearance.background?.rgb_color()
};
public PNLCellAppearance to_appearance() {
File diff suppressed because it is too large. Load diff
@@ -103,14 +103,14 @@ namespace bts.shell.pnl {
public PNLAnimation to_animation(PNLView.Columns key) =>
new PNLAnimation {
column = key,
foreground = is_font_color_overridden ? font_color_override.color.to_uint() : (uint?)null,
background = is_background_overridden ? background_override.color.to_uint() : (uint?)null,
foreground = is_font_color_overridden ? font_color_override.color.rgb_color() : (uint?)null,
background = is_background_overridden ? background_override.color.rgb_color() : (uint?)null,
font_weight = is_font_weight_overridden ? font_weight_override.ToOpenTypeWeight() : (int?)null
};
public PNLCellAppearanceProto to_appearance_proto() =>
new PNLCellAppearanceProto {
background = is_background_overridden ? background_override.color.to_uint() : (uint?)null,
background = is_background_overridden ? background_override.color.rgb_color() : (uint?)null,
font_params = to_font_params()
};
@@ -119,7 +119,7 @@ namespace bts.shell.pnl {
typeface = new TypefaceProto(
font_family_override?.name(),
is_font_weight_overridden ? font_weight_override.ToOpenTypeWeight() : 0),
font_color = is_font_color_overridden ? font_color_override.color.to_uint() : 0,
font_color = is_font_color_overridden ? font_color_override.color.rgb_color() : 0,
font_size = font_size_override
};
}
@@ -132,7 +132,7 @@ namespace bts.shell.pnl {
// group
var (group_cell_appearance, group_row_background_colors) = group_row_defaults.create();
s.group_cell_appearance = PNLCellAppearanceProto.from_appearance(group_cell_appearance);
s.group_background_colors.SetItems(group_row_background_colors.Select(c => c.to_uint()));
s.group_background_colors.SetItems(group_row_background_colors.Select(c => c.rgb_color()));
//
return s;
}
@@ -329,19 +329,20 @@ namespace bts.shell.pnl {
}
static (string desc, Color fg) _fills_title(Columns key) {
const uint net_fg = 0x333333u;
switch (key) {
case Columns.SODLongPos: return ("Open Buy Fills", BTSColors.MarketData.bid);
case Columns.SODShortPos: return ("Open Sell Fills", BTSColors.MarketData.ask);
case Columns.SODNetPos: return ("Open Fills", BTSColors.UI.default_text);
case Columns.SODNetPos: return ("Open Fills", net_fg.rgb_color());
case Columns.DayLongPos: return ("Day Buy Fills", BTSColors.MarketData.bid);
case Columns.DayShortPos: return ("Day Sell Fills", BTSColors.MarketData.ask);
case Columns.DayNetPos: return ("Day Fills", BTSColors.UI.default_text);
case Columns.DayNetPos: return ("Day Fills", net_fg.rgb_color());
case Columns.RawDayLongPos: return ("Raw Day Buy Fills", BTSColors.MarketData.bid);
case Columns.RawDayShortPos: return ("Raw Day Sell Fills", BTSColors.MarketData.ask);
case Columns.RawDayNetPos: return ("Raw Day Fills", BTSColors.UI.default_text);
case Columns.RawDayNetPos: return ("Raw Day Fills", net_fg.rgb_color());
case Columns.TotalLongPos: return ("All Buy Fills", BTSColors.MarketData.bid);
case Columns.TotalShortPos: return ("All Sell Fills", BTSColors.MarketData.ask);
case Columns.TotalNetPos: return ("All Fills", BTSColors.UI.default_text);
case Columns.TotalNetPos: return ("All Fills", net_fg.rgb_color());
default: throw ExceptionBuilder.Argument.unexpected_case(key, nameof(key));
}
}
@@ -367,7 +368,7 @@ namespace bts.shell.pnl {
switch (key) {
case Columns.WorkingLongPos: return ("Working Buy Orders", BTSColors.MarketData.bid);
case Columns.WorkingShortPos: return ("Working Sell Orders", BTSColors.MarketData.ask);
case Columns.WorkingNetPos: return ("Working Orders", BTSColors.UI.default_text);
case Columns.WorkingNetPos: return ("Working Orders", 0x333333u.rgb_color());
default: throw ExceptionBuilder.Argument.unexpected_case(key, nameof(key));
}
}
@@ -1,24 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BCG;
namespace mbts.ui {
public class NMSheetAllTaskingData {
public IDictionary<UInt32, NMSheetTaskEyeData>
bids = new Dictionary<UInt32, NMSheetTaskEyeData>(),
asks = new Dictionary<UInt32, NMSheetTaskEyeData>();
public void add_sec(UInt32 sec, bts.api.Side side, double edge, double size) {
IDictionary<UInt32, NMSheetTaskEyeData> map = side == bts.api.Side.Buy ? bids : asks;
NMSheetTaskEyeData sec_data;
if (!map.TryGetValue(sec, out sec_data)) {
sec_data = new NMSheetTaskEyeData(true, edge, size);
map.Add(sec, sec_data);
}
}
}
}
@@ -1,6 +1,4 @@
using mbts.ui;
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@@ -19,7 +17,7 @@ namespace BCG
private readonly IDictionary<NMSheetSymbol, NMSheetSingleOptionData> _sym_data_map;
private readonly IDictionary<NMSheetSymbol, IDictionary<uint, BBOPacket>> _bbo_map;
private readonly IDictionary<uint, NMSheetTickerData> _complete_ticker_data;
private readonly NMSheetAllTaskingData _task_data;
private readonly TaskingConsolidatedData _task_data;
private readonly double[] _cached_sorted_strikes;
private readonly NMSheetExpiration[] _cached_sorted_expirations;
@@ -29,7 +27,7 @@ namespace BCG
public NMSheetData(IDictionary<NMSheetSymbol, NMSheetSingleOptionData> sym_data_map,
IDictionary<NMSheetSymbol, IDictionary<uint, BBOPacket>> bbo_map,
IDictionary<uint, NMSheetTickerData> complete_ticker_data,
NMSheetAllTaskingData task_data)
TaskingConsolidatedData task_data)
{
_sym_data_map = sym_data_map;
_bbo_map = bbo_map;
@@ -63,14 +61,14 @@ namespace BCG
public NMSheetData filter_for_strikes_in_tasks(bool is_on_only = false)
{
// if (_task_data != null)
// {
// IEnumerable<uint> eye_secs = _task_data.get_set_securities(mbts.tasks.TaskType.Eye, is_on_only),
// quoter_secs = _task_data.get_set_securities(mbts.tasks.TaskType.Quoter, is_on_only);
// HashSet<uint> all_secs = new HashSet<uint>(Enumerable.Concat(eye_secs, quoter_secs));
// return filter_data(this, all_secs);
// }
// else
if (_task_data != null)
{
IEnumerable<uint> eye_secs = _task_data.get_set_securities(mbts.tasks.TaskType.Eye, is_on_only),
quoter_secs = _task_data.get_set_securities(mbts.tasks.TaskType.Quoter, is_on_only);
HashSet<uint> all_secs = new HashSet<uint>(Enumerable.Concat(eye_secs, quoter_secs));
return filter_data(this, all_secs);
}
else
return this;
}
@@ -106,7 +104,9 @@ namespace BCG
return symbol_data.get_security_key(exp.option_expiration, strike, is_call, out security_key);
else
return false;
}
}
public TaskingConsolidatedData get_task_data() { return _task_data; }
#region INMSheetGridFacingData
@@ -31,8 +31,8 @@ namespace BCG {
private readonly IDictionary<DateTime, Tuple<double, double>> _option_exp_driver_detailed_price_data = new Dictionary<DateTime, Tuple<double, double>>();
private IDictionary<uint, BBOPacket> _bbo_data_map = new Dictionary<uint, BBOPacket>();
private IDictionary<uint, NMSheetTickerData> _ticker_data = new Dictionary<uint, NMSheetTickerData>();
private TaskingConsolidatedData _tasking_data;
private readonly ExchangeSecurityMap _sec_map;
private NMSheetAllTaskingData _ee_tasking_data = new NMSheetAllTaskingData();
public NMSheetSingleOptionData(NMSheetSymbol option,
NMSheetDataRequest data_request,
@@ -93,7 +93,7 @@ namespace BCG {
public void set_ticker(IDictionary<uint, NMSheetTickerData> ticker_data) { _ticker_data = ticker_data; }
public void set_task_data(NMSheetAllTaskingData tasking_data) { _ee_tasking_data = tasking_data; }
public void set_task_data(TaskingConsolidatedData tasking_data) { _tasking_data = tasking_data; }
/// Strikes are not sorted
public double[] get_strikes() { return _theo_data_map.get_strikes(); }
@@ -128,7 +128,7 @@ namespace BCG {
_fill_roll_over_data(cp_row, v, expiration, strike);
_fill_presave_theos(cp_row, v, expiration, strike);
NMSheetCallPutBidAskWrapper<NMSheetTaskEyeData> eye_data;
_fill_eye_data(tp_with_seckey, ref cp_row, out eye_data);
_fill_eye_data(tp_with_seckey, driver_bid_ask, call_bbo_packet, put_bbo_packet, ref cp_row, out eye_data);
NMSheetCallPutBidAskWrapper<NMSheetTaskQuoterData> quoter_data;
_fill_quoter_data(tp_with_seckey, driver_bid_ask, cp_row, out quoter_data);
NMSheetTickerData c_trade_data, p_ticker_data;
@@ -3,32 +3,45 @@
using bts.api;
using mbts.spark;
using mbts.ui;
namespace BCG {
public partial class NMSheetSingleOptionData {
// Gets the data from the bus, and fills in out_eye_data, and cp_row
private void _fill_eye_data(Triplet<mbts.spark.TheoPoint, uint, uint> tp_with_seckeys,
ref double[] cp_row,
out NMSheetCallPutBidAskWrapper<NMSheetTaskEyeData> out_eye_data) {
private void _fill_eye_data(Triplet<mbts.spark.TheoPoint, uint, uint> tp_with_seckeys, Tuple<double, double> driver_bid_ask, BBOPacket call_bbo, BBOPacket put_bbo,
ref double[] cp_row, out NMSheetCallPutBidAskWrapper<NMSheetTaskEyeData> out_eye_data) {
NMSheetTaskEyeData call_bid_data, call_ask_data, put_bid_data, put_ask_data;
// call
_get_eye_security_side_data(tp_with_seckeys.second, Side.Buy, out call_bid_data);
_get_eye_security_side_data(tp_with_seckeys.second, Side.Sell, out call_ask_data);
// put
_get_eye_security_side_data(tp_with_seckeys.third, Side.Buy, out put_bid_data);
_get_eye_security_side_data(tp_with_seckeys.third, Side.Sell, out put_ask_data);
out_eye_data = new NMSheetCallPutBidAskWrapper<NMSheetTaskEyeData>(
call_bid_data, call_ask_data, put_bid_data, put_ask_data);
_get_eye_security_side_data(tp_with_seckeys.first, PutOrCall.Call, Side.Buy, tp_with_seckeys.second, driver_bid_ask, call_bbo, out call_bid_data, ref cp_row,
NMSheetColumnName.call_ee_set_bid_edge, NMSheetColumnName.call_ee_set_bid_size, NMSheetColumnName.call_ee_bid_price);
_get_eye_security_side_data(tp_with_seckeys.first, PutOrCall.Call, Side.Sell, tp_with_seckeys.second, driver_bid_ask, call_bbo, out call_ask_data, ref cp_row,
NMSheetColumnName.call_ee_set_ask_edge, NMSheetColumnName.call_ee_set_ask_size, NMSheetColumnName.call_ee_ask_price);
_get_eye_security_side_data(tp_with_seckeys.first, PutOrCall.Put, Side.Buy, tp_with_seckeys.third, driver_bid_ask, put_bbo, out put_bid_data, ref cp_row,
NMSheetColumnName.put_ee_set_bid_edge, NMSheetColumnName.put_ee_set_bid_size, NMSheetColumnName.put_ee_bid_price);
_get_eye_security_side_data(tp_with_seckeys.first, PutOrCall.Put, Side.Sell, tp_with_seckeys.third, driver_bid_ask, put_bbo, out put_ask_data, ref cp_row,
NMSheetColumnName.put_ee_set_ask_edge, NMSheetColumnName.put_ee_set_ask_size, NMSheetColumnName.put_ee_ask_price);
out_eye_data = new NMSheetCallPutBidAskWrapper<NMSheetTaskEyeData>(call_bid_data, call_ask_data, put_bid_data, put_ask_data);
}
private void _get_eye_security_side_data(uint sec_key, Side side,
out NMSheetTaskEyeData inp_out_data) {
inp_out_data = null;
if (_ee_tasking_data == null)
return;
var map = side == Side.Buy ? _ee_tasking_data.bids : _ee_tasking_data.asks;
map.TryGetValue(sec_key, out inp_out_data);
private void _get_eye_security_side_data(mbts.spark.TheoPoint tp, PutOrCall cp, Side side, uint sec_key, Tuple<double, double> driver_bid_ask, BBOPacket bbo,
out NMSheetTaskEyeData inp_out_data,
ref double[] out_array,
NMSheetColumnName inp_edge_col, NMSheetColumnName inp_size_col, NMSheetColumnName eye_price_col) {
mbts.tasks.TaskSecurityEyeData eye_data = _tasking_data.get_eye_data(sec_key, side);
double edge = Double.NaN, eye_price = Double.NaN;
uint size = 0;
if (eye_data != null) {
edge = eye_data.edge;
size = eye_data.size;
/// Why is the eye sending the price instead of theo ?
if (eye_data.is_on)
eye_price = eye_data.eye_published_price;
else {
double theo = _compute_theo(tp, cp, side, driver_bid_ask);
eye_price = Math.Max(0.0, side == Side.Buy ? theo - edge : theo + edge);
}
}
out_array[(int)inp_edge_col] = edge;
out_array[(int)inp_size_col] = (double)size;
out_array[(int)eye_price_col] = eye_price;
inp_out_data = new NMSheetTaskEyeData(eye_data, side == Side.Buy ? eye_price >= BBOPacket.get_ask_price(bbo) : eye_price <= BBOPacket.get_bid_price(bbo));
}
}
}
@@ -1,88 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using bts.api;
using mbts;
using mbts.spark;
using BCG;
using System.Collections;
using mbts.analytics;
using bts.api.analytics;
using System.Reactive.Linq;
using bts.api.orderman;
namespace mbts.ui {
internal class NMSheetAllTaskingDataSource {
private IBus _bus;
HighPerformanceTimer _timer = new HighPerformanceTimer();
private Nullable<DynamicOrderDefinitionImmutable> get_tasking_order(
OrderDefinitionImmutable def) {
if (def.HasCustomDef && def.CustomDef.HasComposite &&
def.CustomDef.Composite.HasDefinition &&
def.CustomDef.Composite.Definition.HasDynamic) {
var dyn = def.CustomDef.Composite.Definition.Dynamic;
if ("Tasking Eye".Equals(dyn.DynamicOrderType)) {
return dyn;
}
}
return null;
}
private bool is_working(OrderStatus status) {
return status == OrderStatus.Working ||
status == OrderStatus.PendingWorking ||
status == OrderStatus.Disconnected;
}
private void add_task_secs(ref NMSheetAllTaskingData t_data,
bts.api.Side side,
DynamicOrderDefinitionImmutable t_order) {
DynamicOrderParam sec_p;
if (t_order.OrderParams.TryGetValue("Securities", out sec_p)) {
if (!String.IsNullOrEmpty(sec_p.AsString)) {
DynamicOrderParam edge_param = null;
t_order.OrderParams.TryGetValue("Edge", out edge_param);
DynamicOrderParam size_param = null;
t_order.OrderParams.TryGetValue("Shot Size", out size_param);
if (edge_param != null && size_param != null) {
var toks = sec_p.AsString.Split(',');
foreach (var s in toks) {
UInt32 sec_key;
if (UInt32.TryParse(s.Trim(), out sec_key)) {
t_data.add_sec(sec_key, side, edge_param.AsDouble, size_param.AsDouble);
}
}
}
}
}
}
public NMSheetAllTaskingDataSource(OrdersModel orders_model, IBus bus) {
bts.Log.Gen.info("NMSheetAllTaskingDataSource constructed");
_bus = bus;
orders_model.on_orders.Subscribe(ords => {
_timer.start();
NMSheetAllTaskingData t_data = new NMSheetAllTaskingData();
bts.Log.Gen.info($"NMSheetAllTaskingDataSource on_orders n_orders: {ords.state.Values.Count()}");
foreach (var k in ords.state.Values) {
OrderRecordImmutable order = k.order;
if (!is_working(order.State.Status))
continue;
var t_dyn = get_tasking_order(order.Def);
if (t_dyn.HasValue) {
add_task_secs(ref t_data, order.Def.Side, t_dyn.Value);
}
}
_timer.stop();
bts.Log.Gen.info($"NMSheetAllTaskingDataSource n_bids: {t_data.bids.Count()} " +
$"n_asks: {t_data.asks.Count()} t_msecs: {_timer.lastIntervalTime}");
bus.post(SparkTags.TC2Tags.TaskData, t_data);
});
}
}
}
@@ -95,13 +95,12 @@ namespace BCG {
}
public class NMSheetTaskEyeData {
public readonly bool is_on;
public readonly double edge, size;
public readonly mbts.tasks.TaskSecurityEyeData eye_data;
public readonly bool is_eye_cross;
public NMSheetTaskEyeData(bool is_on, double edge, double size) {
this.is_on = is_on;
this.edge = edge;
this.size = size;
public NMSheetTaskEyeData(mbts.tasks.TaskSecurityEyeData eye_data, bool is_eye_cross) {
this.eye_data = eye_data;
this.is_eye_cross = is_eye_cross;
}
}
@@ -7,7 +7,6 @@ using System.Threading.Tasks;
using bts.api;
using mbts.spark;
using mbts.ui;
namespace BCG {
public class NMSheetDataCoalescer : IDisposable {
@@ -32,12 +31,12 @@ namespace BCG {
_bbo_data_source = new NMSheetBBODataSource(threaded_bb, nmsheet_symbol_list, () => { _is_dirty = true; });
_ticker_data_source = new NMSheetTickerDataSource(threaded_bb, nmsheet_symbol_list, req_id, () => { _is_dirty = true; });
_presaved_theos_provider = new NMSheetPresavedTheosProvider(threaded_bb, nmsheet_symbol_list, req_id);
_threaded_bb.subscribe(SparkTags.TC2Tags.TaskData);
//_threaded_bb.add_to_subscription_list(TaskingTags.ConsolidatedDataTag);
_threaded_bb.data_callback += _on_bb_update;
}
private void _on_bb_update(object tag, object data) {
if (SparkTags.TC2Tags.TaskData.Equals(tag) || _in_bb_settings_tag.Equals(tag))
if (/*TaskingTags.ConsolidatedDataTag.Equals(tag) ||*/ _in_bb_settings_tag.Equals(tag))
_is_dirty = true;
}
@@ -45,9 +44,9 @@ namespace BCG {
if (_is_dirty) {
_is_dirty = false;
_timer.start();
NMSheetAllTaskingData d = _threaded_bb.read_state(
SparkTags.TC2Tags.TaskData, new NMSheetAllTaskingData());
NMSheetData rv = new NMSheetData(_main_data_source.get_data(), _bbo_data_source.get_all_data(), _ticker_data_source.get_data(), d);
TaskingConsolidatedData d = null;//_threaded_bb.sec_thread_retrieve_from_cache (TaskingTags.ConsolidatedDataTag) as TaskingConsolidatedData;
NMSheetData rv = new NMSheetData(_main_data_source.get_data(), _bbo_data_source.get_all_data(), _ticker_data_source.get_data(),
d ?? TaskingConsolidatedData.empty);
rv = _filter_data(rv, _threaded_bb.read_state(_in_bb_settings_tag));
_timer.stop();
_stats_logger.log(String.Format("NMSheetDataCoalescer_{0}", _req_id), "NMSheetData.cons", _timer.lastIntervalTime);
@@ -58,10 +58,5 @@ namespace BCG {
public static UInt32 get_ask_size(BBOPacket md) {
return md != null ? md._ask_size : (UInt32)0;
}
public static Tuple<double, UInt32> get_md(BBOPacket md, bool is_bid) {
double price = is_bid ? BBOPacket.get_bid_price(md) : BBOPacket.get_ask_price(md);
UInt32 sz = is_bid ? BBOPacket.get_bid_size(md) : BBOPacket.get_ask_size(md);
return Tuple.Create(price, sz);
}
}
}
@@ -0,0 +1,58 @@
using ProtoBuf;
using System;
namespace mbts.tasks {
[ProtoContract(Name = "ElectronicTradingTask")]
[Serializable]
public class ElectronicTradingTask {
[ProtoBuf.ProtoMember(10)]
public readonly TaskCommon common = null;
[ProtoBuf.ProtoMember(20)]
public readonly ExplicitTask explicit_task = null;
[ProtoBuf.ProtoMember(30)]
public readonly ImplicitTask implicit_task = null;
private ElectronicTradingTask() { }
public ElectronicTradingTask(TaskCommon common, ExplicitTask task) {
// Logger.assert(common != null);
// Logger.assert(task != null);
this.common = common;
this.explicit_task = task;
this.implicit_task = null;
}
public ElectronicTradingTask(TaskCommon common, ImplicitTask task) {
// Logger.assert(common != null);
// Logger.assert(task != null);
this.common = common;
this.explicit_task = null;
this.implicit_task = task;
}
public ElectronicTradingTask with(TaskCommon common) {
return explicit_task == null ?
new ElectronicTradingTask(common, implicit_task) :
new ElectronicTradingTask(common, explicit_task);
}
public ElectronicTradingTask with(TaskCommon common = null, ExplicitTask explicit_task = null) {
return new ElectronicTradingTask(common ?? this.common, explicit_task ?? this.explicit_task);
}
public ElectronicTradingTask with(TaskCommon common = null, ImplicitTask implicit_task = null) {
return new ElectronicTradingTask(common ?? this.common, explicit_task ?? this.explicit_task);
}
public override string ToString() {
return common.id;
}
}
public class QuickStartElectronicTradingTask {
private readonly ElectronicTradingTask _task;
public QuickStartElectronicTradingTask(TaskCommon common, ExplicitTask task) {
_task = new ElectronicTradingTask(common, task);
}
public static implicit operator ElectronicTradingTask(QuickStartElectronicTradingTask task) {
return task._task;
}
}
}
@@ -0,0 +1,159 @@

using ProtoBuf;
using System;
using System.Collections.Generic;
namespace mbts.tasks {
[Serializable]
//[RecordType]
[ProtoContract(Name = "TaskCommon")]
public class TaskCommon {
[ProtoMember(1)]
public readonly string session;
[ProtoMember(10)]
public readonly string id;
[ProtoMember(20)]
public readonly DateTime create_time;
[ProtoMember(30)]
public readonly TaskType task_type;
[ProtoMember(40)]
public readonly string name;
[ProtoMember(50)]
public readonly TaskEdgeType edge_type;
[ProtoMember(60)]
public readonly string edge_surface;
[ProtoMember(70)]
public readonly double bid_edge_param;
[ProtoMember(75)]
public readonly double ask_edge_param;
[ProtoMember(80)]
public readonly double bid_size_param;
[ProtoMember(85)]
public readonly double ask_size_param;
[ProtoMember(90)]
public readonly TaskExitCondition exit_condition;
[ProtoMember(100)]
public readonly double exit_condition_parameter;
[ProtoMember(110)]
public readonly bool rfq_only;
[ProtoMember(120)]
public readonly double rfq_quote_for_seconds;
[ProtoMember(130)]
public readonly TaskSide side;
[ProtoMember(140)]
public readonly DateTime last_modification_time;
[ProtoMember(150)]
public readonly bool auto_hedge;
//[ProtoMember(160)]
//public readonly bool auto_start;
[ProtoMember(200)]
public readonly List<Tuple<int, double>> overridden_edges;
[ProtoMember(210)]
public readonly List<Tuple<int, uint>> overridden_sizes;
private TaskCommon() { /*for protobuf*/ }
public TaskCommon(string id,
string session,
DateTime create_time,
TaskType task_type,
string task_name,
TaskExitCondition exit_condition,
double exit_condition_param,
bool rfq_only,
double rfq_quote_for_seconds,
TaskEdgeType edge_type,
string edge_surface,
double bid_edge_param,
double ask_edge_param,
double bid_size_param,
double ask_size_param,
TaskSide side,
DateTime last_modification_time,
bool auto_hedge,
List<Tuple<int, double>> overridden_edges,
List<Tuple<int, uint>> overridden_sizes) {
this.id = id;
this.session = session;
this.create_time = create_time;
this.task_type = task_type;
this.name = task_name;
this.exit_condition = exit_condition;
this.exit_condition_parameter = exit_condition_param;
this.rfq_only = rfq_only;
this.rfq_quote_for_seconds = rfq_quote_for_seconds;
this.edge_type = edge_type;
this.edge_surface = edge_surface;
this.bid_edge_param = bid_edge_param;
this.ask_edge_param = ask_edge_param;
this.bid_size_param = bid_size_param;
this.ask_size_param = ask_size_param;
this.side = side;
this.last_modification_time = last_modification_time;
this.auto_hedge = auto_hedge;
this.overridden_edges = overridden_edges;
this.overridden_sizes = overridden_sizes;
}
public static TaskCommon Default {
get {
return new TaskCommon(
id: Guid.NewGuid().ToString(),
session: String.Empty,
create_time: DateTime.Now,
task_type: TaskType.Quoter,
task_name: "",
exit_condition: TaskExitCondition.Contracts,
exit_condition_param: 100,
rfq_only: false,
rfq_quote_for_seconds: 10,
edge_type: TaskEdgeType.Manual,
edge_surface: "",
bid_edge_param: double.NaN,
ask_edge_param: double.NaN,
bid_size_param: double.NaN,
ask_size_param: double.NaN,
side: TaskSide.Buy | TaskSide.Sell,
last_modification_time: DateTime.Now,
auto_hedge: true,
overridden_edges: new List<Tuple<int, double>>(),
overridden_sizes: new List<Tuple<int, uint>>());
}
}
public TaskCommon with(string id = null, string session = null, DateTime? create_time = null,
TaskType? task_type = null, string name = null, TaskExitCondition? exit_condition = null,
double? exit_condition_parameter = null, bool? rfq_only = null, double? rfq_quote_for_seconds = null, TaskEdgeType? edge_type = null,
string edge_surface = null,
double? bid_edge_param = null, double? bid_size_param = null,
double? ask_edge_param = null, double? ask_size_param = null,
TaskSide? side = null, DateTime? last_modification_time = null,
bool? auto_hedge = null,
List<Tuple<int, double>> overridden_edges = null,
List<Tuple<int, uint>> overridden_sizes = null) {
return new TaskCommon(id ?? this.id,
session ?? this.session,
create_time ?? this.create_time,
task_type ?? this.task_type,
name ?? this.name,
exit_condition ?? this.exit_condition,
exit_condition_parameter ?? this.exit_condition_parameter,
rfq_only ?? this.rfq_only,
rfq_quote_for_seconds ?? this.rfq_quote_for_seconds,
edge_type ?? this.edge_type,
edge_surface ?? this.edge_surface,
bid_edge_param ?? this.bid_edge_param,
ask_edge_param ?? this.ask_edge_param,
bid_size_param ?? this.bid_size_param,
ask_size_param ?? this.ask_size_param,
side ?? this.side,
last_modification_time ?? this.last_modification_time,
auto_hedge ?? this.auto_hedge,
overridden_edges ?? this.overridden_edges,
overridden_sizes ?? this.overridden_sizes);
}
}
}
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mbts.tasks
{
/// Task persisted state combined with
/// the live running state
public class TaskLiveData : IEquatable<TaskLiveData>
{
public readonly ElectronicTradingTask task;
public readonly TaskSwitchState switch_state;
public readonly TaskHealthState task_state;
public readonly double net_accumulation, abs_accumulation;
public TaskLiveData(ElectronicTradingTask task, TaskSwitchState switch_state, TaskHealthState health_state,
double net_accumulation, double abs_accumulation)
{
this.task = task;
this.switch_state = switch_state;
this.task_state = health_state;
this.net_accumulation = net_accumulation;
this.abs_accumulation = abs_accumulation;
}
public string task_id { get { return task.common.id; } }
public TaskType task_type { get { return task.common.task_type; } }
public string name { get { return task.common.name; } }
public double completion_ratio { get { return abs_accumulation / task.common.exit_condition_parameter; } }
public bool is_filled { get { return completion_ratio >= 1.0; } }
public DateTime modification_time { get { return task.common.last_modification_time; } }
public TaskLiveData with(ElectronicTradingTask task = null, TaskSwitchState? switch_state = null, TaskHealthState? task_state = null,
double? net_accumulation = null, double? abs_accumulation = null)
{
return new TaskLiveData(task ?? this.task,
switch_state ?? this.switch_state,
task_state ?? this.task_state,
net_accumulation ?? this.net_accumulation,
abs_accumulation ?? this.abs_accumulation);
}
public int GetHashCode(TaskLiveData obj) { return obj.task_id.GetHashCode(); }
public bool Equals(TaskLiveData other)
{
return ReferenceEquals(task, other.task) &&
switch_state == other.switch_state &&
task_state == other.task_state &&
completion_ratio == other.completion_ratio;
}
public override string ToString()
{
return task.ToString();
}
public string get_summary_text()
{
string sign = task.common.side == TaskSide.Buy ? "+" : (task.common.side == TaskSide.Sell ? "-" : "+/-");
return String.Format("{0}{1} ({2}/{3})", sign, task.common.name, abs_accumulation, task.common.exit_condition_parameter);
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace mbts.tasks {
public class TaskSecurityEyeData {
public TaskSecurityEyeData() {
}
public bool is_output_present {
get {
return false;
}
}
public bool is_on {
get {
return false;
}
}
/// If the security is on, returns the edge as sent by the eye
/// otherwise returns the input edge
public double edge {
get {
return Double.NaN;
}
}
/// If the security is on, returns the size as sent by the eye
/// otherwise returns the input size
public uint size {
get {
return 0;
}
}
public double eye_published_price {
get {
// if (is_on && is_output_present)
// return input.secside_key.side == bts.o2.msgs.Side.type.BUY ? output.price - output.edge : output.price + output.edge;
// return Double.NaN;
return Double.NaN;
}
}
}
}
@@ -48,3 +48,53 @@ namespace mbts.engine {
}
}
}
namespace BCG {
public class TaskingConsolidatedData {
public TaskingConsolidatedData(IEnumerable<TaskLiveData> input_tasks,
object input_securities,
object eye_output,
object quoter_output) {
}
public readonly static TaskingConsolidatedData empty = new TaskingConsolidatedData(Enumerable.Empty<TaskLiveData>(),
null, null, null);
// public TaskingConsolidatedData with(IEnumerable<TaskLiveData> input_tasks = null,
// IEnumerable<TaskSecurityData> input_securities = null,
// IEnumerable<EyeSecurityState> eye_output = null,
// IEnumerable<QuoterSecurityState> quoter_output = null) {
// return new TaskingConsolidatedData(input_tasks ?? this._input_tasks, input_securities ?? this._input_securities,
// eye_output ?? _eye_output, quoter_output ?? _quoter_output);
// }
public IEnumerable<TaskLiveData> get_tasks(TaskType task_type) { return new TaskLiveData[] { }; }
public TaskLiveData get_task_by_name(TaskType task_type, string name) {
IEnumerable<TaskLiveData> live_tasks = get_tasks(task_type);
return live_tasks.FirstOrDefault(lt => lt.task.common.name == name);
}
public IEnumerable<TaskLiveData> get_security_owning_tasks(IEnumerable<SecuritySideKey> secside_keys, TaskType t_type) {
HashSet<TaskLiveData> rv = new HashSet<TaskLiveData>();
return rv;
}
public HashSet<uint> get_set_securities(TaskType task_type, bool is_on_only = false) {
return new HashSet<uint>();
}
public TaskSecurityEyeData get_eye_data(uint key, Side side) { return get_eye_data(new SecuritySideKey(key, side)); }
public TaskSecurityEyeData get_eye_data(SecuritySideKey key) {
return new TaskSecurityEyeData();
}
public TaskSecurityQuoterData get_quoter_data(uint key, Side side) { return get_quoter_data(new SecuritySideKey(key, side)); }
public TaskSecurityQuoterData get_quoter_data(SecuritySideKey key) {
return new TaskSecurityQuoterData();
}
public TaskLiveData get_security_task(SecuritySideKey key, TaskType task_type) {
return null;
}
}
}
@@ -123,15 +123,6 @@ namespace BCG {
#endregion
#region Orders
[System.ComponentModel.Category("Orders / Algo")]
[System.ComponentModel.DisplayName("Default Account")]
public string Account { get; set; }
[System.ComponentModel.Category("Orders / Algo")]
[System.ComponentModel.DisplayName("Default Qty")]
public Nullable<double> DefaultQty { get; set; }
#endregion
public NMSheetSettingLayout() {
show_settings_header = false;
show_exp_navigator = false;
@@ -18,7 +18,6 @@ using mbts.spark.filters;
using System.Collections;
using System.Reactive.Linq;
using System.Threading;
using bts.api.orderman;
namespace BCG {
public partial class NMSheetControl : UserControl {
@@ -556,17 +555,6 @@ namespace BCG {
}
private void _launch_order_entry_window(NMSheetTheoGrid.GridCell cell,
OrderEntryWindow window_type) {
Func<string, bts.AccountTuple> get_account = (string default_acc) => {
string account = _settings.setting_layout.Account;
if (String.IsNullOrEmpty(account)) {
account = default_acc;
}
Nullable<uint> id = _get_account_id(account);
if (!id.HasValue) {
id = 0;
}
return new bts.AccountTuple(id.Value, account);
};
uint key;
var found = _sheet_data.get_security_key(cell.expiration,
cell.strike, cell.call_selected, out key);
@@ -578,20 +566,7 @@ namespace BCG {
if (sc_data.sec_md_map.TryGetValue(key, out var smd)) {
switch (window_type) {
case OrderEntryWindow.Ticket:
bool is_bid = NMSheetSettingColumnOrganization.get_column_info(cell.col).is_bid;
bts.AccountTuple acc_tup = get_account("SMALL");
Nullable<double> qty = _settings.setting_layout.DefaultQty;
OrderDefinition od = new OrderDefinition() {
SecurityKey = smd.id,
TimeInForce = TimeInForce.Gtc,
Account = acc_tup.name,
AccountId = acc_tup.id
};
BBOPacket bbo = _sheet_data.get_bbo(smd.id);
Tuple<double, UInt32> pr_sz = BBOPacket.get_md(bbo, is_bid);
UInt32 effective_qty = qty.HasValue ? Convert.ToUInt32(Math.Abs(qty.Value)) : pr_sz.Item2;
_threaded_bb.post(SparkTags.ShowOrderTicketTag,
(new OrderDefinitionImmutable(od), pr_sz.Item1, effective_qty));
_threaded_bb.post(SparkTags.ShowOrderTicketFromSecurityTag, smd);
break;
case OrderEntryWindow.Ladder:
_threaded_bb.post(SparkTags.ShowLadderTag, smd);
@@ -87,21 +87,21 @@ namespace BCG {
}
private void _refresh_task_data(uint seckey) {
// string eye_task_text = String.Empty, quoter_task_text = String.Empty;
// bool dummy, is_bid, is_ask;
// NMSheetSettingColumnOrganization.parse_column(_last_mousemove_cell.col, out dummy, out dummy, out is_bid, out is_ask);
// if (is_bid ^ is_ask) {
// TaskingConsolidatedData task_data = _sheet_data.get_task_data();
// mbts.tasks.TaskLiveData eye_task_ld = task_data != null ? task_data.get_security_task(new mbts.engine.SecuritySideKey(seckey, is_bid ? Side.Buy : Side.Sell), mbts.tasks.TaskType.Eye) : null;
// if (eye_task_ld != null)
// eye_task_text = String.Format("Eye '{0}' {1} {2}", eye_task_ld.name, eye_task_ld.switch_state.ToString().ToUpper(),
// eye_task_ld.abs_accumulation.ToString("0") + "/" + eye_task_ld.task.common.exit_condition_parameter.ToString("0"));
// mbts.tasks.TaskLiveData quoter_task_ld = task_data != null ? task_data.get_security_task(new mbts.engine.SecuritySideKey(seckey, is_bid ? Side.Buy : Side.Sell), mbts.tasks.TaskType.Quoter) : null;
// if (quoter_task_ld != null)
// quoter_task_text += String.Format("Quoter '{0}' {1} {2}", quoter_task_ld.name, quoter_task_ld.switch_state.ToString().ToUpper(),
// quoter_task_ld.abs_accumulation.ToString("0") + "/" + quoter_task_ld.task.common.exit_condition_parameter.ToString("0"));
// }
// _set_text_visibility(_statusbar_toolstripstatus_task, true, String.Format("{0}{1}{2}", eye_task_text, String.IsNullOrEmpty(eye_task_text) ? String.Empty : " ", quoter_task_text));
string eye_task_text = String.Empty, quoter_task_text = String.Empty;
bool dummy, is_bid, is_ask;
NMSheetSettingColumnOrganization.parse_column(_last_mousemove_cell.col, out dummy, out dummy, out is_bid, out is_ask);
if (is_bid ^ is_ask) {
TaskingConsolidatedData task_data = _sheet_data.get_task_data();
mbts.tasks.TaskLiveData eye_task_ld = task_data != null ? task_data.get_security_task(new mbts.engine.SecuritySideKey(seckey, is_bid ? Side.Buy : Side.Sell), mbts.tasks.TaskType.Eye) : null;
if (eye_task_ld != null)
eye_task_text = String.Format("Eye '{0}' {1} {2}", eye_task_ld.name, eye_task_ld.switch_state.ToString().ToUpper(),
eye_task_ld.abs_accumulation.ToString("0") + "/" + eye_task_ld.task.common.exit_condition_parameter.ToString("0"));
mbts.tasks.TaskLiveData quoter_task_ld = task_data != null ? task_data.get_security_task(new mbts.engine.SecuritySideKey(seckey, is_bid ? Side.Buy : Side.Sell), mbts.tasks.TaskType.Quoter) : null;
if (quoter_task_ld != null)
quoter_task_text += String.Format("Quoter '{0}' {1} {2}", quoter_task_ld.name, quoter_task_ld.switch_state.ToString().ToUpper(),
quoter_task_ld.abs_accumulation.ToString("0") + "/" + quoter_task_ld.task.common.exit_condition_parameter.ToString("0"));
}
_set_text_visibility(_statusbar_toolstripstatus_task, true, String.Format("{0}{1}{2}", eye_task_text, String.IsNullOrEmpty(eye_task_text) ? String.Empty : " ", quoter_task_text));
}
private static void _set_text_visibility(System.Windows.Forms.ToolStripStatusLabel l, bool new_visibility, string new_text) {
@@ -0,0 +1,99 @@
using mbts;
using mbts.tasks;
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace BCG {
partial class NMSheetControl {
//private bool _task_quoter_enabled = true;
private void _init_task_quoter_ui() {
// _task_quoter_enabled = true;
// if (_task_quoter_enabled)
// _disable_task_quoter_submenus();
// else
// _toolstripmenuitem_task_quoter.Enabled = false;
// _toolstripmenuitem_settings_show_task_quoter_data.Click += (s, e) => _get_toolstripmenuitem_display_state_and_publish(_toolstripmenuitem_settings_show_task_quoter_data,
// NMSheetSettingColumnOrganization.get_cols_for_type(NMSheetColumnType.Quoter).ToArray());
}
private void _disable_task_quoter_submenus() {
// _toolstripmenuitem_task_quoter.Enabled = _toolstripmenuitem_task_quoter_add_buys_to_task.Enabled =
// _toolstripmenuitem_task_quoter_add_sells_to_task.Enabled = _toolstripmenuitem_task_quoter_add_buys_and_sells_to_task.Enabled = false;
// _toolstripmenuitem_task_quoter_add_buys_to_task.DropDownItems.Clear();
// _toolstripmenuitem_task_quoter_add_sells_to_task.DropDownItems.Clear();
// _toolstripmenuitem_task_quoter_add_buys_and_sells_to_task.DropDownItems.Clear();
// List<ToolStripItem> create_menu_items = new List<ToolStripItem>();
// foreach (ToolStripItem ti in _toolstripmenuitem_task_quoter.DropDownItems)
// if (_create_menu_tag.Equals(ti.Tag))
// create_menu_items.Add(ti);
// create_menu_items.ForEach(ti => _toolstripmenuitem_task_quoter.DropDownItems.Remove(ti));
}
private void _adapt_contextmenu_for_tasks_quoter() {
// if (_task_quoter_enabled) {
// _disable_task_quoter_submenus();
// if (_task_selection.is_active) {
// _toolstripmenuitem_task_quoter.Enabled = true;
// ///Create
// IEnumerable<TaskCommon> templates = _threaded_bb.sec_thread_retrieve_from_cache(TaskingTags.TemplatesTag) as IEnumerable<TaskCommon>;
// templates = templates == null || templates.Count() == 0 ? new TaskCommon[] { TaskCommon.Default.with(name: "New Task") } : templates;
// double min_strike = _task_selection.strikes.Min(), max_strike = _task_selection.strikes.Max();
// string name = TaskType.Quoter.ToString() + " " +
// _task_selection.exp.get_display_text() + " " +
// (min_strike == max_strike ? min_strike.ToString("0.00") : String.Format("{0} - {1}", min_strike.ToString("0.00"), max_strike.ToString("0.00")));
// int add_task_index = 0;
// foreach (TaskCommon t in templates) {
// ToolStripMenuItem add_task_item = new ToolStripMenuItem(t.name, null, (s, e) => {
// mbts.tasks.TaskCommon common_task = t.with(task_type: TaskType.Quoter, name: name, side: TaskSide.None, id: Guid.NewGuid().ToString());
// ExplicitTask explicit_task = ExplicitTask.Default.with(securities: _task_selection.keys, security_descriptions: _task_selection.names);
// _threaded_bb.sec_thread_write(TaskingTags.ShowCreateTask, new ElectronicTradingTask(common_task, explicit_task));
// });
// add_task_item.Tag = _create_menu_tag;
// add_task_item.Enabled = true;
// _toolstripmenuitem_task_quoter.DropDownItems.Insert(add_task_index++, add_task_item);
// }
// //Add Buys to
// TaskingConsolidatedData task_data = _sheet_data.get_task_data();
// _toolstripmenuitem_task_quoter_add_buys_to_task.Enabled = true;
// IEnumerable<TaskLiveData> tasks = task_data.get_tasks(TaskType.Quoter).OrderBy(t => t.name);
// foreach (TaskLiveData t in tasks) {
// ElectronicTradingTask mod_task = _get_mod_task(t.task, _task_selection);
// ToolStripMenuItem add_item = new ToolStripMenuItem(t.get_summary_text(), null, (s, e) => _threaded_bb.sec_thread_write(TaskingTags.ShowEditTask, mod_task));
// add_item.Enabled = t.task.common.side != TaskSide.Sell;
// _toolstripmenuitem_task_quoter_add_buys_to_task.DropDownItems.Add(add_item);
// }
// /// Add Sells to
// _toolstripmenuitem_task_quoter_add_sells_to_task.Enabled = true;
// foreach (TaskLiveData t in tasks) {
// ElectronicTradingTask mod_task = _get_mod_task(t.task, _task_selection);
// ToolStripMenuItem add_item = new ToolStripMenuItem(t.get_summary_text(), null, (s, e) => _threaded_bb.sec_thread_write(TaskingTags.ShowEditTask, mod_task));
// add_item.Enabled = t.task.common.side != TaskSide.Buy;
// _toolstripmenuitem_task_quoter_add_sells_to_task.DropDownItems.Add(add_item);
// }
// /// Add Buys/Sells to
// _toolstripmenuitem_task_quoter_add_buys_and_sells_to_task.Enabled = true;
// foreach (TaskLiveData t in tasks) {
// ElectronicTradingTask mod_task = _get_mod_task(t.task, _task_selection);
// ToolStripMenuItem add_item = new ToolStripMenuItem(t.get_summary_text(), null, (s, e) => _threaded_bb.sec_thread_write(TaskingTags.ShowEditTask, mod_task));
// add_item.Enabled = t.task.common.side == (TaskSide.Buy | TaskSide.Sell);
// _toolstripmenuitem_task_quoter_add_buys_and_sells_to_task.DropDownItems.Add(add_item);
// }
// }
// }
}
// private ElectronicTradingTask _get_task_quoter_mod_task(ElectronicTradingTask task) {
// List<uint> secs = new List<uint>(task.explicit_task.securities);
// List<string> secs_desc = new List<string>(task.explicit_task.security_descriptions);
// secs.AddRange(_task_selection.keys);
// secs_desc.AddRange(_task_selection.names);
// ElectronicTradingTask mod_task = task.with(explicit_task: task.explicit_task.with(securities: secs, security_descriptions: secs_desc));
// return mod_task;
// }
}
}
@@ -83,25 +83,26 @@ namespace BCG {
}
private bool _get_ee_switch_override(NMSheetSettings settings, MyAlertHelperData helper_data, int exp_index, int strike_index, ref Color out_color) {
if (!helper_data.is_theo)
return false;
NMSheetRowAuxiliaryData aux_data = _formatted_theos.get_aux_data(exp_index, strike_index);
if (aux_data == null)
return false;
NMSheetCallPutBidAskWrapper<NMSheetTaskEyeData> t_data = aux_data.task_ee_data;
if (t_data == null)
return false;
NMSheetTaskEyeData bid_sec_t_data =
t_data.get_data(helper_data.is_call ? bts.api.PutOrCall.Call : bts.api.PutOrCall.Put,
bts.api.Side.Buy);
NMSheetTaskEyeData ask_sec_t_data =
t_data.get_data(helper_data.is_call ? bts.api.PutOrCall.Call : bts.api.PutOrCall.Put,
bts.api.Side.Sell);
if ((bid_sec_t_data != null && bid_sec_t_data.is_on) ||
(ask_sec_t_data != null && ask_sec_t_data.is_on)) {
out_color = settings.setting_alerts.ee_on_color.HasValue ?
settings.setting_alerts.ee_on_color.Value : Color.DarkGreen;
return true;
if (helper_data.is_ee_set_edge_or_size || helper_data.is_ee_price) {
NMSheetRowAuxiliaryData aux_data = _formatted_theos.get_aux_data(exp_index, strike_index);
if (aux_data != null) {
NMSheetCallPutBidAskWrapper<NMSheetTaskEyeData> eye_data = aux_data.task_ee_data;
if (eye_data != null) {
NMSheetTaskEyeData secside_eye_data = eye_data.get_data(helper_data.is_call, helper_data.is_bid);
if (secside_eye_data != null && secside_eye_data.eye_data != null) {
if (helper_data.is_ee_price) {
if (secside_eye_data.is_eye_cross) {
out_color = _settings.setting_alerts.ee_fire_color.Value;
return true;
}
}
if (secside_eye_data.eye_data.is_on) {
out_color = _settings.setting_alerts.ee_on_color.Value;
return true;
}
}
}
}
}
return false;
}
@@ -11,8 +11,6 @@ using System.Reactive.Linq;
using System.Windows.Input;
namespace mbts.spark {
using RegionalTickFactors = user.settings.RegionalTickFactors;
class InlineOrderTicketProperties {
public readonly InlineUserProperty<double> price;
public readonly InlineUserProperty<double> size;
@@ -104,7 +102,6 @@ namespace mbts.spark {
public SecurityImmutable security => _security.Value;
public double price { get; set; }
public RegionalTickFactors price_tick => security.regional_ticks();
public CalculatorLogic<double> size_calculator { get; }
public double display_quantity_divisor {
get => _display_quantity_divisor;
@@ -225,7 +225,10 @@ namespace bts.spark {
var security = try_get_security(order.Def.SecurityKey);
var change_descs = new List<string>(1);
var price_display = TickUtils.get_tick(security, price).to_api_tick_display_settingsi();
TickDisplaySettingsImmutable? price_display =
security.HasValue && security.Value.HasContractSpec ?
security.Value.ContractSpec.tick_factors().to_api_tick_display_settingsi() : null;
var price_qty_change_desc = OrderUtils.update_description(
order, price, size, price_display);
@@ -74,7 +74,7 @@
<usp:PriceEntryControl
Grid.ColumnSpan="2"
usp:OrderModificationControl.IsDirty="{Binding price_dirty, FallbackValue={x:Null}}"
RegionalTick="{Binding price_tick}"
ContractSpec="{Binding security.ContractSpec}"
Focusable="false"
TickDefaultValue="{Binding current_price, Converter={StaticResource TickDefaultPriceConverter}, FallbackValue={u:Double 0}}"
Value="{Binding price}"
@@ -29,7 +29,7 @@ namespace mbts.spark {
get {
var m = new OrderMetadata { KeyBinding = string.Empty, NoProps = false };
if (_studio_meta.HasValue && _studio_meta.Value.badge_color.HasValue)
m.Color = _studio_meta.Value.badge_color.Value.to_uint();
m.Color = _studio_meta.Value.badge_color.Value.rgb_color();
return m;
}
}
+8 -5
View File
@@ -254,14 +254,17 @@ namespace mbts.spark {
$"{(order.HasDef ? order.Def.Side.ToString() : "(unknown-side)")} {(order.HasState ? ($@"{spec.format(order.State.Price)} @ {order.State.Quantity}") : "(unknown-price) @ (unknown-quantity)")}";
public static string short_description(
SecurityImmutable security, Side side, double price, double quantity) {
var price_display = TickUtils.get_tick(security, price).to_api_tick_display_settingsi();
return new StringBuilderEx(
SecurityImmutable security, Side side, double price, double quantity) =>
new StringBuilderEx(
security.ToString(), " ",
side.ToString(), " ",
price_quantity_description(price, quantity, price_display)
price_quantity_description(price, quantity, security.spec_or_default())
).ToString();
}
public static string price_quantity_description(
double price, double quantity, ContractSpecificationImmutable spec) =>
price_quantity_description(
price, quantity, spec.tick_factors().to_api_tick_display_settingsi());
public static string price_quantity_description(
double price,
@@ -136,7 +136,7 @@ namespace mbts.analytics {
IEnumerable<VolSurfaceExpiration> all_exps) {
var exps = all_exps.Where(vse => vse.symbol.is_null_or_empty()).ToArray();
var exp_header_cells = exps
.Select(vse => SecurityFormatter.format_expiration(vse.expiration))
.Select(vse => DateFormatter.Format(vse.expiration, DateFormat.DayMonthAbvDiff2000))
.ToArray();
return (exps, exp_header_cells);
}
@@ -145,7 +145,7 @@ namespace mbts.analytics {
IEnumerable<VolSurfaceExpiration> all_exps) {
var exps = all_exps.ToArray();
var exp_header_cells = exps.Select(vse => string.IsNullOrEmpty(vse.symbol) ?
SecurityFormatter.format_expiration(vse.expiration) : vse.symbol)
DateFormatter.Format(vse.expiration, DateFormat.DayMonthAbvDiff2000) : vse.symbol)
.ToArray();
return (exps, exp_header_cells);
}
@@ -57,6 +57,8 @@
<analytics:ComboFutureDataColumn x:Key="FutureSymDataColumn" HeaderTemplate="{StaticResource SymHeaderTemplate}" ElementStyle="{StaticResource FutureSymDataElementStyle}" MinWidth="60" x:Shared="False" />
<analytics:ComboOptionDataColumn x:Key="OptionExpDataColumn" HeaderTemplate="{StaticResource ExpHeaderTemplate}" ElementStyle="{StaticResource OptionExpDataElementStyle}" MinWidth="60" x:Shared="False" />
<analytics:ComboOptionDataColumn x:Key="OptionSymDataColumn" HeaderTemplate="{StaticResource SymHeaderTemplate}" ElementStyle="{StaticResource OptionSymDataElementStyle}" MinWidth="60" x:Shared="False" />
<MenuItem x:Key="LaunchConfigurationEditorMenuItem" x:Shared="False" Header="Report Configuration..." Command="{Binding DataContext.launch_configuration_editor, Source={x:Reference ComboWindow}}" />
<MenuItem x:Key="ExportToCSVMenuItem" Header="Export To CSV..." Command="{Binding export_to_csv_command}" CommandParameter="{Binding DataContext.show_call_put, Source={x:Reference ComboWindow}}" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
@@ -97,7 +99,14 @@
VerticalGridLinesBrush="LightGray"
CanUserResizeColumns="False"
CanUserReorderColumns="False"
IsReadOnly="True" />
IsReadOnly="True"
>
<DataGrid.ContextMenu>
<ContextMenu>
<StaticResourceExtension ResourceKey="LaunchConfigurationEditorMenuItem" />
</ContextMenu>
</DataGrid.ContextMenu>
</c:DataGridEx>
</AdornerDecorator>
<GridSplitter Grid.Row="2" Height="3" Background="Black" HorizontalAlignment="Stretch" />
@@ -135,6 +144,12 @@
<TextBlock Text="{Binding Item.strike, RelativeSource={RelativeSource AncestorType=DataGridRow}}" />
</DataTemplate>
</DataGrid.RowHeaderTemplate>
<DataGrid.ContextMenu>
<ContextMenu>
<StaticResourceExtension ResourceKey="LaunchConfigurationEditorMenuItem" />
<StaticResourceExtension ResourceKey="ExportToCSVMenuItem" />
</ContextMenu>
</DataGrid.ContextMenu>
</c:DataGridEx>
</AdornerDecorator>
@@ -121,7 +121,7 @@ namespace mbts.analytics {
timer.stop();
Log.Ui.info($"PNLReportCalculator n_pos: {output.position_data.Count()} " +
$"n_day_trades: {output.day_trades.Count()} time(msecs): {timer.lastIntervalTime}");
//_log_before_posting(output.position_data);
_log_before_posting(output.position_data);
_bus.post(SparkTags.ReportBlackboardTags.PNL.PNLData, output);
});
}
@@ -1,7 +1,5 @@
#nullable enable
namespace mbts.analytics {
using bts.api;
using System;
using System.Diagnostics.Contracts;
@@ -19,9 +17,13 @@ namespace mbts.analytics {
symbol = null;
}
private static string _format_exp(DateTime exp) {
return mbts.ui.utility.ExpirationFormatter.DateFormatter.format_day_month_year(exp);
}
SlideGreekUnitKey(DateTime exp_date) {
exp = exp_date;
_unique_name = SecurityFormatter.format_expiration(exp_date);
_unique_name = _format_exp(exp_date);
type = GroupType.Exp;
symbol = null;
}
@@ -29,7 +31,7 @@ namespace mbts.analytics {
SlideGreekUnitKey(DateTime exp_date, string symbol) {
exp = exp_date;
this.symbol = symbol;
_unique_name = $"{SecurityFormatter.format_expiration(exp_date)}:{symbol}";
_unique_name = $"{_format_exp(exp_date)}:{symbol}";
type = GroupType.SymExp;
}
@@ -115,21 +115,21 @@ namespace mbts.analytics {
}
private void _handle_nonvol_data(VolSurfaceNonVolData vs_nonvol_data) {
// bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_nonvol_data report {0}",
// _report.ReportName));
bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_nonvol_data report {0}",
_report.ReportName));
_vs_nonvol_data = vs_nonvol_data;
}
private void _handle_future_prices(
IReadOnlyDictionary<SecurityExpiration, FutureTheoStructure> future_prices_map) {
// bts.Log.Gen.Diag(String.Format("SlideReportCalculator._handle_future_prices report {0}",
// _report.ReportName));
bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_future_prices report {0}",
_report.ReportName));
_future_prices_map = future_prices_map.ToDictionary(kv => kv.Key, kv => kv.Value.theo);
}
private void _handle_trades(IEnumerable<ITradeLogRow> trades) {
// bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_trades report {0}",
// _report.ReportName));
bts.Log.Gen.info(String.Format("SlideReportCalculator._handle_trades report {0}",
_report.ReportName));
_all_trades = trades.Where(t => t.is_active);
if (_report.CalcMode == Report.Types.ReportCalculationMode.PositionOrTheoChange) {
_compute_dirty = true;
+2 -1
View File
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<Authors>Blue Trading Systems</Authors>
<Company>Blue Trading Systems</Company>
@@ -34,6 +34,7 @@
<PackageReference Include="System.Reactive.Interfaces" Version="5.0.0" />
<PackageReference Include="System.Reactive.Linq" Version="5.0.0" />
<PackageReference Include="System.Reactive.PlatformServices" Version="5.0.0" />
<PackageReference Include="System.Runtime.Experimental" Version="6.0.2" />
<PackageReference Include="CommandLineParser" Version="2.9.1" />
<ProjectReference Include="../spark_api/spark_api.csproj" />
<ProjectReference Include="../spark_core/spark_core.csproj" />
@@ -71,8 +71,7 @@ namespace BCG {
foreach (string sym in temp.Keys) {
SortedList<DateTime, string> temp2 = temp[sym];
foreach (KeyValuePair<DateTime, string> kvp in temp2) {
string datecode = bts.api.SecurityFormatter.format_expiration(
kvp.Key, date_format: bts.api.DateFormat.MonthCodeLastDigitYear);
string datecode = bts.api.DateFormatter.Format(kvp.Key, bts.api.DateFormat.MonthCodeLastDigitYear);
string explegs = (temp.Keys.Count > 1) ? string.Concat(sym, datecode, "_", kvp.Value) :
string.Concat(datecode, "_", kvp.Value);
@@ -61,7 +61,7 @@ namespace BCG {
string rv = String.Empty;
foreach (SingleSpreadLeg l in legs)
rv += (rv == String.Empty ? "" : "/") + l.symbol + //BCG.Utilities.Dates.DateCode.getMonthSymbol(l.exp) + (l.exp.Year - 2000);
SecurityFormatter.format_expiration(l.exp);
bts.api.DateFormatter.Format(l.exp, bts.api.DateFormat.DayMonthAbvDiff2000);
return rv;
}
Loaded 100 of 226 files, more files were not shown because too many files have changed in this diff. Show more