Compare commits
31
Commits
fix_tooltips
..
twap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a364ebdbaf | ||
|
|
41bc4f7950 | ||
|
|
963bd15b35 | ||
|
|
282e10cba3 | ||
|
|
fa1b436fb3 | ||
|
|
191518d8bc | ||
|
|
50768750d6 | ||
|
|
450ef7dd56 | ||
|
|
89a4f9264a | ||
|
|
55ade15574 | ||
|
|
36b8b35e47 | ||
|
|
23bb872052 | ||
|
|
bf8df1d396 | ||
|
|
d064af817c | ||
|
|
7b3c4b76bc | ||
|
|
5de431f279 | ||
|
|
7b63d951f0 | ||
|
|
018887980b | ||
|
|
8b4d649bd4 | ||
|
|
441d3c886b | ||
|
|
472e32f558 | ||
|
|
472c9252f9 | ||
|
|
98a9ad3ef2 | ||
|
|
7b237fedea | ||
|
|
7281aa8ff1 | ||
|
|
d915e2f064 | ||
|
|
beb5d855b1 | ||
|
|
120b86aaae | ||
|
|
44eeff98e7 | ||
|
|
dc420a097a | ||
|
|
69ee85dea9 |
No files matched your search
@@ -16,6 +16,7 @@ insert_anchor_links = "right"
|
||||
selected by default
|
||||
- Increased width of login panel to better show login error messages
|
||||
- Added optional 'Maker/Taker' pricing to Spreader algo
|
||||
- Algo buttons in ladder can now be made to deactivate after launching an algo or remain 'sticky'
|
||||
### Internal changes
|
||||
- Made it easier to generate simple UI's for new order types
|
||||
### API Changes
|
||||
|
||||
+1
-1
Submodule docker/linux updated: e13bb5d8df...ce08a5129f.
+1
-1
Submodule externals updated: 67a79263ba...d0e8645b5e.
+2
-2
@@ -10,7 +10,7 @@ using System.Reactive.Disposables;
|
||||
namespace mbts.spark {
|
||||
static class AlgoParamRowsHelper {
|
||||
public static IDisposable connect(AlgoDefinitionVM algo, ObservableAggregateCollection<AlgoParamRowVM> rows, bool include_algo_type_rows) =>
|
||||
algo == null ? null : new CompositeDisposable(algo.observe_algo_root().SubscribeEach(a => {
|
||||
algo == null ? null : new CompositeDisposable(algo.observe_algo_root().OnDispatcher().SubscribeEach(a => {
|
||||
rows.clear_collections();
|
||||
if (a == null)
|
||||
return Disposable.empty;
|
||||
@@ -77,7 +77,7 @@ namespace mbts.spark {
|
||||
include_algo_type_rows ?
|
||||
(ObservableCollection<AlgoParamRowVM>)new ObservableAppendCollection<AlgoParamRowVM>(child_rows, selector_wrapper) :
|
||||
child_rows,
|
||||
s.subscribe_selected_algo().SubscribeEach(a => {
|
||||
s.subscribe_selected_algo().OnDispatcher().SubscribeEach(a => {
|
||||
s.value = a;
|
||||
child_rows.clear_collections();
|
||||
return _wrap_rows(a, selector_wrapper, child_rows, include_algo_type_rows);
|
||||
|
||||
@@ -194,20 +194,27 @@ namespace mbts.spark {
|
||||
readonly bts.persist.algo.AlgoPersistedKey[] _favorite_algos;
|
||||
[ProtoMember(2)]
|
||||
public readonly int column_count;
|
||||
[ProtoMember(3)]
|
||||
readonly bts.persist.algo.AlgoPersistedKey[] _stickied_algos;
|
||||
|
||||
public LadderFavoriteAlgosSettings(AlgoKey[] favorite_algos, int column_count)
|
||||
: this(ArrayHelper.safe_convert(favorite_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted)), column_count) { }
|
||||
public LadderFavoriteAlgosSettings(AlgoKey[] favorite_algos, int column_count, AlgoKey[] stickied_algos)
|
||||
: this(ArrayHelper.safe_convert(favorite_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted)),
|
||||
column_count,
|
||||
ArrayHelper.safe_convert(stickied_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted))) { }
|
||||
|
||||
LadderFavoriteAlgosSettings(bts.persist.algo.AlgoPersistedKey[] favorite_algos, int column_count) {
|
||||
LadderFavoriteAlgosSettings(bts.persist.algo.AlgoPersistedKey[] favorite_algos, int column_count, bts.persist.algo.AlgoPersistedKey[] stickied_algos) {
|
||||
_favorite_algos = favorite_algos;
|
||||
this.column_count = column_count;
|
||||
_stickied_algos = stickied_algos;
|
||||
}
|
||||
|
||||
public IReadOnlyList<AlgoKey> favorite_algos => ArrayHelper.safe_convert(_favorite_algos, k => k.to_algo_key());
|
||||
public IReadOnlyList<AlgoKey> stickied_algos => ArrayHelper.safe_convert(_stickied_algos, k => k.to_algo_key());
|
||||
|
||||
public bool Equals(LadderFavoriteAlgosSettings other) =>
|
||||
column_count == other.column_count &&
|
||||
favorite_algos.SequenceEqual(other.favorite_algos);
|
||||
favorite_algos.SequenceEqual(other.favorite_algos) &&
|
||||
stickied_algos.SequenceEqual(other.stickied_algos);
|
||||
|
||||
public override bool Equals(object obj) =>
|
||||
EqualityComparer.equals_obj(this, obj);
|
||||
@@ -215,7 +222,8 @@ namespace mbts.spark {
|
||||
public override int GetHashCode() =>
|
||||
EqualityComparer.aggregate_hash(
|
||||
column_count,
|
||||
EqualityComparer.aggregate_hash_limited(favorite_algos));
|
||||
EqualityComparer.aggregate_hash_limited(favorite_algos),
|
||||
EqualityComparer.aggregate_hash_limited(stickied_algos));
|
||||
|
||||
public static bool operator ==(LadderFavoriteAlgosSettings a, LadderFavoriteAlgosSettings b) => a.Equals(b);
|
||||
public static bool operator !=(LadderFavoriteAlgosSettings a, LadderFavoriteAlgosSettings b) => !a.Equals(b);
|
||||
@@ -273,7 +281,7 @@ namespace mbts.spark {
|
||||
order_entry_panel_initial_width = _default_order_entry_panel_width;
|
||||
zoom_factor = _default_zoom_factor;
|
||||
use_defaults = true;
|
||||
favorite_algos = new LadderFavoriteAlgosSettings(null, 2);
|
||||
favorite_algos = new LadderFavoriteAlgosSettings(null, 2, null);
|
||||
show_warn_on_cross = _default_show_warn_on_cross;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using ProtoBuf;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reactive.Subjects;
|
||||
@@ -22,6 +23,7 @@ using LadderSettings = mbts.spark.LadderSettings;
|
||||
namespace bts.shell {
|
||||
class LadderWindowFactory : ShellWindowFactory<LadderSaveState> {
|
||||
const string _window_type = "ladder";
|
||||
const int _version_where_stickied_algos_introduced = 2;
|
||||
readonly LadderConfig _ladder_conf;
|
||||
readonly IBus _bus;
|
||||
readonly IWindowManager _wm;
|
||||
@@ -38,7 +40,7 @@ namespace bts.shell {
|
||||
OrdersModel orders_model,
|
||||
MBOService mbo)
|
||||
|
||||
: base(owner, "SparkLadder") {
|
||||
: base(owner, "SparkLadder", 2) {
|
||||
_bus = bus;
|
||||
_wm = wm;
|
||||
_settings_hub = settings_hub;
|
||||
@@ -60,6 +62,16 @@ namespace bts.shell {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override Task<IShellWindow> try_upgrade_state(Stream load_stream, int version) {
|
||||
var state = ProtoBuf.Serializer.DeserializeWithLengthPrefix<LadderSaveState>(load_stream, ProtoBuf.PrefixStyle.Fixed32);
|
||||
if (version < _version_where_stickied_algos_introduced) {
|
||||
// We want to assign any existing favorite algos to stickied algos upon setting upgrade
|
||||
var favorite_algos_array = state.settings.favorite_algos.favorite_algos.ToArray();
|
||||
state.settings.favorite_algos = new LadderFavoriteAlgosSettings(favorite_algos_array, state.settings.favorite_algos.column_count, favorite_algos_array);
|
||||
}
|
||||
return load(state);
|
||||
}
|
||||
|
||||
LadderSaveState _get_state(LadderVM vm, uint id) {
|
||||
LadderSettings s = vm.get_save_state();
|
||||
if (id != 0) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using bts.api;
|
||||
using bts.api.orderman;
|
||||
using bts.collections;
|
||||
using bts.persist.algo;
|
||||
using bts.shell.orderbook;
|
||||
using bts.utils;
|
||||
using mbts.collections;
|
||||
@@ -723,12 +724,15 @@ namespace mbts.spark {
|
||||
readonly IObservableCollection<AlgoDefinitionVM> _algo_definitions;
|
||||
readonly ObservableCollection<FavoriteAlgoItem> _raw_items = new ObservableCollection<FavoriteAlgoItem>();
|
||||
int _column_count = 2;
|
||||
HashSet<AlgoPersistedKey> _sticky_algo_keys;
|
||||
IDisposable _sticky_algos_hook;
|
||||
|
||||
public FavoriteAlgosVM(IObservableCollection<AlgoDefinitionVM> algo_definitions) {
|
||||
_algo_definitions = algo_definitions;
|
||||
items = new ObservableAggregateCollection<FavoriteAlgoItem>(_raw_items, new ObservableCollection<FavoriteAlgoItem> { FavoriteAlgoItem.AddButtonPlaceholderItem });
|
||||
add_item_cmd = new DelegateCommand(() => _raw_items.Add(_item_factory()));
|
||||
remove_item_cmd = new DelegateCommand<FavoriteAlgoItem>(fai => _raw_items.Remove(fai));
|
||||
_dispose = Disposable.Create(() => Disposable.dispose(ref _sticky_algos_hook));
|
||||
}
|
||||
|
||||
public ObservableCollection<FavoriteAlgoItem> items { get; }
|
||||
@@ -745,6 +749,17 @@ namespace mbts.spark {
|
||||
fai.selector.try_select(k);
|
||||
return fai;
|
||||
}));
|
||||
_sticky_algo_keys = new HashSet<AlgoPersistedKey>(value.stickied_algos.Where(k => k.is_persisted).Select(x => new AlgoPersistedKey(x.persisted)));
|
||||
Disposable.replace(ref _sticky_algos_hook,
|
||||
ObservableAutoWrapper.connect_item_hooks(_raw_items, x =>
|
||||
x.selector.subscribe_value().Subscribe(algo => {
|
||||
if (algo != null &&
|
||||
algo.key.is_persisted &&
|
||||
(x.is_sticky = _sticky_algo_keys.Remove(new AlgoPersistedKey(algo.key.persisted))) &&
|
||||
_sticky_algo_keys.Count == 0)
|
||||
//
|
||||
Disposable.dispose(ref _sticky_algos_hook);
|
||||
})));
|
||||
}
|
||||
|
||||
public LadderFavoriteAlgosSettings create() =>
|
||||
@@ -753,7 +768,13 @@ namespace mbts.spark {
|
||||
.Where(k => k.HasValue && k.Value.is_persisted)
|
||||
.Select(k => k.Value)
|
||||
.ToArray(),
|
||||
column_count);
|
||||
column_count,
|
||||
_raw_items
|
||||
.Where(fai => fai.is_sticky)
|
||||
.Select(fai => fai.algo_definition?.key ?? fai.selector.desired_key)
|
||||
.Where(k => k.HasValue && k.Value.is_persisted)
|
||||
.Select(k => k.Value)
|
||||
.ToArray());
|
||||
|
||||
FavoriteAlgoItem _item_factory() =>
|
||||
new FavoriteAlgoItem(_algo_definitions, new ListCollectionView<AlgoDefinitionVM>(_algo_definitions) {
|
||||
@@ -766,6 +787,7 @@ namespace mbts.spark {
|
||||
public static readonly FavoriteAlgoItem AddButtonPlaceholderItem = new _AddButtonPlaceholderItem();
|
||||
|
||||
internal readonly KeyedItemSelector<AlgoDefinitionVM, AlgoKey> selector;
|
||||
bool _is_sticky;
|
||||
|
||||
protected FavoriteAlgoItem() { }
|
||||
|
||||
@@ -776,6 +798,7 @@ namespace mbts.spark {
|
||||
|
||||
public ICollectionView<AlgoDefinitionVM> algo_definitions_view { get; }
|
||||
public AlgoDefinitionVM algo_definition { get => selector.value; set => selector.value = value; }
|
||||
public bool is_sticky { get => _is_sticky; set => Set(ref _is_sticky, value); }
|
||||
|
||||
class _AddButtonPlaceholderItem : FavoriteAlgoItem, ITemplateSelectorKey {
|
||||
public string key => LadderSettingsView.FavoriteAlgoAddButtonTemplateKey;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using bts.api;
|
||||
using bts.api.orderman;
|
||||
using bts.collections;
|
||||
using bts.shell;
|
||||
using bts.spark;
|
||||
using bts.utils;
|
||||
using mbts.co2;
|
||||
using mbts.spark.utilities;
|
||||
using mbts.ui;
|
||||
using mbts.ui.shell;
|
||||
using mbts.utils;
|
||||
@@ -32,6 +34,7 @@ namespace mbts.spark {
|
||||
_show_tif, _show_order_type, _show_size_preset, _show_auto_clear, _show_clear, _show_cancel_buys,
|
||||
_show_cancel_sells, _show_cancel_all, _show_zoom;
|
||||
readonly PropertyAutoWrapper<LadderSettings, Brush> _bid_background, _bid_foreground, _ask_background, _ask_foreground;
|
||||
readonly HashSet<AlgoKey> _sticky_algos = new HashSet<AlgoKey>();
|
||||
double _position, _day_position;
|
||||
bool _show_account_position, _show_day_position;
|
||||
ulong _misc_time = 0;
|
||||
@@ -133,7 +136,7 @@ namespace mbts.spark {
|
||||
//_window_height = backing(nameof(window_height), settings_manager.subscribe_current().OnDispatcher().Select(s => s.zoom_factor), (scale) => scale * 600);
|
||||
//_window_width = backing(nameof(window_width), settings_manager.subscribe_current().OnDispatcher().Select(s => s.zoom_factor), (scale) => scale * 420);
|
||||
position_click_command = new DelegateCommand(() => size_calculator.value = DoubleHelper.safe_convert_to_uint(Math.Abs(_show_day_position ? day_position : position)));
|
||||
send_order_command = new DelegateCommand<(double price, Side? side, MouseButton button)>(send_order);
|
||||
send_order_command = new AsyncCommand<(double price, Side? side, MouseButton button)>(send_order_async);
|
||||
cancel_command = new AsyncCommand<LadderModel.CancelType>(_model.cancel_orders, true);
|
||||
show_book_command = new DelegateCommand(_show_book);
|
||||
show_ticket_command = new DelegateCommand(_show_ticket);
|
||||
@@ -223,7 +226,10 @@ namespace mbts.spark {
|
||||
.SelectManyInSeries(a => _model.order_gateway.on_security_positions(security.Id)
|
||||
.Select(table => table.state.Values.FirstOrDefault(pos => pos.Item2.Account == a, tup => tup.Item2, (bts.api.position.PositionUnitImmutable?)null)));
|
||||
return Disposable.Create(
|
||||
settings.OnDispatcher().Subscribe(s => order_properties_vm.on_favorite_algos(s.favorite_algos)),
|
||||
settings.OnDispatcher().Subscribe(s => {
|
||||
_sticky_algos.SetItems(s.favorite_algos.stickied_algos);
|
||||
order_properties_vm.on_favorite_algos(s.favorite_algos);
|
||||
}),
|
||||
order_properties_vm,
|
||||
position_src.OnDispatcher().Subscribe(pos => {
|
||||
double total, day;
|
||||
@@ -400,20 +406,19 @@ namespace mbts.spark {
|
||||
settings_invalidated?.Invoke();
|
||||
}
|
||||
|
||||
public void send_order((double price, Side? side, MouseButton button) args) {
|
||||
if (order_properties_vm == null || args.button == MouseButton.Middle)
|
||||
return;
|
||||
var size_from_alternate = args.button == MouseButton.Right;
|
||||
if (DoubleHelper.IsNaNOrInfinity(args.price) || !args.side.HasValue || HasErrors || order_properties_vm.HasErrors || (size_from_alternate && current_settings.alternate_order_size == 0)) {
|
||||
return;
|
||||
}
|
||||
if (!size_from_alternate && (!size_calculator.value.HasValue || size_calculator.value.Value == 0)) {
|
||||
size_calculator.flash_error();
|
||||
}
|
||||
else {
|
||||
uint size = size_from_alternate ? current_settings.alternate_order_size : (uint)Math.Abs(size_calculator.value ?? 0);
|
||||
send_order_async(args.side.Value, size, args.price).ignore();
|
||||
public Task send_order_async((double price, Side? side, MouseButton button) args) {
|
||||
if (order_properties_vm != null && args.button != MouseButton.Middle) {
|
||||
var size_from_alternate = args.button == MouseButton.Right;
|
||||
if (!DoubleHelper.IsNaNOrInfinity(args.price) && args.side.HasValue && !HasErrors && !order_properties_vm.HasErrors && (!size_from_alternate || current_settings.alternate_order_size > 0)) {
|
||||
if (!size_from_alternate && (!size_calculator.value.HasValue || size_calculator.value.Value == 0)) {
|
||||
size_calculator.flash_error();
|
||||
} else {
|
||||
uint size = size_from_alternate ? current_settings.alternate_order_size : (uint)Math.Abs(size_calculator.value ?? 0);
|
||||
return send_order_async(args.side.Value, size, args.price);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task send_order_async(Side side, uint size, double price) {
|
||||
@@ -433,6 +438,13 @@ namespace mbts.spark {
|
||||
await _model.order_gateway.send_order(order, price, size);
|
||||
if (auto_clear)
|
||||
size_calculator.value = 0;
|
||||
var fav_algo = order_properties_vm.selected_favorite_algo_definition;
|
||||
if (fav_algo != null && !_sticky_algos.Contains(fav_algo.key) && !order_properties_vm.try_pop_selected_algo_definition()) {
|
||||
var key = new AlgoKey(OrderDataHelper.get_default_algo(OrderDataHelper.get_algo_format(security.ContractCase)));
|
||||
if (order_properties_vm.try_get_algo_definition(key, out var r)) {
|
||||
order_properties_vm.selected_algo_definition = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _update_header() {
|
||||
|
||||
@@ -805,6 +805,7 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="c0"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="c1"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Command="{Binding DataContext.remove_item_cmd, RelativeSource={RelativeSource AncestorType=ItemsControl}}" CommandParameter="{Binding}" Style="{StaticResource RoundCloseButton}"/>
|
||||
<ComboBox Grid.Column="1" ItemsSource="{Binding algo_definitions_view}" SelectedItem="{Binding algo_definition}">
|
||||
@@ -814,6 +815,7 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<CheckBox Grid.Column="2" VerticalAlignment="Center" VerticalContentAlignment="Center" IsChecked="{Binding is_sticky}"> Stay Enabled?</CheckBox>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</u:KeyedTemplateSelector.Default>
|
||||
@@ -823,6 +825,7 @@
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="c0"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="c1"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="1" HorizontalAlignment="Stretch" Command="{Binding DataContext.add_item_cmd, RelativeSource={RelativeSource AncestorType=ItemsControl}}">Add</Button>
|
||||
</Grid>
|
||||
|
||||
@@ -631,25 +631,54 @@ namespace mbts.spark.utilities {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
static CustomOrderDefinition.CustomOneofCase[] algo_config(
|
||||
Func<bts.config.AlgoPermissions, List<string>> selector)
|
||||
{
|
||||
var conf = mbts.config.Configuration.get<bts.config.AlgoPermissions>();
|
||||
return selector(conf).Select(x =>
|
||||
{
|
||||
return (CustomOrderDefinition.CustomOneofCase)System.Enum.Parse(typeof(CustomOrderDefinition.CustomOneofCase), x, true);
|
||||
}).ToArray();
|
||||
}
|
||||
|
||||
public static readonly CustomOrderDefinition.CustomOneofCase[]
|
||||
|
||||
// exchange_order_types are the types which can be submitted on an exchange security
|
||||
exchange_order_types = algo_config(x => x.exchange_order_types),
|
||||
spreader_order_types = algo_config(x => x.spreader_order_types),
|
||||
attachable_order_types = algo_config(x => x.attachable_order_types),
|
||||
outright_order_types = algo_config(x => x.outright_order_types);
|
||||
|
||||
exchange_order_types = new[] {
|
||||
CustomOrderDefinition.CustomOneofCase.Market,
|
||||
CustomOrderDefinition.CustomOneofCase.Limit,
|
||||
CustomOrderDefinition.CustomOneofCase.Stop,
|
||||
CustomOrderDefinition.CustomOneofCase.StopLimit,
|
||||
CustomOrderDefinition.CustomOneofCase.GlbxIceberg,
|
||||
CustomOrderDefinition.CustomOneofCase.Iceberg,
|
||||
CustomOrderDefinition.CustomOneofCase.Lean,
|
||||
CustomOrderDefinition.CustomOneofCase.Join,
|
||||
CustomOrderDefinition.CustomOneofCase.Cover,
|
||||
CustomOrderDefinition.CustomOneofCase.Top,
|
||||
CustomOrderDefinition.CustomOneofCase.Offset,
|
||||
CustomOrderDefinition.CustomOneofCase.Splitter,
|
||||
CustomOrderDefinition.CustomOneofCase.Scratch,
|
||||
CustomOrderDefinition.CustomOneofCase.Prorata,
|
||||
},
|
||||
spreader_order_types = new[] {
|
||||
CustomOrderDefinition.CustomOneofCase.Spreader,
|
||||
CustomOrderDefinition.CustomOneofCase.Iceberg,
|
||||
CustomOrderDefinition.CustomOneofCase.Lean,
|
||||
CustomOrderDefinition.CustomOneofCase.Join,
|
||||
CustomOrderDefinition.CustomOneofCase.Cover,
|
||||
CustomOrderDefinition.CustomOneofCase.Top,
|
||||
CustomOrderDefinition.CustomOneofCase.Splitter,
|
||||
CustomOrderDefinition.CustomOneofCase.Scratch,
|
||||
CustomOrderDefinition.CustomOneofCase.Prorata,
|
||||
},
|
||||
attachable_order_types = new[] {
|
||||
CustomOrderDefinition.CustomOneofCase.Iceberg,
|
||||
CustomOrderDefinition.CustomOneofCase.Lean,
|
||||
CustomOrderDefinition.CustomOneofCase.Join,
|
||||
CustomOrderDefinition.CustomOneofCase.Cover,
|
||||
CustomOrderDefinition.CustomOneofCase.Top,
|
||||
CustomOrderDefinition.CustomOneofCase.Offset,
|
||||
CustomOrderDefinition.CustomOneofCase.Scratch,
|
||||
CustomOrderDefinition.CustomOneofCase.Prorata,
|
||||
},
|
||||
outright_order_types = new[] {
|
||||
CustomOrderDefinition.CustomOneofCase.Market,
|
||||
CustomOrderDefinition.CustomOneofCase.Limit,
|
||||
CustomOrderDefinition.CustomOneofCase.Stop,
|
||||
CustomOrderDefinition.CustomOneofCase.StopLimit,
|
||||
CustomOrderDefinition.CustomOneofCase.GlbxIceberg,
|
||||
};
|
||||
public static readonly CustomOrderDefinition.CustomOneofCase[] all_order_types = exchange_order_types.Union(spreader_order_types).ToArray();
|
||||
|
||||
public static void copy_values(CustomOrderDefinitionImmutable source, ref CustomOrderDefinition target) =>
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace mbts.spark {
|
||||
readonly ListCollectionView<AlgoDefinitionVM> _algo_definitions_view, _favorite_algo_definitions_view;
|
||||
readonly TableUpdateBuffer<AlgoData, AlgoKey> _definitions_buffer = new TableUpdateBuffer<AlgoData, AlgoKey>(d => d.key);
|
||||
readonly ObservableAggregateCollection<AlgoParamRowVM> _algo_param_rows = new ObservableAggregateCollection<AlgoParamRowVM>();
|
||||
readonly AlgoDefinitionVM the_anchor_algo_def_vm;
|
||||
IReadOnlyDictionary<AlgoKey, AlgoDefinitionMetadata> _algo_metadata = DictionaryHelper.empty<AlgoKey, AlgoDefinitionMetadata>();
|
||||
IReadOnlyDictionary<AlgoKey, int> _favorite_algos_index = DictionaryHelper.empty<AlgoKey, int>();
|
||||
IDisposable _algo_param_rows_hook;
|
||||
@@ -68,6 +69,7 @@ namespace mbts.spark {
|
||||
|
||||
public OrderPropertiesEditorVM(OrdersModel model, IObservable<SecurityMD> security_md_source, IObservable<InlineOrderProperties> order_properties) {
|
||||
_model = model;
|
||||
the_anchor_algo_def_vm = AlgoDefinitionVM.create(_model, OrderDataHelper.Defaults.AlgoData(CustomOrderDefinition.CustomOneofCase.Limit));
|
||||
var security_source = security_md_source.Select(smd => smd.security);
|
||||
_security = backing(nameof(security), security_source, SecurityDataHelper.Defaults.SecurityImmutable);
|
||||
security_source = _security.observe_current(true);
|
||||
@@ -237,11 +239,15 @@ namespace mbts.spark {
|
||||
|
||||
void _selected_algo_definition_Changed(AlgoDefinitionVM old_value, AlgoDefinitionVM new_value, SelectionReason reason) {
|
||||
Disposable.dispose(ref _algo_param_rows_hook);
|
||||
if (old_value != null)
|
||||
// Taha feels that we should always revert to a Limit order either when the user explicity unchecks a sticky button
|
||||
// or when a non-sticky button is pressed. Rather than completely remove the stack at this time (b/c it may be come
|
||||
// back in the future), let's just always push a specfic def_vm.key onto it [Limit] ;)
|
||||
//_selected_algo_stack.Push(old_value.key);
|
||||
_selected_algo_stack.Push(the_anchor_algo_def_vm.key);
|
||||
if (new_value != null) {
|
||||
if (use_algo_param_grid)
|
||||
_algo_param_rows_hook = _connect_algo_param_rows(new_value, _algo_param_rows);
|
||||
if (reason != SelectionReason.Explicit)
|
||||
_selected_algo_stack.Push(new_value.key);
|
||||
}
|
||||
if (open_algo_popup_on_select) {
|
||||
if (reason == SelectionReason.UserSelectedNewValue && new_value?.algo_root is IAlgoVM ar && ar.can_expand)
|
||||
@@ -277,6 +283,18 @@ namespace mbts.spark {
|
||||
get => _selected_algo_definition.selected_item;
|
||||
set => _selected_algo_definition.selected_item = value;
|
||||
}
|
||||
|
||||
public bool try_get_algo_definition(AlgoKey a, out AlgoDefinitionVM result) =>
|
||||
_algo_definitions.TryGetValue(a, out result);
|
||||
|
||||
public bool try_pop_selected_algo_definition() {
|
||||
if (_selected_algo_stack.TryPop(out AlgoKey k) && _algo_definitions.TryGetValue(k, out AlgoDefinitionVM vm)) {
|
||||
_selected_algo_definition.select_explicit(vm);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public AlgoDefinitionVM selected_favorite_algo_definition {
|
||||
get => selected_algo_definition?.is_favorite ?? false ? selected_algo_definition : null;
|
||||
set {
|
||||
@@ -353,6 +371,7 @@ namespace mbts.spark {
|
||||
d.favorite_index = _get_favorite_algo_index(d.key);
|
||||
}
|
||||
favorite_algos_column_count = value.column_count;
|
||||
RaisePropertyChanged(nameof(selected_favorite_algo_definition));
|
||||
}
|
||||
|
||||
static IDisposable _connect_algo_param_rows(AlgoDefinitionVM def, ObservableAggregateCollection<AlgoParamRowVM> rows) =>
|
||||
@@ -371,4 +390,4 @@ namespace mbts.spark {
|
||||
algo_definitions_view.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,14 @@ namespace bts.shell {
|
||||
Disposable.dispose(ref _dispose);
|
||||
}
|
||||
public abstract Task<IShellWindow> load(T state);
|
||||
protected virtual Task<IShellWindow> try_upgrade_state(Stream load_stream, int version) => null;
|
||||
|
||||
public Task<IShellWindow> load_window(Stream load_stream, int version) {
|
||||
if (version == this.version) {
|
||||
var t = ProtoBuf.Serializer.DeserializeWithLengthPrefix<T>(load_stream, ProtoBuf.PrefixStyle.Fixed32);
|
||||
return load(t);
|
||||
}
|
||||
return null;
|
||||
return try_upgrade_state(load_stream, version);
|
||||
}
|
||||
public void save(T data, Stream output) {
|
||||
var header = new ShellSerializationHeader() {
|
||||
|
||||
@@ -236,12 +236,12 @@ namespace mbts.ui {
|
||||
throw new NotImplementedException("This ICommand does not implement IRaiseCanExecuteChanged");
|
||||
}
|
||||
|
||||
public static async Task ExecuteAsync(this ICommand command, object parameter) {
|
||||
public static Task ExecuteAsync(this ICommand command, object parameter) {
|
||||
ExceptionAssert.Argument.NotNull(command, nameof(command));
|
||||
if (command is IAsyncCommand acmd)
|
||||
await acmd.Execute(parameter);
|
||||
return acmd.Execute(parameter);
|
||||
else
|
||||
await Task.Run(() => command.Execute(parameter));
|
||||
return Task.Run(() => command.Execute(parameter));
|
||||
}
|
||||
|
||||
public static void TryExecuteIfCan(this ICommand command, object parameter) {
|
||||
|
||||
@@ -136,8 +136,8 @@ namespace mbts.spark {
|
||||
var skip_local = profiles.WrapSkip(1);
|
||||
var skip_local_wrapper = skip_local.WrapSelector(
|
||||
p => new SettingsProfile<T>(p.id, p.name, p.value.create(), p.security_criteria),
|
||||
ns => new ProfileVM(ns.id, vm_factory(ns.value), ns.name, ns.security_criteria));
|
||||
profiles.Add(_local_profile = new ProfileVM(0, vm_factory(init), "Custom", template_key: ShellSettingsDialog.LocalProfileItemTemplateKey));
|
||||
ns => new ProfileVM(ns.id, vm_factory(ns.value), ns.name, ns.security_criteria, target_value: ns.value));
|
||||
profiles.Add(_local_profile = new ProfileVM(0, vm_factory(init), "Custom", template_key: ShellSettingsDialog.LocalProfileItemTemplateKey, target_value: init));
|
||||
_selected_profile = backing(nameof(selected_profile), _local_profile);
|
||||
// dialog skirt items
|
||||
_apply_item = new DialogSkirtItem("Apply", new DelegateCommand(apply));
|
||||
@@ -325,26 +325,37 @@ namespace mbts.spark {
|
||||
//
|
||||
SecurityCriteria _security_criteria;
|
||||
SettingsProfile<T> _committed, _last_result;
|
||||
T _target_value;
|
||||
string _name, _template_key;
|
||||
bool _is_selected;
|
||||
IDisposable _dispose;
|
||||
|
||||
public ProfileVM(uint id, TVM value, string name, SecurityCriteria security_criteria = null, string template_key = null) {
|
||||
public ProfileVM(uint id, TVM value, string name, SecurityCriteria security_criteria = null, string template_key = null, T target_value = null) {
|
||||
this.id = id;
|
||||
this.value = value;
|
||||
_name = name;
|
||||
_security_criteria = security_criteria;
|
||||
_template_key = template_key;
|
||||
_target_value = target_value;
|
||||
_committed = _last_result = create();
|
||||
_is_dirty = backing(nameof(is_dirty), () => !_last_result.Equals(_committed));
|
||||
_refresh_is_dirty = new DeferrableActionWrapper(_is_dirty.refresh);
|
||||
var sub = value.Subscribe(v => {
|
||||
_last_result = _last_result.with(value: v);
|
||||
_refresh_is_dirty.execute();
|
||||
_on_value_changed();
|
||||
});
|
||||
_dispose = value is IDisposable d ? Disposable.Create(sub, d) : sub;
|
||||
}
|
||||
|
||||
void _on_value_changed() {
|
||||
if (_target_value != null && is_dirty && _last_result.value.Equals(_target_value)) {
|
||||
_target_value = null;
|
||||
_committed = _last_result;
|
||||
_refresh_is_dirty.execute();
|
||||
}
|
||||
}
|
||||
|
||||
public uint id { get; }
|
||||
public TVM value { get; }
|
||||
public string name {
|
||||
@@ -380,21 +391,26 @@ namespace mbts.spark {
|
||||
/// assign directly to <see cref="_last_result"/>, to capture props that aren't visible in the dialog (i.e., props that are manipulated in the main window)
|
||||
_last_result = data;
|
||||
}
|
||||
_on_value_changed();
|
||||
}
|
||||
|
||||
public void load_value_from(T value) {
|
||||
using (_refresh_is_dirty.defer_execution())
|
||||
this.value.load_from(value);
|
||||
_on_value_changed();
|
||||
}
|
||||
|
||||
public void commit(SettingsProfile<T> data) {
|
||||
using (_refresh_is_dirty.defer_execution())
|
||||
_load_from(_committed = data);
|
||||
_on_value_changed();
|
||||
}
|
||||
|
||||
public void commit_current() {
|
||||
_committed = _last_result;
|
||||
_target_value = _committed.value;
|
||||
_refresh_is_dirty.execute();
|
||||
_on_value_changed();
|
||||
}
|
||||
|
||||
public void revert() {
|
||||
@@ -402,6 +418,7 @@ namespace mbts.spark {
|
||||
_load_from(_committed);
|
||||
_last_result = _committed;
|
||||
}
|
||||
_on_value_changed();
|
||||
}
|
||||
|
||||
public IObservable<bool> subscribe_is_dirty() => _is_dirty.observe_current(true);
|
||||
@@ -414,6 +431,7 @@ namespace mbts.spark {
|
||||
public override string ToString() => _name;
|
||||
|
||||
void _load_from(SettingsProfile<T> data) {
|
||||
_target_value = data.value;
|
||||
name = data.name;
|
||||
security_criteria = data.security_criteria;
|
||||
value.load_from(data.value);
|
||||
|
||||
@@ -1 +1 @@
|
||||
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/HistoricalDataService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/UI.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/AuthSessionManager.cpp;utils/AuthToken.cpp;utils/Dispatcher.cpp;utils/GrowableSPSCQueue.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/crypto/CipherType.cpp;utils/crypto/CryptoInit.cpp;utils/crypto/Digest.cpp;utils/crypto/KeyCodeHelper.cpp;utils/cryLine truncated
|
||||
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/AuthSessionManager.cpp;utils/AuthToken.cpp;utils/Dispatcher.cpp;utils/GrowableSPSCQueue.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/crypto/CipherType.cpp;utils/crypto/CryptoInit.cpp;utils/crypto/Digest.cpp;utils/crypto/KeyCodeHelper.cpp;utils/crypto/PasswordCallback.cpp;utils/crypto/PrivateKey.cpp;utils/cryptoLine truncated
|
||||
@@ -141,3 +141,4 @@ if (WIN32)
|
||||
include(${CMAKE_SOURCE_DIR}/tools/vs_filters.cmake)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
syntax="proto3";
|
||||
package bts.history;
|
||||
option csharp_namespace="bts.history";
|
||||
option cc_enable_arenas=true;
|
||||
import "lib/api/apioptions.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
|
||||
message Slice {
|
||||
google.protobuf.Timestamp begin = 10;
|
||||
google.protobuf.Timestamp end = 20;
|
||||
uint32 buy_volume = 30;
|
||||
double avg_buy_price = 40;
|
||||
uint32 sell_volume = 50;
|
||||
double avg_sell_price = 60;
|
||||
}
|
||||
message Slices {
|
||||
repeated Slice slice_vec = 10;
|
||||
}
|
||||
message SliceDistribution {
|
||||
google.protobuf.Timestamp begin = 10;
|
||||
google.protobuf.Timestamp end = 20;
|
||||
double volume_mean = 30;
|
||||
double volume_variance = 40;
|
||||
double price_mean = 50;
|
||||
double price_variance = 60;
|
||||
}
|
||||
message TradingDistribution {
|
||||
double volume_mean = 10;
|
||||
double volume_variance = 20;
|
||||
double volume_skewness = 30;
|
||||
double price_mean = 40;
|
||||
double price_variance = 50;
|
||||
double price_skewness = 60;
|
||||
repeated SliceDistribution slices = 100;
|
||||
}
|
||||
|
||||
message SlicesQuery {
|
||||
string security_desc = 10;
|
||||
google.protobuf.Timestamp begin = 20;
|
||||
google.protobuf.Timestamp end = 30;
|
||||
google.protobuf.Duration dt = 40;
|
||||
}
|
||||
message TradingDistributionQuery {
|
||||
string security_desc = 10;
|
||||
google.protobuf.Timestamp begin = 20;
|
||||
google.protobuf.Timestamp end = 30;
|
||||
google.protobuf.Duration dt = 40;
|
||||
}
|
||||
|
||||
service HistoricalDataService {
|
||||
rpc get_trading_slices(SlicesQuery) returns (Slices);
|
||||
rpc get_trading_distribution (TradingDistributionQuery) returns (TradingDistribution);
|
||||
}
|
||||
@@ -105,11 +105,6 @@ message CustomOrderDefinition
|
||||
ScratchOrderDefinition scratch = 31;
|
||||
ProRataOrderDefinition prorata = 32;
|
||||
|
||||
TWAPOrderDefinition twap = 100;
|
||||
VWAPOrderDefinition vwap = 101;
|
||||
POVOrderDefinition pov = 102;
|
||||
ArrivalPriceOrderDefinition arrival = 103;
|
||||
|
||||
DynamicOrderDefinition dynamic = 1000;
|
||||
}
|
||||
}
|
||||
@@ -235,89 +230,6 @@ message ProRataOrderDefinition {
|
||||
CustomOrderDefinition hedge = 20;
|
||||
CustomOrderDefinition overfill_hedge = 30;
|
||||
}
|
||||
|
||||
message OrderDuration {
|
||||
//default = 0, when to start the order, 0 = immediately
|
||||
google.protobuf.Timestamp start = 10;
|
||||
oneof end
|
||||
{
|
||||
//when to conclude
|
||||
google.protobuf.Timestamp end_timestamp = 20;
|
||||
//alternative to end_time, minutes from start time at which to stop
|
||||
uint32 duration_in_minutes = 30;
|
||||
}
|
||||
//default = 60
|
||||
uint32 discretization_interval_in_seconds = 40;
|
||||
// default = 1, time in periods which to let unexecuted size remain
|
||||
// 0 means unexecuted size must be resolved (paid up) by end of initial period-- this means orders can only work within their period
|
||||
// 1 means unexecuted size must be resolved (paid up) by end of next period-- this establishes two tracks: 'tactical' and 'aggressive'
|
||||
// orders start in the tactical track and are moved to the aggressive once they work beyond their slippage thresh
|
||||
// 2...etc
|
||||
uint32 tactical_schedule_slippage = 50;
|
||||
}
|
||||
message OrderAggression {
|
||||
// default = 0.0, 0.0 - 99.99 be no more than X% of the market, 0.0 means no cap
|
||||
double max_participation_pct = 10;
|
||||
// default = 0.0, price at which you will take liquidity regardless of other parameters, 0.0 means there is no iwouldprice
|
||||
double i_would_price = 20;
|
||||
// default = 0.0, risk neutral, -1.0 to 1.0. nondimensional parameter. -1 is completely risk averse, 1 is risk seeking
|
||||
// this has the net effect of tilting Arrival and VWAP schedules to do more earlier the more negative the parameter
|
||||
// Constant * lambda in Almgren 2000; Konishi 2002
|
||||
double risk_threshold = 30;
|
||||
}
|
||||
message VolumeDistribution {
|
||||
// default = 20, historical volume distribution time horizon
|
||||
uint32 volume_time_horizon_days = 10;
|
||||
|
||||
// default = 0.0 means use historical mean, another value overrides the computed volume mean
|
||||
double volume_mean_override = 15;
|
||||
// default = 0.0 means use historical variance, another value overrides the computed volume variance
|
||||
double volume_variance_override = 20;
|
||||
}
|
||||
message PriceDistribution {
|
||||
// default = 5 biz, 7 cal (weekly), historical price distribution time horizon
|
||||
uint32 price_time_horizon_days = 10;
|
||||
|
||||
// default = 0.0 means use historical mean, another value overrides the computed price mean
|
||||
double price_mean_override = 15;
|
||||
// default = 0.0 means use historical variance, another value overrides the computed price variance
|
||||
double price_variance_override = 20;
|
||||
}
|
||||
|
||||
message TWAPOrderDefinition {
|
||||
OrderDuration duration = 10;
|
||||
OrderAggression aggression = 20;
|
||||
|
||||
CustomOrderDefinition tactical_child = 200;
|
||||
CustomOrderDefinition aggressive_child = 210;
|
||||
}
|
||||
message VWAPOrderDefinition {
|
||||
OrderDuration duration = 10;
|
||||
OrderAggression aggression = 20;
|
||||
VolumeDistribution volume_distribution = 30;
|
||||
PriceDistribution price_distribution = 40;
|
||||
|
||||
CustomOrderDefinition tactical_child = 200;
|
||||
CustomOrderDefinition aggressive_child = 210;
|
||||
}
|
||||
message POVOrderDefinition {
|
||||
double min_participation_pct = 10;
|
||||
OrderDuration duration = 20;
|
||||
OrderAggression aggression = 30;
|
||||
|
||||
CustomOrderDefinition tactical_child = 200;
|
||||
CustomOrderDefinition aggressive_child = 210;
|
||||
}
|
||||
message ArrivalPriceOrderDefinition {
|
||||
OrderDuration duration = 10;
|
||||
OrderAggression aggression = 20;
|
||||
VolumeDistribution volume_distribution = 30;
|
||||
PriceDistribution price_distribution = 40;
|
||||
|
||||
CustomOrderDefinition tactical_child = 200;
|
||||
CustomOrderDefinition aggressive_child = 210;
|
||||
}
|
||||
|
||||
message DynamicOrderDefinition {
|
||||
string dynamic_order_type = 1;
|
||||
map<string, DynamicOrderParam> order_params = 2;
|
||||
@@ -374,11 +286,6 @@ message OrderState {
|
||||
ScratchOrderState scratch = 32;
|
||||
ProRataOrderState prorata = 33;
|
||||
|
||||
TWAPOrderState twap = 100;
|
||||
VWAPOrderState vwap = 101;
|
||||
POVOrderState pov = 102;
|
||||
ArrivalPriceOrderState arrival = 103;
|
||||
|
||||
DynamicOrderState dynamic = 255; // do not use anything bigger than 255, or things will break
|
||||
}
|
||||
}
|
||||
@@ -459,10 +366,6 @@ message ProRataOrderState {}
|
||||
message DynamicOrderState {}
|
||||
message QueueHolderState {}
|
||||
message SplitterOrderState {}
|
||||
message TWAPOrderState {}
|
||||
message VWAPOrderState {}
|
||||
message POVOrderState {}
|
||||
message ArrivalPriceOrderState {}
|
||||
|
||||
enum OrderStatus {
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
AlgoPermissions {
|
||||
value {
|
||||
exchange_order_types: 'Market'
|
||||
exchange_order_types: 'Limit'
|
||||
exchange_order_types: 'Stop'
|
||||
exchange_order_types: 'StopLimit'
|
||||
exchange_order_types: 'GlbxIceberg'
|
||||
exchange_order_types: 'Iceberg'
|
||||
exchange_order_types: 'Lean'
|
||||
exchange_order_types: 'Join'
|
||||
exchange_order_types: 'Cover'
|
||||
exchange_order_types: 'Top'
|
||||
exchange_order_types: 'Offset'
|
||||
exchange_order_types: 'Splitter'
|
||||
exchange_order_types: 'Scratch'
|
||||
exchange_order_types: 'Prorata'
|
||||
exchange_order_types: 'Twap'
|
||||
|
||||
spreader_order_types: 'Spreader'
|
||||
spreader_order_types: 'Iceberg'
|
||||
spreader_order_types: 'Lean'
|
||||
spreader_order_types: 'Join'
|
||||
spreader_order_types: 'Cover'
|
||||
spreader_order_types: 'Top'
|
||||
spreader_order_types: 'Splitter'
|
||||
spreader_order_types: 'Scratch'
|
||||
spreader_order_types: 'Prorata'
|
||||
|
||||
attachable_order_types: 'Iceberg'
|
||||
attachable_order_types: 'Lean'
|
||||
attachable_order_types: 'Join'
|
||||
attachable_order_types: 'Cover'
|
||||
attachable_order_types: 'Top'
|
||||
attachable_order_types: 'Offset'
|
||||
attachable_order_types: 'Scratch'
|
||||
attachable_order_types: 'Prorata'
|
||||
attachable_order_types: 'Twap'
|
||||
|
||||
outright_order_types: 'Market'
|
||||
outright_order_types: 'Limit'
|
||||
outright_order_types: 'Stop'
|
||||
outright_order_types: 'StopLimit'
|
||||
outright_order_types: 'GlbxIceberg'
|
||||
}
|
||||
}
|
||||
@@ -90,8 +90,6 @@ CppConfig
|
||||
cpp_entry { key: "8D" value: 1000 }
|
||||
cpp_entry { key: "8W" value: 1000 }
|
||||
cpp_entry { key: "8XN" value: 2500 }
|
||||
cpp_entry { key: "8ZN" value: 2500 }
|
||||
cpp_entry { key: "9FN" value: 2500 }
|
||||
cpp_entry { key: "9Q" value: 1000 }
|
||||
cpp_entry { key: "A0D" value: 100 }
|
||||
cpp_entry { key: "A0F" value: 100 }
|
||||
@@ -163,6 +161,7 @@ CppConfig
|
||||
cpp_entry { key: "AAW" value: 42000 }
|
||||
cpp_entry { key: "AB3" value: 80 }
|
||||
cpp_entry { key: "AB7" value: 1000 }
|
||||
cpp_entry { key: "ABF" value: 100 }
|
||||
cpp_entry { key: "ABH" value: 42000 }
|
||||
cpp_entry { key: "ABI" value: 1000 }
|
||||
cpp_entry { key: "ABS" value: 1000 }
|
||||
@@ -170,6 +169,7 @@ CppConfig
|
||||
cpp_entry { key: "ABX" value: 1000 }
|
||||
cpp_entry { key: "ABY" value: 1000 }
|
||||
cpp_entry { key: "AC0" value: 42000 }
|
||||
cpp_entry { key: "ACB" value: 1000 }
|
||||
cpp_entry { key: "ACD" value: 200000 }
|
||||
cpp_entry { key: "ACM" value: 1000 }
|
||||
cpp_entry { key: "ACT" value: 1000 }
|
||||
@@ -183,7 +183,7 @@ CppConfig
|
||||
cpp_entry { key: "AE5" value: 1000 }
|
||||
cpp_entry { key: "AE8" value: 5 }
|
||||
cpp_entry { key: "AE9" value: 80 }
|
||||
cpp_entry { key: "AEJ" value: 960 }
|
||||
cpp_entry { key: "AEB" value: 1000 }
|
||||
cpp_entry { key: "AEP" value: 25 }
|
||||
cpp_entry { key: "AET" value: 1000 }
|
||||
cpp_entry { key: "AEZ" value: 42000 }
|
||||
@@ -222,7 +222,6 @@ CppConfig
|
||||
cpp_entry { key: "AJB" value: 1000 }
|
||||
cpp_entry { key: "AJJ" value: 5 }
|
||||
cpp_entry { key: "AJL" value: 42000 }
|
||||
cpp_entry { key: "AJP" value: 960 }
|
||||
cpp_entry { key: "AJR" value: 1000 }
|
||||
cpp_entry { key: "AJS" value: 42000 }
|
||||
cpp_entry { key: "AJU" value: 42000 }
|
||||
@@ -346,7 +345,6 @@ CppConfig
|
||||
cpp_entry { key: "BCF" value: 50 }
|
||||
cpp_entry { key: "BCH" value: 50 }
|
||||
cpp_entry { key: "BDB" value: 1000 }
|
||||
cpp_entry { key: "BDI" value: 100 }
|
||||
cpp_entry { key: "BDS" value: 1000 }
|
||||
cpp_entry { key: "BFR" value: 100 }
|
||||
cpp_entry { key: "BG" value: 1000 }
|
||||
@@ -357,13 +355,12 @@ CppConfig
|
||||
cpp_entry { key: "BOO" value: 6350 }
|
||||
cpp_entry { key: "BOS" value: 250 }
|
||||
cpp_entry { key: "BR7" value: 1000 }
|
||||
cpp_entry { key: "BSW" value: 136 }
|
||||
cpp_entry { key: "BSF" value: 25 }
|
||||
cpp_entry { key: "BTC" value: 5 }
|
||||
cpp_entry { key: "BTT" value: 50 }
|
||||
cpp_entry { key: "BUB" value: 1000 }
|
||||
cpp_entry { key: "BUC" value: 42000 }
|
||||
cpp_entry { key: "BUS" value: 20 }
|
||||
cpp_entry { key: "BUW" value: 20 }
|
||||
cpp_entry { key: "BWF" value: 50 }
|
||||
cpp_entry { key: "BWH" value: 50 }
|
||||
cpp_entry { key: "BZ" value: 1000 }
|
||||
@@ -394,6 +391,7 @@ CppConfig
|
||||
cpp_entry { key: "CFB" value: 1000 }
|
||||
cpp_entry { key: "CFC" value: 1000 }
|
||||
cpp_entry { key: "CGB" value: 42000 }
|
||||
cpp_entry { key: "CHB" value: 1000 }
|
||||
cpp_entry { key: "CHI" value: 250 }
|
||||
cpp_entry { key: "CHL" value: 100000 }
|
||||
cpp_entry { key: "CHP" value: 50000000 }
|
||||
@@ -406,9 +404,11 @@ CppConfig
|
||||
cpp_entry { key: "CL" value: 1000 }
|
||||
cpp_entry { key: "CL1" value: 1000 }
|
||||
cpp_entry { key: "CL2" value: 1000 }
|
||||
cpp_entry { key: "CLD" value: 1000 }
|
||||
cpp_entry { key: "CLL" value: 1000 }
|
||||
cpp_entry { key: "CLS" value: 1000 }
|
||||
cpp_entry { key: "CLT" value: 1000 }
|
||||
cpp_entry { key: "CMB" value: 1000 }
|
||||
cpp_entry { key: "CMF" value: 1000 }
|
||||
cpp_entry { key: "CNH" value: 100000 }
|
||||
cpp_entry { key: "COL" value: 80 }
|
||||
@@ -431,7 +431,6 @@ CppConfig
|
||||
cpp_entry { key: "CUS" value: 250 }
|
||||
cpp_entry { key: "CY" value: 1000 }
|
||||
cpp_entry { key: "CZK" value: 4000000 }
|
||||
cpp_entry { key: "CZN" value: 2500 }
|
||||
cpp_entry { key: "D0" value: 20 }
|
||||
cpp_entry { key: "D0X" value: 20 }
|
||||
cpp_entry { key: "D0Z" value: 20 }
|
||||
@@ -461,9 +460,9 @@ CppConfig
|
||||
cpp_entry { key: "DDO" value: 1000 }
|
||||
cpp_entry { key: "DEB" value: 744 }
|
||||
cpp_entry { key: "DEN" value: 250 }
|
||||
cpp_entry { key: "DEP" value: 252 }
|
||||
cpp_entry { key: "DEP" value: 264 }
|
||||
cpp_entry { key: "DFL" value: 100 }
|
||||
cpp_entry { key: "DFT" value: 100 }
|
||||
cpp_entry { key: "DFN" value: 100 }
|
||||
cpp_entry { key: "DG2" value: 100 }
|
||||
cpp_entry { key: "DG3" value: 100 }
|
||||
cpp_entry { key: "DGH" value: 1000 }
|
||||
@@ -472,7 +471,6 @@ CppConfig
|
||||
cpp_entry { key: "DGT" value: 100 }
|
||||
cpp_entry { key: "DHA" value: 80 }
|
||||
cpp_entry { key: "DHI" value: 1000 }
|
||||
cpp_entry { key: "DIH" value: 2500 }
|
||||
cpp_entry { key: "DJR" value: 100 }
|
||||
cpp_entry { key: "DKR" value: 1000 }
|
||||
cpp_entry { key: "DMB" value: 100 }
|
||||
@@ -503,7 +501,6 @@ CppConfig
|
||||
cpp_entry { key: "EAC" value: 80 }
|
||||
cpp_entry { key: "EAD" value: 125000 }
|
||||
cpp_entry { key: "EAE" value: 5 }
|
||||
cpp_entry { key: "EAF" value: 1000 }
|
||||
cpp_entry { key: "EAW" value: 80 }
|
||||
cpp_entry { key: "EBE" value: 1000 }
|
||||
cpp_entry { key: "ECD" value: 125000 }
|
||||
@@ -542,7 +539,6 @@ CppConfig
|
||||
cpp_entry { key: "EST" value: 50 }
|
||||
cpp_entry { key: "ETT" value: 100 }
|
||||
cpp_entry { key: "EUB" value: 80 }
|
||||
cpp_entry { key: "EUL" value: 1000 }
|
||||
cpp_entry { key: "EURADC" value: 1 }
|
||||
cpp_entry { key: "EURBPC" value: 1 }
|
||||
cpp_entry { key: "EURBPN" value: 1 }
|
||||
@@ -668,17 +664,24 @@ CppConfig
|
||||
cpp_entry { key: "H4X" value: 20 }
|
||||
cpp_entry { key: "H4Z" value: 20 }
|
||||
cpp_entry { key: "H5" value: 20 }
|
||||
cpp_entry { key: "H5B" value: 1000 }
|
||||
cpp_entry { key: "H5F" value: 1000 }
|
||||
cpp_entry { key: "H5G" value: 1000 }
|
||||
cpp_entry { key: "H5L" value: 80 }
|
||||
cpp_entry { key: "H5X" value: 20 }
|
||||
cpp_entry { key: "H5Z" value: 20 }
|
||||
cpp_entry { key: "HB" value: 2500 }
|
||||
cpp_entry { key: "HBC" value: 1000 }
|
||||
cpp_entry { key: "HBR" value: 1000 }
|
||||
cpp_entry { key: "HCL" value: 1000 }
|
||||
cpp_entry { key: "HDB" value: 1000 }
|
||||
cpp_entry { key: "HE" value: 400 }
|
||||
cpp_entry { key: "HET" value: 400 }
|
||||
cpp_entry { key: "HG" value: 25000 }
|
||||
cpp_entry { key: "HG0" value: 25000 }
|
||||
cpp_entry { key: "HGB" value: 1000 }
|
||||
cpp_entry { key: "HGF" value: 25000 }
|
||||
cpp_entry { key: "HGK" value: 25000 }
|
||||
cpp_entry { key: "HGS" value: 25000 }
|
||||
cpp_entry { key: "HGT" value: 25000 }
|
||||
cpp_entry { key: "HH" value: 10000 }
|
||||
@@ -703,11 +706,16 @@ CppConfig
|
||||
cpp_entry { key: "HQX" value: 20 }
|
||||
cpp_entry { key: "HQZ" value: 20 }
|
||||
cpp_entry { key: "HRC" value: 20 }
|
||||
cpp_entry { key: "HRP" value: 20 }
|
||||
cpp_entry { key: "HS" value: 20 }
|
||||
cpp_entry { key: "HSX" value: 20 }
|
||||
cpp_entry { key: "HSZ" value: 20 }
|
||||
cpp_entry { key: "HTA" value: 1000 }
|
||||
cpp_entry { key: "HTB" value: 1000 }
|
||||
cpp_entry { key: "HTC" value: 1000 }
|
||||
cpp_entry { key: "HTE" value: 1000 }
|
||||
cpp_entry { key: "HTI" value: 1000 }
|
||||
cpp_entry { key: "HTM" value: 1000 }
|
||||
cpp_entry { key: "HTT" value: 1000 }
|
||||
cpp_entry { key: "HUF" value: 30000000 }
|
||||
cpp_entry { key: "HWA" value: 80 }
|
||||
@@ -719,7 +727,6 @@ CppConfig
|
||||
cpp_entry { key: "ICI" value: 1000 }
|
||||
cpp_entry { key: "IDL" value: 5 }
|
||||
cpp_entry { key: "IH" value: 50 }
|
||||
cpp_entry { key: "ILB" value: 1750 }
|
||||
cpp_entry { key: "ILS" value: 1000000 }
|
||||
cpp_entry { key: "IN" value: 2500 }
|
||||
cpp_entry { key: "IP" value: 50 }
|
||||
@@ -727,11 +734,12 @@ CppConfig
|
||||
cpp_entry { key: "IPT" value: 10 }
|
||||
cpp_entry { key: "IS" value: 50 }
|
||||
cpp_entry { key: "ITB" value: 744 }
|
||||
cpp_entry { key: "ITP" value: 252 }
|
||||
cpp_entry { key: "ITP" value: 264 }
|
||||
cpp_entry { key: "IW" value: 50 }
|
||||
cpp_entry { key: "J4L" value: 80 }
|
||||
cpp_entry { key: "J7" value: 6250000 }
|
||||
cpp_entry { key: "JA" value: 1000 }
|
||||
cpp_entry { key: "JCC" value: 1000 }
|
||||
cpp_entry { key: "JDL" value: 80 }
|
||||
cpp_entry { key: "JE" value: 42000 }
|
||||
cpp_entry { key: "JET" value: 42000 }
|
||||
@@ -740,7 +748,7 @@ CppConfig
|
||||
cpp_entry { key: "JKB" value: 10000 }
|
||||
cpp_entry { key: "JKF" value: 10000 }
|
||||
cpp_entry { key: "JKM" value: 10000 }
|
||||
cpp_entry { key: "JML" value: 200 }
|
||||
cpp_entry { key: "JML" value: 480 }
|
||||
cpp_entry { key: "JNC" value: 1000 }
|
||||
cpp_entry { key: "JNG" value: 10000 }
|
||||
cpp_entry { key: "JNL" value: 80 }
|
||||
@@ -809,6 +817,9 @@ CppConfig
|
||||
cpp_entry { key: "LSW" value: 1000 }
|
||||
cpp_entry { key: "LT" value: 42000 }
|
||||
cpp_entry { key: "LWB" value: 1000 }
|
||||
cpp_entry { key: "M1B" value: 10 }
|
||||
cpp_entry { key: "M2K" value: 5 }
|
||||
cpp_entry { key: "M35" value: 10 }
|
||||
cpp_entry { key: "M5F" value: 10 }
|
||||
cpp_entry { key: "M6A" value: 10000 }
|
||||
cpp_entry { key: "M6B" value: 6250 }
|
||||
@@ -839,10 +850,11 @@ CppConfig
|
||||
cpp_entry { key: "MEB" value: 100 }
|
||||
cpp_entry { key: "MEE" value: 100 }
|
||||
cpp_entry { key: "MEF" value: 10 }
|
||||
cpp_entry { key: "MEL" value: 840 }
|
||||
cpp_entry { key: "MEO" value: 100 }
|
||||
cpp_entry { key: "MES" value: 5 }
|
||||
cpp_entry { key: "MEW" value: 100 }
|
||||
cpp_entry { key: "MFB" value: 1000 }
|
||||
cpp_entry { key: "MFC" value: 100 }
|
||||
cpp_entry { key: "MFD" value: 100 }
|
||||
cpp_entry { key: "MFF" value: 1000 }
|
||||
cpp_entry { key: "MFP" value: 100 }
|
||||
@@ -879,6 +891,7 @@ CppConfig
|
||||
cpp_entry { key: "MNE" value: 100 }
|
||||
cpp_entry { key: "MNG" value: 2500 }
|
||||
cpp_entry { key: "MNH" value: 10000 }
|
||||
cpp_entry { key: "MNQ" value: 2 }
|
||||
cpp_entry { key: "MNS" value: 635 }
|
||||
cpp_entry { key: "MNT" value: 80 }
|
||||
cpp_entry { key: "MO" value: 1000 }
|
||||
@@ -910,6 +923,7 @@ CppConfig
|
||||
cpp_entry { key: "MXB" value: 35000 }
|
||||
cpp_entry { key: "MXL" value: 5 }
|
||||
cpp_entry { key: "MXR" value: 35000 }
|
||||
cpp_entry { key: "MYM" value: 0.5 }
|
||||
cpp_entry { key: "N1B" value: 1000 }
|
||||
cpp_entry { key: "N1R" value: 10 }
|
||||
cpp_entry { key: "N1T" value: 10 }
|
||||
@@ -927,7 +941,6 @@ CppConfig
|
||||
cpp_entry { key: "NCF" value: 100 }
|
||||
cpp_entry { key: "NCO" value: 5 }
|
||||
cpp_entry { key: "NCP" value: 100 }
|
||||
cpp_entry { key: "NEN" value: 2500 }
|
||||
cpp_entry { key: "NEO" value: 5 }
|
||||
cpp_entry { key: "NEP" value: 80 }
|
||||
cpp_entry { key: "NFC" value: 1000 }
|
||||
@@ -941,10 +954,14 @@ CppConfig
|
||||
cpp_entry { key: "NHN" value: 2500 }
|
||||
cpp_entry { key: "NHO" value: 5 }
|
||||
cpp_entry { key: "NHP" value: 80 }
|
||||
cpp_entry { key: "NIM" value: 500 }
|
||||
cpp_entry { key: "NIT" value: 500 }
|
||||
cpp_entry { key: "NIY" value: 500 }
|
||||
cpp_entry { key: "NJ" value: 2500 }
|
||||
cpp_entry { key: "NKD" value: 5 }
|
||||
cpp_entry { key: "NKM" value: 5 }
|
||||
cpp_entry { key: "NKN" value: 2500 }
|
||||
cpp_entry { key: "NKT" value: 5 }
|
||||
cpp_entry { key: "NL" value: 2500 }
|
||||
cpp_entry { key: "NLS" value: 42000 }
|
||||
cpp_entry { key: "NMO" value: 5 }
|
||||
@@ -984,7 +1001,7 @@ CppConfig
|
||||
cpp_entry { key: "NYR" value: 42000 }
|
||||
cpp_entry { key: "NYT" value: 1000 }
|
||||
cpp_entry { key: "NZDUSC" value: 1 }
|
||||
cpp_entry { key: "NZN" value: 2500 }
|
||||
cpp_entry { key: "NZDUSD" value: 1 }
|
||||
cpp_entry { key: "OAD" value: 1 }
|
||||
cpp_entry { key: "ODO" value: 1000 }
|
||||
cpp_entry { key: "OFF" value: 5 }
|
||||
@@ -1000,6 +1017,7 @@ CppConfig
|
||||
cpp_entry { key: "OVL" value: 5 }
|
||||
cpp_entry { key: "PA" value: 100 }
|
||||
cpp_entry { key: "PAL" value: 80 }
|
||||
cpp_entry { key: "PAM" value: 10 }
|
||||
cpp_entry { key: "PAT" value: 100 }
|
||||
cpp_entry { key: "PBO" value: 5 }
|
||||
cpp_entry { key: "PBP" value: 80 }
|
||||
@@ -1020,7 +1038,6 @@ CppConfig
|
||||
cpp_entry { key: "PHF" value: 5 }
|
||||
cpp_entry { key: "PHO" value: 5 }
|
||||
cpp_entry { key: "PHP" value: 80 }
|
||||
cpp_entry { key: "PIO" value: 500 }
|
||||
cpp_entry { key: "PJY" value: 125000 }
|
||||
cpp_entry { key: "PKP" value: 80 }
|
||||
cpp_entry { key: "PL" value: 50 }
|
||||
@@ -1082,6 +1099,8 @@ CppConfig
|
||||
cpp_entry { key: "R2T" value: 10 }
|
||||
cpp_entry { key: "R2V" value: 50 }
|
||||
cpp_entry { key: "R53" value: 1000 }
|
||||
cpp_entry { key: "R5B" value: 1000 }
|
||||
cpp_entry { key: "R5E" value: 1000 }
|
||||
cpp_entry { key: "R5F" value: 1000 }
|
||||
cpp_entry { key: "R5M" value: 100 }
|
||||
cpp_entry { key: "R5O" value: 10 }
|
||||
@@ -1091,6 +1110,7 @@ CppConfig
|
||||
cpp_entry { key: "RBF" value: 100 }
|
||||
cpp_entry { key: "RBG" value: 42000 }
|
||||
cpp_entry { key: "RBL" value: 42000 }
|
||||
cpp_entry { key: "RBM" value: 100 }
|
||||
cpp_entry { key: "RBS" value: 42000 }
|
||||
cpp_entry { key: "RBT" value: 42000 }
|
||||
cpp_entry { key: "REX" value: 100 }
|
||||
@@ -1119,13 +1139,15 @@ CppConfig
|
||||
cpp_entry { key: "RYA" value: 42000 }
|
||||
cpp_entry { key: "S1U" value: 1000 }
|
||||
cpp_entry { key: "S53" value: 1000 }
|
||||
cpp_entry { key: "S5B" value: 1000 }
|
||||
cpp_entry { key: "S5F" value: 1000 }
|
||||
cpp_entry { key: "S5M" value: 100 }
|
||||
cpp_entry { key: "S5O" value: 10 }
|
||||
cpp_entry { key: "SBM" value: 100 }
|
||||
cpp_entry { key: "SBT" value: 50 }
|
||||
cpp_entry { key: "SD" value: 1000 }
|
||||
cpp_entry { key: "SDA" value: 250 }
|
||||
cpp_entry { key: "SDD" value: 1600 }
|
||||
cpp_entry { key: "SDD" value: 1760 }
|
||||
cpp_entry { key: "SDG" value: 250 }
|
||||
cpp_entry { key: "SDI" value: 1000 }
|
||||
cpp_entry { key: "SDM" value: 100 }
|
||||
@@ -1157,12 +1179,14 @@ CppConfig
|
||||
cpp_entry { key: "SMT" value: 100 }
|
||||
cpp_entry { key: "SMU" value: 1000 }
|
||||
cpp_entry { key: "SMW" value: 100 }
|
||||
cpp_entry { key: "SOM" value: 500 }
|
||||
cpp_entry { key: "SON" value: 2500 }
|
||||
cpp_entry { key: "SP" value: 250 }
|
||||
cpp_entry { key: "SR1" value: 4167 }
|
||||
cpp_entry { key: "SR3" value: 2500 }
|
||||
cpp_entry { key: "SR5" value: 1000 }
|
||||
cpp_entry { key: "SRT" value: 1600 }
|
||||
cpp_entry { key: "SRB" value: 1000 }
|
||||
cpp_entry { key: "SRT" value: 1760 }
|
||||
cpp_entry { key: "SSI" value: 1000 }
|
||||
cpp_entry { key: "SSP" value: 5000 }
|
||||
cpp_entry { key: "SSW" value: 1000 }
|
||||
@@ -1173,25 +1197,31 @@ CppConfig
|
||||
cpp_entry { key: "STY" value: 1000 }
|
||||
cpp_entry { key: "SU" value: 250 }
|
||||
cpp_entry { key: "SUT" value: 250 }
|
||||
cpp_entry { key: "T02" value: 800 }
|
||||
cpp_entry { key: "T03" value: 800 }
|
||||
cpp_entry { key: "T04" value: 800 }
|
||||
cpp_entry { key: "T06" value: 800 }
|
||||
cpp_entry { key: "T07" value: 800 }
|
||||
cpp_entry { key: "T08" value: 800 }
|
||||
cpp_entry { key: "T09" value: 800 }
|
||||
cpp_entry { key: "T12" value: 800 }
|
||||
cpp_entry { key: "T13" value: 800 }
|
||||
cpp_entry { key: "T14" value: 800 }
|
||||
cpp_entry { key: "T17" value: 800 }
|
||||
cpp_entry { key: "T18" value: 800 }
|
||||
cpp_entry { key: "T15" value: 800 }
|
||||
cpp_entry { key: "T16" value: 800 }
|
||||
cpp_entry { key: "T19" value: 800 }
|
||||
cpp_entry { key: "T1U" value: 1000 }
|
||||
cpp_entry { key: "T20" value: 800 }
|
||||
cpp_entry { key: "T21" value: 800 }
|
||||
cpp_entry { key: "T24" value: 800 }
|
||||
cpp_entry { key: "T22" value: 800 }
|
||||
cpp_entry { key: "T23" value: 800 }
|
||||
cpp_entry { key: "T26" value: 800 }
|
||||
cpp_entry { key: "T27" value: 800 }
|
||||
cpp_entry { key: "T28" value: 800 }
|
||||
cpp_entry { key: "T29" value: 800 }
|
||||
cpp_entry { key: "T2B" value: 1000 }
|
||||
cpp_entry { key: "T2D" value: 1000 }
|
||||
cpp_entry { key: "T2M" value: 100 }
|
||||
cpp_entry { key: "T31" value: 800 }
|
||||
cpp_entry { key: "T30" value: 800 }
|
||||
cpp_entry { key: "T3B" value: 1000 }
|
||||
cpp_entry { key: "T3L" value: 80 }
|
||||
cpp_entry { key: "T4B" value: 1000 }
|
||||
@@ -1207,6 +1237,7 @@ CppConfig
|
||||
cpp_entry { key: "TC" value: 2500 }
|
||||
cpp_entry { key: "TC6" value: 1000 }
|
||||
cpp_entry { key: "TC9" value: 1000 }
|
||||
cpp_entry { key: "TCS" value: 1000 }
|
||||
cpp_entry { key: "TD3" value: 1000 }
|
||||
cpp_entry { key: "TD8" value: 1000 }
|
||||
cpp_entry { key: "TEX" value: 1000 }
|
||||
@@ -1216,6 +1247,7 @@ CppConfig
|
||||
cpp_entry { key: "THB" value: 1000 }
|
||||
cpp_entry { key: "THD" value: 10000 }
|
||||
cpp_entry { key: "TIC" value: 500 }
|
||||
cpp_entry { key: "TIL" value: 1000 }
|
||||
cpp_entry { key: "TIO" value: 500 }
|
||||
cpp_entry { key: "TK" value: 1000 }
|
||||
cpp_entry { key: "TKB" value: 1000 }
|
||||
@@ -1252,7 +1284,6 @@ CppConfig
|
||||
cpp_entry { key: "TUT" value: 1000 }
|
||||
cpp_entry { key: "TUX" value: 1000 }
|
||||
cpp_entry { key: "TW" value: 1000 }
|
||||
cpp_entry { key: "TXN" value: 2500 }
|
||||
cpp_entry { key: "TYT" value: 1000 }
|
||||
cpp_entry { key: "TYX" value: 1000 }
|
||||
cpp_entry { key: "TZ6" value: 2500 }
|
||||
@@ -1262,10 +1293,12 @@ CppConfig
|
||||
cpp_entry { key: "UB" value: 1000 }
|
||||
cpp_entry { key: "UCM" value: 100 }
|
||||
cpp_entry { key: "UDL" value: 80 }
|
||||
cpp_entry { key: "UFB" value: 100 }
|
||||
cpp_entry { key: "UFE" value: 100 }
|
||||
cpp_entry { key: "UFG" value: 100 }
|
||||
cpp_entry { key: "UFN" value: 100 }
|
||||
cpp_entry { key: "UFU" value: 100 }
|
||||
cpp_entry { key: "UFZ" value: 100 }
|
||||
cpp_entry { key: "UFV" value: 100 }
|
||||
cpp_entry { key: "UGG" value: 42000 }
|
||||
cpp_entry { key: "UKG" value: 310 }
|
||||
cpp_entry { key: "ULB" value: 42000 }
|
||||
@@ -1276,10 +1309,12 @@ CppConfig
|
||||
cpp_entry { key: "UNB" value: 1000 }
|
||||
cpp_entry { key: "UNS" value: 1000 }
|
||||
cpp_entry { key: "UR" value: 1000 }
|
||||
cpp_entry { key: "USC" value: 1000 }
|
||||
cpp_entry { key: "USDBRL" value: 1 }
|
||||
cpp_entry { key: "USDCAC" value: 1 }
|
||||
cpp_entry { key: "USDCAD" value: 1 }
|
||||
cpp_entry { key: "USDCAN" value: 1 }
|
||||
cpp_entry { key: "USDCHF" value: 10 }
|
||||
cpp_entry { key: "USDCKC" value: 1 }
|
||||
cpp_entry { key: "USDCLP" value: 1 }
|
||||
cpp_entry { key: "USDCNY" value: 1 }
|
||||
@@ -1309,6 +1344,7 @@ CppConfig
|
||||
cpp_entry { key: "USDTLC" value: 1 }
|
||||
cpp_entry { key: "USDTWD" value: 1 }
|
||||
cpp_entry { key: "USDZRC" value: 1 }
|
||||
cpp_entry { key: "USE" value: 1000 }
|
||||
cpp_entry { key: "UV" value: 1000 }
|
||||
cpp_entry { key: "UX" value: 250 }
|
||||
cpp_entry { key: "V3L" value: 5 }
|
||||
@@ -1338,6 +1374,7 @@ CppConfig
|
||||
cpp_entry { key: "WTA" value: 1000 }
|
||||
cpp_entry { key: "WTD" value: 1000 }
|
||||
cpp_entry { key: "WTI" value: 1000 }
|
||||
cpp_entry { key: "WTL" value: 1000 }
|
||||
cpp_entry { key: "WTS" value: 1000 }
|
||||
cpp_entry { key: "WTT" value: 1000 }
|
||||
cpp_entry { key: "X0" value: 1000 }
|
||||
@@ -1390,6 +1427,7 @@ CppConfig
|
||||
cpp_entry { key: "YWE" value: 80 }
|
||||
cpp_entry { key: "YWF" value: 5 }
|
||||
cpp_entry { key: "YWK" value: 5 }
|
||||
cpp_entry { key: "Z00000" value: 1000 }
|
||||
cpp_entry { key: "Z1B" value: 100 }
|
||||
cpp_entry { key: "Z3N" value: 2000 }
|
||||
cpp_entry { key: "Z4" value: 1000 }
|
||||
@@ -1507,8 +1545,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "8D" value: NYMEX }
|
||||
cme_mic { key: "8W" value: NYMEX }
|
||||
cme_mic { key: "8XN" value: NYMEX }
|
||||
cme_mic { key: "8ZN" value: NYMEX }
|
||||
cme_mic { key: "9FN" value: NYMEX }
|
||||
cme_mic { key: "9Q" value: NYMEX }
|
||||
cme_mic { key: "A0D" value: NYMEX }
|
||||
cme_mic { key: "A0F" value: NYMEX }
|
||||
@@ -1580,6 +1616,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "AAW" value: NYMEX }
|
||||
cme_mic { key: "AB3" value: NYMEX }
|
||||
cme_mic { key: "AB7" value: NYMEX }
|
||||
cme_mic { key: "ABF" value: NYMEX }
|
||||
cme_mic { key: "ABH" value: NYMEX }
|
||||
cme_mic { key: "ABI" value: NYMEX }
|
||||
cme_mic { key: "ABS" value: NYMEX }
|
||||
@@ -1587,6 +1624,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "ABX" value: NYMEX }
|
||||
cme_mic { key: "ABY" value: NYMEX }
|
||||
cme_mic { key: "AC0" value: NYMEX }
|
||||
cme_mic { key: "ACB" value: NYMEX }
|
||||
cme_mic { key: "ACD" value: CME }
|
||||
cme_mic { key: "ACM" value: NYMEX }
|
||||
cme_mic { key: "ACT" value: NYMEX }
|
||||
@@ -1600,7 +1638,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "AE5" value: NYMEX }
|
||||
cme_mic { key: "AE8" value: NYMEX }
|
||||
cme_mic { key: "AE9" value: NYMEX }
|
||||
cme_mic { key: "AEJ" value: NYMEX }
|
||||
cme_mic { key: "AEB" value: NYMEX }
|
||||
cme_mic { key: "AEP" value: COMEX }
|
||||
cme_mic { key: "AET" value: NYMEX }
|
||||
cme_mic { key: "AEZ" value: NYMEX }
|
||||
@@ -1639,7 +1677,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "AJB" value: NYMEX }
|
||||
cme_mic { key: "AJJ" value: NYMEX }
|
||||
cme_mic { key: "AJL" value: NYMEX }
|
||||
cme_mic { key: "AJP" value: NYMEX }
|
||||
cme_mic { key: "AJR" value: NYMEX }
|
||||
cme_mic { key: "AJS" value: NYMEX }
|
||||
cme_mic { key: "AJU" value: NYMEX }
|
||||
@@ -1763,7 +1800,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "BCF" value: CBT }
|
||||
cme_mic { key: "BCH" value: CBT }
|
||||
cme_mic { key: "BDB" value: NYMEX }
|
||||
cme_mic { key: "BDI" value: CME }
|
||||
cme_mic { key: "BDS" value: DME }
|
||||
cme_mic { key: "BFR" value: NYMEX }
|
||||
cme_mic { key: "BG" value: NYMEX }
|
||||
@@ -1774,13 +1810,12 @@ CmeSymbolMics
|
||||
cme_mic { key: "BOO" value: NYMEX }
|
||||
cme_mic { key: "BOS" value: CME }
|
||||
cme_mic { key: "BR7" value: NYMEX }
|
||||
cme_mic { key: "BSW" value: CBT }
|
||||
cme_mic { key: "BSF" value: CBT }
|
||||
cme_mic { key: "BTC" value: CME }
|
||||
cme_mic { key: "BTT" value: CME }
|
||||
cme_mic { key: "BUB" value: CBT }
|
||||
cme_mic { key: "BUC" value: NYMEX }
|
||||
cme_mic { key: "BUS" value: NYMEX }
|
||||
cme_mic { key: "BUW" value: NYMSW }
|
||||
cme_mic { key: "BWF" value: CBT }
|
||||
cme_mic { key: "BWH" value: CBT }
|
||||
cme_mic { key: "BZ" value: NYMEX }
|
||||
@@ -1811,6 +1846,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "CFB" value: NYMEX }
|
||||
cme_mic { key: "CFC" value: NYMEX }
|
||||
cme_mic { key: "CGB" value: NYMEX }
|
||||
cme_mic { key: "CHB" value: NYMEX }
|
||||
cme_mic { key: "CHI" value: CME }
|
||||
cme_mic { key: "CHL" value: CME }
|
||||
cme_mic { key: "CHP" value: CME }
|
||||
@@ -1823,9 +1859,11 @@ CmeSymbolMics
|
||||
cme_mic { key: "CL" value: NYMEX }
|
||||
cme_mic { key: "CL1" value: NYMEX }
|
||||
cme_mic { key: "CL2" value: NYMEX }
|
||||
cme_mic { key: "CLD" value: NYMEX }
|
||||
cme_mic { key: "CLL" value: NYMEX }
|
||||
cme_mic { key: "CLS" value: NYMEX }
|
||||
cme_mic { key: "CLT" value: NYMEX }
|
||||
cme_mic { key: "CMB" value: NYMEX }
|
||||
cme_mic { key: "CMF" value: NYMEX }
|
||||
cme_mic { key: "CNH" value: CME }
|
||||
cme_mic { key: "COL" value: NYMEX }
|
||||
@@ -1848,7 +1886,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "CUS" value: CME }
|
||||
cme_mic { key: "CY" value: NYMEX }
|
||||
cme_mic { key: "CZK" value: CME }
|
||||
cme_mic { key: "CZN" value: NYMEX }
|
||||
cme_mic { key: "D0" value: CME }
|
||||
cme_mic { key: "D0X" value: CME }
|
||||
cme_mic { key: "D0Z" value: CME }
|
||||
@@ -1880,7 +1917,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "DEN" value: CME }
|
||||
cme_mic { key: "DEP" value: NYMEX }
|
||||
cme_mic { key: "DFL" value: CBT }
|
||||
cme_mic { key: "DFT" value: CBT }
|
||||
cme_mic { key: "DFN" value: CBT }
|
||||
cme_mic { key: "DG2" value: CBT }
|
||||
cme_mic { key: "DG3" value: CBT }
|
||||
cme_mic { key: "DGH" value: DME }
|
||||
@@ -1889,7 +1926,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "DGT" value: CBT }
|
||||
cme_mic { key: "DHA" value: NYMEX }
|
||||
cme_mic { key: "DHI" value: DME }
|
||||
cme_mic { key: "DIH" value: NYMEX }
|
||||
cme_mic { key: "DJR" value: CBT }
|
||||
cme_mic { key: "DKR" value: DME }
|
||||
cme_mic { key: "DMB" value: DME }
|
||||
@@ -1920,7 +1956,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "EAC" value: NYMEX }
|
||||
cme_mic { key: "EAD" value: CME }
|
||||
cme_mic { key: "EAE" value: NYMEX }
|
||||
cme_mic { key: "EAF" value: NYMEX }
|
||||
cme_mic { key: "EAW" value: NYMEX }
|
||||
cme_mic { key: "EBE" value: NYMEX }
|
||||
cme_mic { key: "ECD" value: CME }
|
||||
@@ -1959,7 +1994,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "EST" value: CME }
|
||||
cme_mic { key: "ETT" value: CME }
|
||||
cme_mic { key: "EUB" value: NYMEX }
|
||||
cme_mic { key: "EUL" value: NYMEX }
|
||||
cme_mic { key: "EURADC" value: CME }
|
||||
cme_mic { key: "EURBPC" value: CME }
|
||||
cme_mic { key: "EURBPN" value: CME }
|
||||
@@ -2085,17 +2119,24 @@ CmeSymbolMics
|
||||
cme_mic { key: "H4X" value: CME }
|
||||
cme_mic { key: "H4Z" value: CME }
|
||||
cme_mic { key: "H5" value: CME }
|
||||
cme_mic { key: "H5B" value: NYMEX }
|
||||
cme_mic { key: "H5F" value: NYMEX }
|
||||
cme_mic { key: "H5G" value: NYMEX }
|
||||
cme_mic { key: "H5L" value: NYMEX }
|
||||
cme_mic { key: "H5X" value: CME }
|
||||
cme_mic { key: "H5Z" value: CME }
|
||||
cme_mic { key: "HB" value: NYMEX }
|
||||
cme_mic { key: "HBC" value: NYMEX }
|
||||
cme_mic { key: "HBR" value: NYMEX }
|
||||
cme_mic { key: "HCL" value: NYMEX }
|
||||
cme_mic { key: "HDB" value: NYMEX }
|
||||
cme_mic { key: "HE" value: CME }
|
||||
cme_mic { key: "HET" value: CME }
|
||||
cme_mic { key: "HG" value: COMEX }
|
||||
cme_mic { key: "HG0" value: COMEX }
|
||||
cme_mic { key: "HGB" value: NYMEX }
|
||||
cme_mic { key: "HGF" value: COMEX }
|
||||
cme_mic { key: "HGK" value: COMEX }
|
||||
cme_mic { key: "HGS" value: COMEX }
|
||||
cme_mic { key: "HGT" value: COMEX }
|
||||
cme_mic { key: "HH" value: NYMEX }
|
||||
@@ -2120,11 +2161,16 @@ CmeSymbolMics
|
||||
cme_mic { key: "HQX" value: CME }
|
||||
cme_mic { key: "HQZ" value: CME }
|
||||
cme_mic { key: "HRC" value: NYMEX }
|
||||
cme_mic { key: "HRP" value: COMEX }
|
||||
cme_mic { key: "HS" value: CME }
|
||||
cme_mic { key: "HSX" value: CME }
|
||||
cme_mic { key: "HSZ" value: CME }
|
||||
cme_mic { key: "HTA" value: NYMEX }
|
||||
cme_mic { key: "HTB" value: NYMEX }
|
||||
cme_mic { key: "HTC" value: NYMEX }
|
||||
cme_mic { key: "HTE" value: NYMEX }
|
||||
cme_mic { key: "HTI" value: NYMEX }
|
||||
cme_mic { key: "HTM" value: NYMEX }
|
||||
cme_mic { key: "HTT" value: NYMEX }
|
||||
cme_mic { key: "HUF" value: CME }
|
||||
cme_mic { key: "HWA" value: NYMEX }
|
||||
@@ -2136,7 +2182,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "ICI" value: NYMEX }
|
||||
cme_mic { key: "IDL" value: NYMEX }
|
||||
cme_mic { key: "IH" value: MGE }
|
||||
cme_mic { key: "ILB" value: NYMEX }
|
||||
cme_mic { key: "ILS" value: CME }
|
||||
cme_mic { key: "IN" value: NYMEX }
|
||||
cme_mic { key: "IP" value: MGE }
|
||||
@@ -2149,6 +2194,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "J4L" value: NYMEX }
|
||||
cme_mic { key: "J7" value: CME }
|
||||
cme_mic { key: "JA" value: NYMEX }
|
||||
cme_mic { key: "JCC" value: NYMEX }
|
||||
cme_mic { key: "JDL" value: NYMEX }
|
||||
cme_mic { key: "JE" value: NYMEX }
|
||||
cme_mic { key: "JET" value: NYMEX }
|
||||
@@ -2226,6 +2272,9 @@ CmeSymbolMics
|
||||
cme_mic { key: "LSW" value: NYMEX }
|
||||
cme_mic { key: "LT" value: NYMEX }
|
||||
cme_mic { key: "LWB" value: NYMEX }
|
||||
cme_mic { key: "M1B" value: NYMEX }
|
||||
cme_mic { key: "M2K" value: CME }
|
||||
cme_mic { key: "M35" value: NYMEX }
|
||||
cme_mic { key: "M5F" value: NYMEX }
|
||||
cme_mic { key: "M6A" value: CME }
|
||||
cme_mic { key: "M6B" value: CME }
|
||||
@@ -2256,10 +2305,11 @@ CmeSymbolMics
|
||||
cme_mic { key: "MEB" value: NYMEX }
|
||||
cme_mic { key: "MEE" value: NYMEX }
|
||||
cme_mic { key: "MEF" value: NYMEX }
|
||||
cme_mic { key: "MEL" value: NYMEX }
|
||||
cme_mic { key: "MEO" value: NYMEX }
|
||||
cme_mic { key: "MES" value: CME }
|
||||
cme_mic { key: "MEW" value: NYMEX }
|
||||
cme_mic { key: "MFB" value: NYMEX }
|
||||
cme_mic { key: "MFC" value: CBT }
|
||||
cme_mic { key: "MFD" value: NYMEX }
|
||||
cme_mic { key: "MFF" value: NYMEX }
|
||||
cme_mic { key: "MFP" value: NYMEX }
|
||||
@@ -2296,6 +2346,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "MNE" value: NYMEX }
|
||||
cme_mic { key: "MNG" value: NYMEX }
|
||||
cme_mic { key: "MNH" value: CME }
|
||||
cme_mic { key: "MNQ" value: CME }
|
||||
cme_mic { key: "MNS" value: NYMEX }
|
||||
cme_mic { key: "MNT" value: NYMEX }
|
||||
cme_mic { key: "MO" value: NYMEX }
|
||||
@@ -2327,6 +2378,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "MXB" value: NYMEX }
|
||||
cme_mic { key: "MXL" value: NYMEX }
|
||||
cme_mic { key: "MXR" value: NYMEX }
|
||||
cme_mic { key: "MYM" value: CBT }
|
||||
cme_mic { key: "N1B" value: NYMEX }
|
||||
cme_mic { key: "N1R" value: CME }
|
||||
cme_mic { key: "N1T" value: CME }
|
||||
@@ -2344,7 +2396,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "NCF" value: NYMEX }
|
||||
cme_mic { key: "NCO" value: NYMEX }
|
||||
cme_mic { key: "NCP" value: NYMEX }
|
||||
cme_mic { key: "NEN" value: NYMEX }
|
||||
cme_mic { key: "NEO" value: NYMEX }
|
||||
cme_mic { key: "NEP" value: NYMEX }
|
||||
cme_mic { key: "NFC" value: NYMEX }
|
||||
@@ -2358,10 +2409,14 @@ CmeSymbolMics
|
||||
cme_mic { key: "NHN" value: NYMEX }
|
||||
cme_mic { key: "NHO" value: NYMEX }
|
||||
cme_mic { key: "NHP" value: NYMEX }
|
||||
cme_mic { key: "NIM" value: CME }
|
||||
cme_mic { key: "NIT" value: CME }
|
||||
cme_mic { key: "NIY" value: CME }
|
||||
cme_mic { key: "NJ" value: NYMEX }
|
||||
cme_mic { key: "NKD" value: CME }
|
||||
cme_mic { key: "NKM" value: CME }
|
||||
cme_mic { key: "NKN" value: NYMEX }
|
||||
cme_mic { key: "NKT" value: CME }
|
||||
cme_mic { key: "NL" value: NYMEX }
|
||||
cme_mic { key: "NLS" value: NYMEX }
|
||||
cme_mic { key: "NMO" value: NYMEX }
|
||||
@@ -2401,7 +2456,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "NYR" value: NYMEX }
|
||||
cme_mic { key: "NYT" value: NYMEX }
|
||||
cme_mic { key: "NZDUSC" value: CME }
|
||||
cme_mic { key: "NZN" value: NYMEX }
|
||||
cme_mic { key: "NZDUSD" value: FXS }
|
||||
cme_mic { key: "OAD" value: NYMEX }
|
||||
cme_mic { key: "ODO" value: DME }
|
||||
cme_mic { key: "OFF" value: NYMEX }
|
||||
@@ -2417,6 +2472,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "OVL" value: NYMEX }
|
||||
cme_mic { key: "PA" value: NYMEX }
|
||||
cme_mic { key: "PAL" value: NYMEX }
|
||||
cme_mic { key: "PAM" value: NYMEX }
|
||||
cme_mic { key: "PAT" value: NYMEX }
|
||||
cme_mic { key: "PBO" value: NYMEX }
|
||||
cme_mic { key: "PBP" value: NYMEX }
|
||||
@@ -2437,7 +2493,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "PHF" value: NYMEX }
|
||||
cme_mic { key: "PHO" value: NYMEX }
|
||||
cme_mic { key: "PHP" value: NYMEX }
|
||||
cme_mic { key: "PIO" value: NYMEX }
|
||||
cme_mic { key: "PJY" value: CME }
|
||||
cme_mic { key: "PKP" value: NYMEX }
|
||||
cme_mic { key: "PL" value: NYMEX }
|
||||
@@ -2499,6 +2554,8 @@ CmeSymbolMics
|
||||
cme_mic { key: "R2T" value: CME }
|
||||
cme_mic { key: "R2V" value: CME }
|
||||
cme_mic { key: "R53" value: NYMEX }
|
||||
cme_mic { key: "R5B" value: NYMEX }
|
||||
cme_mic { key: "R5E" value: NYMEX }
|
||||
cme_mic { key: "R5F" value: NYMEX }
|
||||
cme_mic { key: "R5M" value: NYMEX }
|
||||
cme_mic { key: "R5O" value: NYMEX }
|
||||
@@ -2508,6 +2565,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "RBF" value: NYMEX }
|
||||
cme_mic { key: "RBG" value: NYMEX }
|
||||
cme_mic { key: "RBL" value: NYMEX }
|
||||
cme_mic { key: "RBM" value: NYMEX }
|
||||
cme_mic { key: "RBS" value: NYMEX }
|
||||
cme_mic { key: "RBT" value: NYMEX }
|
||||
cme_mic { key: "REX" value: CBT }
|
||||
@@ -2536,9 +2594,11 @@ CmeSymbolMics
|
||||
cme_mic { key: "RYA" value: NYMEX }
|
||||
cme_mic { key: "S1U" value: CBT }
|
||||
cme_mic { key: "S53" value: NYMEX }
|
||||
cme_mic { key: "S5B" value: NYMEX }
|
||||
cme_mic { key: "S5F" value: NYMEX }
|
||||
cme_mic { key: "S5M" value: NYMEX }
|
||||
cme_mic { key: "S5O" value: NYMEX }
|
||||
cme_mic { key: "SBM" value: NYMEX }
|
||||
cme_mic { key: "SBT" value: CBT }
|
||||
cme_mic { key: "SD" value: NYMEX }
|
||||
cme_mic { key: "SDA" value: CME }
|
||||
@@ -2574,11 +2634,13 @@ CmeSymbolMics
|
||||
cme_mic { key: "SMT" value: CME }
|
||||
cme_mic { key: "SMU" value: NYMEX }
|
||||
cme_mic { key: "SMW" value: NYMEX }
|
||||
cme_mic { key: "SOM" value: CBT }
|
||||
cme_mic { key: "SON" value: CME }
|
||||
cme_mic { key: "SP" value: CME }
|
||||
cme_mic { key: "SR1" value: CME }
|
||||
cme_mic { key: "SR3" value: CME }
|
||||
cme_mic { key: "SR5" value: NYMEX }
|
||||
cme_mic { key: "SRB" value: NYMEX }
|
||||
cme_mic { key: "SRT" value: NYMEX }
|
||||
cme_mic { key: "SSI" value: NYMEX }
|
||||
cme_mic { key: "SSP" value: COMEX }
|
||||
@@ -2590,25 +2652,31 @@ CmeSymbolMics
|
||||
cme_mic { key: "STY" value: NYMEX }
|
||||
cme_mic { key: "SU" value: CME }
|
||||
cme_mic { key: "SUT" value: CME }
|
||||
cme_mic { key: "T02" value: NYMEX }
|
||||
cme_mic { key: "T03" value: NYMEX }
|
||||
cme_mic { key: "T04" value: NYMEX }
|
||||
cme_mic { key: "T06" value: NYMEX }
|
||||
cme_mic { key: "T07" value: NYMEX }
|
||||
cme_mic { key: "T08" value: NYMEX }
|
||||
cme_mic { key: "T09" value: NYMEX }
|
||||
cme_mic { key: "T12" value: NYMEX }
|
||||
cme_mic { key: "T13" value: NYMEX }
|
||||
cme_mic { key: "T14" value: NYMEX }
|
||||
cme_mic { key: "T17" value: NYMEX }
|
||||
cme_mic { key: "T18" value: NYMEX }
|
||||
cme_mic { key: "T15" value: NYMEX }
|
||||
cme_mic { key: "T16" value: NYMEX }
|
||||
cme_mic { key: "T19" value: NYMEX }
|
||||
cme_mic { key: "T1U" value: CBT }
|
||||
cme_mic { key: "T20" value: NYMEX }
|
||||
cme_mic { key: "T21" value: NYMEX }
|
||||
cme_mic { key: "T24" value: NYMEX }
|
||||
cme_mic { key: "T22" value: NYMEX }
|
||||
cme_mic { key: "T23" value: NYMEX }
|
||||
cme_mic { key: "T26" value: NYMEX }
|
||||
cme_mic { key: "T27" value: NYMEX }
|
||||
cme_mic { key: "T28" value: NYMEX }
|
||||
cme_mic { key: "T29" value: NYMEX }
|
||||
cme_mic { key: "T2B" value: NYMEX }
|
||||
cme_mic { key: "T2D" value: NYMEX }
|
||||
cme_mic { key: "T2M" value: NYMEX }
|
||||
cme_mic { key: "T31" value: NYMEX }
|
||||
cme_mic { key: "T30" value: NYMEX }
|
||||
cme_mic { key: "T3B" value: NYMEX }
|
||||
cme_mic { key: "T3L" value: NYMEX }
|
||||
cme_mic { key: "T4B" value: NYMEX }
|
||||
@@ -2624,6 +2692,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "TC" value: NYMEX }
|
||||
cme_mic { key: "TC6" value: NYMEX }
|
||||
cme_mic { key: "TC9" value: NYMEX }
|
||||
cme_mic { key: "TCS" value: NYMEX }
|
||||
cme_mic { key: "TD3" value: NYMEX }
|
||||
cme_mic { key: "TD8" value: NYMEX }
|
||||
cme_mic { key: "TEX" value: CBT }
|
||||
@@ -2633,6 +2702,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "THB" value: NYMEX }
|
||||
cme_mic { key: "THD" value: NYMEX }
|
||||
cme_mic { key: "TIC" value: NYMEX }
|
||||
cme_mic { key: "TIL" value: NYMEX }
|
||||
cme_mic { key: "TIO" value: NYMEX }
|
||||
cme_mic { key: "TK" value: NYMEX }
|
||||
cme_mic { key: "TKB" value: NYMEX }
|
||||
@@ -2669,7 +2739,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "TUT" value: CBT }
|
||||
cme_mic { key: "TUX" value: CBT }
|
||||
cme_mic { key: "TW" value: NYMEX }
|
||||
cme_mic { key: "TXN" value: NYMEX }
|
||||
cme_mic { key: "TYT" value: CBT }
|
||||
cme_mic { key: "TYX" value: CBT }
|
||||
cme_mic { key: "TZ6" value: NYMEX }
|
||||
@@ -2679,10 +2748,12 @@ CmeSymbolMics
|
||||
cme_mic { key: "UB" value: CBT }
|
||||
cme_mic { key: "UCM" value: NYMEX }
|
||||
cme_mic { key: "UDL" value: NYMEX }
|
||||
cme_mic { key: "UFB" value: CBT }
|
||||
cme_mic { key: "UFE" value: CBT }
|
||||
cme_mic { key: "UFG" value: CBT }
|
||||
cme_mic { key: "UFN" value: CBT }
|
||||
cme_mic { key: "UFU" value: CBT }
|
||||
cme_mic { key: "UFZ" value: CBT }
|
||||
cme_mic { key: "UFV" value: CBT }
|
||||
cme_mic { key: "UGG" value: NYMEX }
|
||||
cme_mic { key: "UKG" value: NYMEX }
|
||||
cme_mic { key: "ULB" value: NYMEX }
|
||||
@@ -2693,10 +2764,12 @@ CmeSymbolMics
|
||||
cme_mic { key: "UNB" value: NYMEX }
|
||||
cme_mic { key: "UNS" value: NYMEX }
|
||||
cme_mic { key: "UR" value: NYMEX }
|
||||
cme_mic { key: "USC" value: NYMEX }
|
||||
cme_mic { key: "USDBRL" value: CME }
|
||||
cme_mic { key: "USDCAC" value: CME }
|
||||
cme_mic { key: "USDCAD" value: FXS }
|
||||
cme_mic { key: "USDCAN" value: CME }
|
||||
cme_mic { key: "USDCHF" value: FXS }
|
||||
cme_mic { key: "USDCKC" value: CME }
|
||||
cme_mic { key: "USDCLP" value: CME }
|
||||
cme_mic { key: "USDCNY" value: CME }
|
||||
@@ -2726,6 +2799,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "USDTLC" value: CME }
|
||||
cme_mic { key: "USDTWD" value: CME }
|
||||
cme_mic { key: "USDZRC" value: CME }
|
||||
cme_mic { key: "USE" value: NYMEX }
|
||||
cme_mic { key: "UV" value: NYMEX }
|
||||
cme_mic { key: "UX" value: NYMEX }
|
||||
cme_mic { key: "V3L" value: NYMEX }
|
||||
@@ -2755,6 +2829,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "WTA" value: NYMEX }
|
||||
cme_mic { key: "WTD" value: NYMEX }
|
||||
cme_mic { key: "WTI" value: NYMEX }
|
||||
cme_mic { key: "WTL" value: NYMEX }
|
||||
cme_mic { key: "WTS" value: NYMEX }
|
||||
cme_mic { key: "WTT" value: NYMEX }
|
||||
cme_mic { key: "X0" value: NYMEX }
|
||||
@@ -2807,6 +2882,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "YWE" value: NYMEX }
|
||||
cme_mic { key: "YWF" value: NYMEX }
|
||||
cme_mic { key: "YWK" value: NYMEX }
|
||||
cme_mic { key: "Z00000" value: CME }
|
||||
cme_mic { key: "Z1B" value: NYMEX }
|
||||
cme_mic { key: "Z3N" value: CBT }
|
||||
cme_mic { key: "Z4" value: NYMEX }
|
||||
|
||||
@@ -143,11 +143,4 @@ message OffsetAttachUIOptions {
|
||||
|
||||
message ManualFillsOptions {
|
||||
optional bool modal_transactions = 1 [default = true];
|
||||
}
|
||||
|
||||
message AlgoPermissions {
|
||||
repeated string exchange_order_types = 10;
|
||||
repeated string spreader_order_types = 20;
|
||||
repeated string attachable_order_types = 30;
|
||||
repeated string outright_order_types = 40;
|
||||
}
|
||||
@@ -156,18 +156,6 @@ class OrderStateUpdateEvent : public mercury::Event<OrderStateUpdateEvent> {
|
||||
case api::orderman::OrderState::kProrata:
|
||||
result.mutable_prorata();
|
||||
break;
|
||||
case api::orderman::OrderState::kTwap:
|
||||
result.mutable_twap();
|
||||
break;
|
||||
case api::orderman::OrderState::kVwap:
|
||||
result.mutable_vwap();
|
||||
break;
|
||||
case api::orderman::OrderState::kPov:
|
||||
result.mutable_pov();
|
||||
break;
|
||||
case api::orderman::OrderState::kArrival:
|
||||
result.mutable_arrival();
|
||||
break;
|
||||
case api::orderman::OrderState::kDynamic:
|
||||
result.mutable_dynamic();
|
||||
break;
|
||||
|
||||
@@ -23,11 +23,6 @@
|
||||
#include "lib/orderman/orders/algo/algo_orders/OffsetAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/ScratchAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/ProRataAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/TWAPAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/VWAPAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/POVAlgo.h"
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/ArrivalPriceAlgo.h"
|
||||
|
||||
#include "lib/orderman/orders/book_algos/OCOOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/PricerOrder.h"
|
||||
#include "lib/orderman/orders/spreader_orders/SpreaderOrder.h"
|
||||
@@ -210,22 +205,6 @@ Order &OrderFactory::allocate(OrderKey k, OrderKey pk,
|
||||
order_ptr.reset(
|
||||
new orderman::AlgoWrapperOrder(std::make_unique<ProRataAlgo>()));
|
||||
break;
|
||||
case CustomOrderDefinition::kTwap:
|
||||
order_ptr.reset(
|
||||
new orderman::AlgoWrapperOrder(std::make_unique<TWAPAlgo>()));
|
||||
break;
|
||||
case CustomOrderDefinition::kVwap:
|
||||
order_ptr.reset(
|
||||
new orderman::AlgoWrapperOrder(std::make_unique<VWAPAlgo>()));
|
||||
break;
|
||||
case CustomOrderDefinition::kPov:
|
||||
order_ptr.reset(
|
||||
new orderman::AlgoWrapperOrder(std::make_unique<POVAlgo>()));
|
||||
break;
|
||||
case CustomOrderDefinition::kArrival:
|
||||
order_ptr.reset(
|
||||
new orderman::AlgoWrapperOrder(std::make_unique<ArrivalPriceAlgo>()));
|
||||
break;
|
||||
case CustomOrderDefinition::kDynamic: {
|
||||
order_ptr = me->dynamic_order_registry.build(
|
||||
def.custom_def().dynamic().dynamic_order_type());
|
||||
@@ -236,7 +215,6 @@ Order &OrderFactory::allocate(OrderKey k, OrderKey pk,
|
||||
order_ptr.reset(new orderman::DynamicOrder());
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case CustomOrderDefinition::kComposite:
|
||||
order_ptr.reset(new orderman::CompositeOrder());
|
||||
|
||||
@@ -1,227 +0,0 @@
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/ArrivalPriceAlgo.h"
|
||||
#include "lib/orderman/orders/algo/IAlgoServices.h"
|
||||
#include "lib/orderman/orders/algo/DynamicHelpers.h"
|
||||
|
||||
#include "lib/orderman/order_factory/IOrderFactory.h"
|
||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderUtils.h"
|
||||
#include "lib/os/os.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
enum class ArrivalPriceAlgo::Status { WAITING_FOR_MD, WAITING_TO_SCRATCH, SCRATCHED };
|
||||
|
||||
struct ArrivalPriceAlgo::PImpl
|
||||
{
|
||||
IAlgoServices *algo;
|
||||
OrderDefinition definition;
|
||||
|
||||
Quantity scratch_threshold;
|
||||
Price chase_diff;
|
||||
Status status = Status::WAITING_FOR_MD;
|
||||
OrderKey child_key = null_order_key();
|
||||
ChildTemplate *child_template = nullptr;
|
||||
Book last_book;
|
||||
Book book_at_inception;
|
||||
Price scratch_price=Price(os::nan());
|
||||
};
|
||||
|
||||
ArrivalPriceAlgo::ArrivalPriceAlgo() : me(new PImpl()) {}
|
||||
ArrivalPriceAlgo::~ArrivalPriceAlgo() {}
|
||||
IAlgoServices &ArrivalPriceAlgo::algo() const { return *me->algo; }
|
||||
|
||||
OrderOpResult ArrivalPriceAlgo::do_before_launch(IBeforeLaunchAlgoServices &serv)
|
||||
{
|
||||
const auto& def = serv.definition();
|
||||
bts_assert(def.has_custom_def());
|
||||
bts_assert(def.custom_def().has_scratch());
|
||||
// Validate the scratch part of the definition
|
||||
auto &scratch = def.custom_def().scratch();
|
||||
if (!scratch.has_child() && OrderKey(def.attach_target_order_key()) == null_order_key())
|
||||
{
|
||||
return OrderOpResult{ ORDER_ERROR_INVALID_ORDER_DEFINITON,
|
||||
"Scratch order must have either a child order definition or an order to attach to"};
|
||||
}
|
||||
if (!serv.is_attaching())
|
||||
{
|
||||
// if we are not attaching create a child template so we can
|
||||
// quickly launch our child when the time comes.
|
||||
auto child_def = def;
|
||||
*child_def.mutable_custom_def() = def.custom_def().scratch().child();
|
||||
me->child_template = &(serv.make_child_template(child_def));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void ArrivalPriceAlgo::do_launch(IAlgoServices &algo)
|
||||
{
|
||||
me->algo = &algo;
|
||||
update_scratch_threshold();
|
||||
bts_assert(me->child_template);
|
||||
me->child_key = algo.launch_child(*me->child_template, algo.price(), algo.quantity());
|
||||
algo.subscribe_book(SecurityKey(algo.security().id()));
|
||||
}
|
||||
|
||||
void ArrivalPriceAlgo::do_launch_attached(IAlgoServices &algo, OrderKey k, ChildState st)
|
||||
{
|
||||
me->algo = &algo;
|
||||
update_scratch_threshold();
|
||||
me->child_key = k;
|
||||
algo.subscribe_book(SecurityKey(algo.security().id()));
|
||||
on_child_change(k, st);
|
||||
}
|
||||
|
||||
void ArrivalPriceAlgo::do_update(api::orderman::Update const &update)
|
||||
{
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} receiving update: {}", algo().order_key().value(), utils::pb::to_string(update));
|
||||
|
||||
if (update.has_custom() && !update.custom().has_scratch())
|
||||
{
|
||||
algo().terminate_error("Invalid update");
|
||||
return;
|
||||
}
|
||||
|
||||
Update child_update;
|
||||
Price price_to_pass = get_price_to_pass(Price(update.price()));
|
||||
child_update.set_price(price_to_pass.value());
|
||||
child_update.set_quantity(update.quantity());
|
||||
if (update.has_custom())
|
||||
{
|
||||
update_scratch_threshold();
|
||||
auto &scratch_update = update.custom().scratch();
|
||||
*child_update.mutable_custom() = scratch_update.child();
|
||||
}
|
||||
algo().update_child(me->child_key, child_update);
|
||||
|
||||
// If we were not yet scratched it is possible we now can, since we
|
||||
// could have changed the scratch_threshold
|
||||
if (me->status == Status::WAITING_TO_SCRATCH)
|
||||
try_to_scratch();
|
||||
}
|
||||
|
||||
void ArrivalPriceAlgo::on_book(SecurityKey, Book const &b)
|
||||
{
|
||||
me->last_book = b;
|
||||
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} on book. BID: {}@{} ASK: {}@{}",
|
||||
algo().order_key().value(), b.side(api::SIDE_BUY)[0].size(),
|
||||
b.side(api::SIDE_BUY)[0].price(), b.side(api::SIDE_SELL)[0].size(),
|
||||
b.side(api::SIDE_SELL)[0].price());
|
||||
|
||||
switch (me->status)
|
||||
{
|
||||
case Status::WAITING_FOR_MD:
|
||||
{
|
||||
auto other_side = securities::other_side(algo().definition().side());
|
||||
auto &other_side_top = me->last_book.side(other_side)[0];
|
||||
|
||||
if (other_side_top.size() > 0)
|
||||
{
|
||||
me->status = Status::WAITING_TO_SCRATCH;
|
||||
me->book_at_inception = b;
|
||||
LOG(OrderMan, Diag,
|
||||
"ScratchOrder order {} receiving first book: {} Target: {}",
|
||||
algo().order_key().value(), me->scratch_threshold.value(),
|
||||
other_side_top.price());
|
||||
try_to_scratch();
|
||||
}
|
||||
} break;
|
||||
case Status::SCRATCHED:
|
||||
break;
|
||||
case Status::WAITING_TO_SCRATCH:
|
||||
try_to_scratch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrivalPriceAlgo::try_to_scratch()
|
||||
{
|
||||
bts_assert(me->status == Status::WAITING_TO_SCRATCH);
|
||||
auto my_side = algo().definition().side();
|
||||
auto other_side = securities::other_side(my_side);
|
||||
|
||||
Quantity my_quan;
|
||||
auto &my_side_psz = me->last_book.side(my_side)[0];
|
||||
auto &other_side_psz = me->last_book.side(other_side)[0];
|
||||
auto other_side_price = Price(other_side_psz.price());
|
||||
auto inception_other_side_price = Price(me->book_at_inception.side(other_side)[0].price());
|
||||
|
||||
bool market_moved = !securities::is_equal_or_better(other_side, other_side_price, inception_other_side_price);
|
||||
bool on_market = securities::is_same(Price(my_side_psz.price()), Price(algo().price()));
|
||||
if (market_moved || (on_market && my_side_psz.size() <= me->scratch_threshold.value()) )
|
||||
{
|
||||
Price scratch_price = securities::worsen_price(other_side, inception_other_side_price, me->chase_diff);
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} scratching: {}@{}",
|
||||
algo().order_key().value(), algo().quantity().value(), scratch_price);
|
||||
|
||||
// Time to scratch
|
||||
Update child_update;
|
||||
me->scratch_price = scratch_price;
|
||||
child_update.set_price(scratch_price.value());
|
||||
//we still want to try to scratch all of it
|
||||
child_update.set_quantity(algo().quantity().value());
|
||||
algo().update_child(me->child_key, child_update);
|
||||
me->status = Status::SCRATCHED;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(OrderMan, Diag,
|
||||
"ScratchOrder order {} still waiting to scratch. Order: {}@{} "
|
||||
"My side: {}@{}"
|
||||
"Thresh : {}@{}",
|
||||
algo().order_key().value(), algo().quantity().value(), algo().price().value(),
|
||||
my_side_psz.size(), my_side_psz.price(),
|
||||
me->scratch_threshold.value(), my_quan);
|
||||
}
|
||||
}
|
||||
|
||||
Price ArrivalPriceAlgo::get_price_to_pass (Price price) const
|
||||
{
|
||||
Price rv;
|
||||
switch (me->status) {
|
||||
case Status::WAITING_FOR_MD:
|
||||
case Status::WAITING_TO_SCRATCH:
|
||||
rv = price;
|
||||
break;
|
||||
case Status::SCRATCHED:
|
||||
rv = me->scratch_price;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void ArrivalPriceAlgo::update_scratch_threshold()
|
||||
{
|
||||
if (algo().definition().custom_def().scratch().scratch_threshold().quantity_case() ==
|
||||
bts::spark::QuantityMeasure::QuantityCase::QUANTITY_NOT_SET)
|
||||
{
|
||||
algo().terminate_error("Invalid quantity, terminating");
|
||||
return;
|
||||
}
|
||||
me->scratch_threshold = SpreaderUtils::_quantity_threshold(
|
||||
algo().definition().custom_def().scratch().scratch_threshold(), algo().quantity());
|
||||
me->chase_diff = Price(securities::tick_size(
|
||||
algo().security()).value() * algo().definition().custom_def().scratch().chase_ticks());
|
||||
}
|
||||
|
||||
void ArrivalPriceAlgo::on_child_change(OrderKey, ChildState const &st)
|
||||
{
|
||||
algo().update_fill_state(st.total_fills, st.last_price);
|
||||
switch (st.status)
|
||||
{
|
||||
case ChildStatus::WORKING:
|
||||
return;
|
||||
case ChildStatus::COMPLETED:
|
||||
algo().complete();
|
||||
return;
|
||||
case ChildStatus::CANCELED:
|
||||
algo().cancel("Unexpected child cancel");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/orders/algo/IAlgoOrder.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class ArrivalPriceAlgo : public IAlgoOrder
|
||||
{
|
||||
public:
|
||||
ArrivalPriceAlgo();
|
||||
~ArrivalPriceAlgo();
|
||||
|
||||
OrderOpResult do_before_launch(IBeforeLaunchAlgoServices&) override;
|
||||
void do_launch(IAlgoServices &) override;
|
||||
void do_launch_attached(IAlgoServices&,OrderKey, ChildState) override;
|
||||
void do_update(api::orderman::Update const &) override;
|
||||
void on_book(SecurityKey, Book const &) override;
|
||||
void on_child_change(OrderKey, ChildState const &) override;
|
||||
|
||||
private:
|
||||
enum class Status;
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
IAlgoServices& algo() const;
|
||||
|
||||
void update_scratch_threshold();
|
||||
void try_to_scratch();
|
||||
Price get_price_to_pass (Price price) const;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,227 +0,0 @@
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/POVAlgo.h"
|
||||
#include "lib/orderman/orders/algo/IAlgoServices.h"
|
||||
#include "lib/orderman/orders/algo/DynamicHelpers.h"
|
||||
|
||||
#include "lib/orderman/order_factory/IOrderFactory.h"
|
||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderUtils.h"
|
||||
#include "lib/os/os.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
enum class POVAlgo::Status { WAITING_FOR_MD, WAITING_TO_SCRATCH, SCRATCHED };
|
||||
|
||||
struct POVAlgo::PImpl
|
||||
{
|
||||
IAlgoServices *algo;
|
||||
OrderDefinition definition;
|
||||
|
||||
Quantity scratch_threshold;
|
||||
Price chase_diff;
|
||||
Status status = Status::WAITING_FOR_MD;
|
||||
OrderKey child_key = null_order_key();
|
||||
ChildTemplate *child_template = nullptr;
|
||||
Book last_book;
|
||||
Book book_at_inception;
|
||||
Price scratch_price=Price(os::nan());
|
||||
};
|
||||
|
||||
POVAlgo::POVAlgo() : me(new PImpl()) {}
|
||||
POVAlgo::~POVAlgo() {}
|
||||
IAlgoServices &POVAlgo::algo() const { return *me->algo; }
|
||||
|
||||
OrderOpResult POVAlgo::do_before_launch(IBeforeLaunchAlgoServices &serv)
|
||||
{
|
||||
const auto& def = serv.definition();
|
||||
bts_assert(def.has_custom_def());
|
||||
bts_assert(def.custom_def().has_scratch());
|
||||
// Validate the scratch part of the definition
|
||||
auto &scratch = def.custom_def().scratch();
|
||||
if (!scratch.has_child() && OrderKey(def.attach_target_order_key()) == null_order_key())
|
||||
{
|
||||
return OrderOpResult{ ORDER_ERROR_INVALID_ORDER_DEFINITON,
|
||||
"Scratch order must have either a child order definition or an order to attach to"};
|
||||
}
|
||||
if (!serv.is_attaching())
|
||||
{
|
||||
// if we are not attaching create a child template so we can
|
||||
// quickly launch our child when the time comes.
|
||||
auto child_def = def;
|
||||
*child_def.mutable_custom_def() = def.custom_def().scratch().child();
|
||||
me->child_template = &(serv.make_child_template(child_def));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void POVAlgo::do_launch(IAlgoServices &algo)
|
||||
{
|
||||
me->algo = &algo;
|
||||
update_scratch_threshold();
|
||||
bts_assert(me->child_template);
|
||||
me->child_key = algo.launch_child(*me->child_template, algo.price(), algo.quantity());
|
||||
algo.subscribe_book(SecurityKey(algo.security().id()));
|
||||
}
|
||||
|
||||
void POVAlgo::do_launch_attached(IAlgoServices &algo, OrderKey k, ChildState st)
|
||||
{
|
||||
me->algo = &algo;
|
||||
update_scratch_threshold();
|
||||
me->child_key = k;
|
||||
algo.subscribe_book(SecurityKey(algo.security().id()));
|
||||
on_child_change(k, st);
|
||||
}
|
||||
|
||||
void POVAlgo::do_update(api::orderman::Update const &update)
|
||||
{
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} receiving update: {}", algo().order_key().value(), utils::pb::to_string(update));
|
||||
|
||||
if (update.has_custom() && !update.custom().has_scratch())
|
||||
{
|
||||
algo().terminate_error("Invalid update");
|
||||
return;
|
||||
}
|
||||
|
||||
Update child_update;
|
||||
Price price_to_pass = get_price_to_pass(Price(update.price()));
|
||||
child_update.set_price(price_to_pass.value());
|
||||
child_update.set_quantity(update.quantity());
|
||||
if (update.has_custom())
|
||||
{
|
||||
update_scratch_threshold();
|
||||
auto &scratch_update = update.custom().scratch();
|
||||
*child_update.mutable_custom() = scratch_update.child();
|
||||
}
|
||||
algo().update_child(me->child_key, child_update);
|
||||
|
||||
// If we were not yet scratched it is possible we now can, since we
|
||||
// could have changed the scratch_threshold
|
||||
if (me->status == Status::WAITING_TO_SCRATCH)
|
||||
try_to_scratch();
|
||||
}
|
||||
|
||||
void POVAlgo::on_book(SecurityKey, Book const &b)
|
||||
{
|
||||
me->last_book = b;
|
||||
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} on book. BID: {}@{} ASK: {}@{}",
|
||||
algo().order_key().value(), b.side(api::SIDE_BUY)[0].size(),
|
||||
b.side(api::SIDE_BUY)[0].price(), b.side(api::SIDE_SELL)[0].size(),
|
||||
b.side(api::SIDE_SELL)[0].price());
|
||||
|
||||
switch (me->status)
|
||||
{
|
||||
case Status::WAITING_FOR_MD:
|
||||
{
|
||||
auto other_side = securities::other_side(algo().definition().side());
|
||||
auto &other_side_top = me->last_book.side(other_side)[0];
|
||||
|
||||
if (other_side_top.size() > 0)
|
||||
{
|
||||
me->status = Status::WAITING_TO_SCRATCH;
|
||||
me->book_at_inception = b;
|
||||
LOG(OrderMan, Diag,
|
||||
"ScratchOrder order {} receiving first book: {} Target: {}",
|
||||
algo().order_key().value(), me->scratch_threshold.value(),
|
||||
other_side_top.price());
|
||||
try_to_scratch();
|
||||
}
|
||||
} break;
|
||||
case Status::SCRATCHED:
|
||||
break;
|
||||
case Status::WAITING_TO_SCRATCH:
|
||||
try_to_scratch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void POVAlgo::try_to_scratch()
|
||||
{
|
||||
bts_assert(me->status == Status::WAITING_TO_SCRATCH);
|
||||
auto my_side = algo().definition().side();
|
||||
auto other_side = securities::other_side(my_side);
|
||||
|
||||
Quantity my_quan;
|
||||
auto &my_side_psz = me->last_book.side(my_side)[0];
|
||||
auto &other_side_psz = me->last_book.side(other_side)[0];
|
||||
auto other_side_price = Price(other_side_psz.price());
|
||||
auto inception_other_side_price = Price(me->book_at_inception.side(other_side)[0].price());
|
||||
|
||||
bool market_moved = !securities::is_equal_or_better(other_side, other_side_price, inception_other_side_price);
|
||||
bool on_market = securities::is_same(Price(my_side_psz.price()), Price(algo().price()));
|
||||
if (market_moved || (on_market && my_side_psz.size() <= me->scratch_threshold.value()) )
|
||||
{
|
||||
Price scratch_price = securities::worsen_price(other_side, inception_other_side_price, me->chase_diff);
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} scratching: {}@{}",
|
||||
algo().order_key().value(), algo().quantity().value(), scratch_price);
|
||||
|
||||
// Time to scratch
|
||||
Update child_update;
|
||||
me->scratch_price = scratch_price;
|
||||
child_update.set_price(scratch_price.value());
|
||||
//we still want to try to scratch all of it
|
||||
child_update.set_quantity(algo().quantity().value());
|
||||
algo().update_child(me->child_key, child_update);
|
||||
me->status = Status::SCRATCHED;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(OrderMan, Diag,
|
||||
"ScratchOrder order {} still waiting to scratch. Order: {}@{} "
|
||||
"My side: {}@{}"
|
||||
"Thresh : {}@{}",
|
||||
algo().order_key().value(), algo().quantity().value(), algo().price().value(),
|
||||
my_side_psz.size(), my_side_psz.price(),
|
||||
me->scratch_threshold.value(), my_quan);
|
||||
}
|
||||
}
|
||||
|
||||
Price POVAlgo::get_price_to_pass (Price price) const
|
||||
{
|
||||
Price rv;
|
||||
switch (me->status) {
|
||||
case Status::WAITING_FOR_MD:
|
||||
case Status::WAITING_TO_SCRATCH:
|
||||
rv = price;
|
||||
break;
|
||||
case Status::SCRATCHED:
|
||||
rv = me->scratch_price;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void POVAlgo::update_scratch_threshold()
|
||||
{
|
||||
if (algo().definition().custom_def().scratch().scratch_threshold().quantity_case() ==
|
||||
bts::spark::QuantityMeasure::QuantityCase::QUANTITY_NOT_SET)
|
||||
{
|
||||
algo().terminate_error("Invalid quantity, terminating");
|
||||
return;
|
||||
}
|
||||
me->scratch_threshold = SpreaderUtils::_quantity_threshold(
|
||||
algo().definition().custom_def().scratch().scratch_threshold(), algo().quantity());
|
||||
me->chase_diff = Price(securities::tick_size(
|
||||
algo().security()).value() * algo().definition().custom_def().scratch().chase_ticks());
|
||||
}
|
||||
|
||||
void POVAlgo::on_child_change(OrderKey, ChildState const &st)
|
||||
{
|
||||
algo().update_fill_state(st.total_fills, st.last_price);
|
||||
switch (st.status)
|
||||
{
|
||||
case ChildStatus::WORKING:
|
||||
return;
|
||||
case ChildStatus::COMPLETED:
|
||||
algo().complete();
|
||||
return;
|
||||
case ChildStatus::CANCELED:
|
||||
algo().cancel("Unexpected child cancel");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/orders/algo/IAlgoOrder.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class POVAlgo : public IAlgoOrder
|
||||
{
|
||||
public:
|
||||
POVAlgo();
|
||||
~POVAlgo();
|
||||
|
||||
OrderOpResult do_before_launch(IBeforeLaunchAlgoServices&) override;
|
||||
void do_launch(IAlgoServices &) override;
|
||||
void do_launch_attached(IAlgoServices&,OrderKey, ChildState) override;
|
||||
void do_update(api::orderman::Update const &) override;
|
||||
void on_book(SecurityKey, Book const &) override;
|
||||
void on_child_change(OrderKey, ChildState const &) override;
|
||||
|
||||
private:
|
||||
enum class Status;
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
IAlgoServices& algo() const;
|
||||
|
||||
void update_scratch_threshold();
|
||||
void try_to_scratch();
|
||||
Price get_price_to_pass (Price price) const;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,109 +0,0 @@
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/TWAPAlgo.h"
|
||||
#include "lib/orderman/orders/algo/IAlgoServices.h"
|
||||
#include "lib/orderman/orders/algo/DynamicHelpers.h"
|
||||
#include "lib/api/services/OrderService.pb.h"
|
||||
|
||||
#include "lib/orderman/order_factory/IOrderFactory.h"
|
||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderUtils.h"
|
||||
#include "lib/os/os.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
|
||||
struct TWAPAlgo::PImpl
|
||||
{
|
||||
};
|
||||
|
||||
TWAPAlgo::TWAPAlgo() : me(new PImpl()) {}
|
||||
TWAPAlgo::~TWAPAlgo() {}
|
||||
|
||||
OrderOpResult TWAPAlgo::do_before_launch(IBeforeLaunchAlgoServices &serv)
|
||||
{
|
||||
const auto& def = serv.definition();
|
||||
bts_assert(def.has_custom_def());
|
||||
bts_assert(def.custom_def().has_twap());
|
||||
// Validate the algo part of the definition
|
||||
auto &algo = def.custom_def().twap();
|
||||
if (!algo.has_tactical_child() || algo.has_aggressive_child())
|
||||
{
|
||||
return OrderOpResult{ ORDER_ERROR_INVALID_ORDER_DEFINITON,
|
||||
"Algo order must have a tactical and aggressive child order definition"};
|
||||
}
|
||||
if (!serv.is_attaching())
|
||||
{
|
||||
// if we are not attaching create a child template so we can
|
||||
// quickly launch our child when the time comes.
|
||||
auto tchild_def = def;
|
||||
*tchild_def.mutable_custom_def() = def.custom_def().twap().tactical_child();
|
||||
tactical_template() = &(serv.make_child_template(tchild_def));
|
||||
|
||||
auto achild_def = def;
|
||||
*achild_def.mutable_custom_def() = def.custom_def().twap().aggressive_child();
|
||||
aggressive_template() = &(serv.make_child_template(achild_def));
|
||||
|
||||
auto mchild_def = def;
|
||||
mchild_def.mutable_custom_def()->mutable_market();
|
||||
market_template() = &(serv.make_child_template(mchild_def));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void TWAPAlgo::do_launch(IAlgoServices &algo)
|
||||
{
|
||||
set_algo(&algo);
|
||||
update_params();
|
||||
bts_assert(tactical_template());
|
||||
bts_assert(aggressive_template());
|
||||
bts_assert(market_template());
|
||||
|
||||
algo.subscribe_book(SecurityKey(algo.security().id()));
|
||||
algo.subscribe_ticker(SecurityKey(algo.security().id()));
|
||||
algo.subscribe_timer();
|
||||
}
|
||||
|
||||
void TWAPAlgo::do_launch_attached(IAlgoServices &algo, OrderKey k, ChildState st)
|
||||
{
|
||||
set_algo(&algo);
|
||||
update_params();
|
||||
bts_assert(tactical_template());
|
||||
bts_assert(aggressive_template());
|
||||
bts_assert(market_template());
|
||||
|
||||
add_child(k, TimeSlicer::Channel::Tactical);
|
||||
on_child_change(k, st);
|
||||
|
||||
algo.subscribe_book(SecurityKey(algo.security().id()));
|
||||
algo.subscribe_ticker(SecurityKey(algo.security().id()));
|
||||
algo.subscribe_timer();
|
||||
}
|
||||
|
||||
void TWAPAlgo::do_update(const api::orderman::Update& update)
|
||||
{
|
||||
LOG(OrderMan, Diag, "TWAPAlgo order {} receiving update: {}", algo().order_key().value(), utils::pb::to_string(update));
|
||||
_do_update(update, update.custom().twap().tactical_child(), update.custom().twap().aggressive_child());
|
||||
}
|
||||
|
||||
|
||||
void TWAPAlgo::update_params()
|
||||
{
|
||||
if (!algo().definition().custom_def().twap().has_duration())
|
||||
{
|
||||
algo().terminate_error("Invalid duration params, terminating");
|
||||
return;
|
||||
}
|
||||
if (!algo().definition().custom_def().twap().has_aggression())
|
||||
{
|
||||
algo().terminate_error("Invalid aggression params, terminating");
|
||||
return;
|
||||
}
|
||||
duration().CopyFrom(algo().definition().custom_def().twap().duration());
|
||||
//next timer will pick this up
|
||||
}
|
||||
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/TimeSlicer.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class TWAPAlgo : public TimeSlicer
|
||||
{
|
||||
public:
|
||||
TWAPAlgo();
|
||||
~TWAPAlgo();
|
||||
|
||||
OrderOpResult do_before_launch(IBeforeLaunchAlgoServices&) override;
|
||||
void do_launch(IAlgoServices &) override;
|
||||
void do_launch_attached(IAlgoServices&, OrderKey, ChildState) override;
|
||||
void do_update(const api::orderman::Update& update) override;
|
||||
|
||||
protected:
|
||||
void update_params() override;
|
||||
|
||||
protected:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,380 +0,0 @@
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/TimeSlicer.h"
|
||||
#include "lib/orderman/orders/algo/IAlgoServices.h"
|
||||
#include "lib/orderman/orders/algo/DynamicHelpers.h"
|
||||
#include "lib/api/services/OrderService.pb.h"
|
||||
|
||||
#include "lib/orderman/order_factory/IOrderFactory.h"
|
||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderUtils.h"
|
||||
#include "lib/os/os.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
enum class TimeSlicer::Status { WAITING_FOR_MD, WAITING_FOR_START, WORKING, DONE };
|
||||
|
||||
struct OrderDef
|
||||
{
|
||||
OrderKey child_key = null_order_key();
|
||||
uint32_t generation = 0u;
|
||||
TimeSlicer::Channel channel = TimeSlicer::Channel::Tactical;
|
||||
};
|
||||
|
||||
struct TimeSlicer::PImpl
|
||||
{
|
||||
IAlgoServices* algo;
|
||||
|
||||
OrderDuration duration;
|
||||
Status status = Status::WAITING_FOR_MD;
|
||||
google::protobuf::Timestamp start_time, end_time;
|
||||
uint32_t generation = 0; uint32_t expected_generations = 0;
|
||||
|
||||
ChildTemplate* tactical_template = nullptr;
|
||||
ChildTemplate* aggressive_template = nullptr;
|
||||
ChildTemplate* market_template = nullptr;
|
||||
|
||||
std::map<OrderKey, OrderDef> child_orders;
|
||||
std::map<OrderKey, ChildState> child_state;
|
||||
Quantity total_filled = Quantity(0);
|
||||
|
||||
Book last_book;
|
||||
TradeVector last_trades;
|
||||
};
|
||||
OrderDuration& TimeSlicer::duration()
|
||||
{
|
||||
return me->duration;
|
||||
}
|
||||
TimeSlicer::Status& TimeSlicer::status()
|
||||
{
|
||||
return me->status;
|
||||
}
|
||||
google::protobuf::Timestamp& TimeSlicer::start_time()
|
||||
{
|
||||
return me->start_time;
|
||||
}
|
||||
google::protobuf::Timestamp& TimeSlicer::end_time()
|
||||
{
|
||||
return me->end_time;
|
||||
}
|
||||
uint32_t& TimeSlicer::generation()
|
||||
{
|
||||
return me->generation;
|
||||
}
|
||||
uint32_t& TimeSlicer::expected_generations()
|
||||
{
|
||||
return me->expected_generations;
|
||||
}
|
||||
ChildTemplate*& TimeSlicer::tactical_template()
|
||||
{
|
||||
return me->tactical_template;
|
||||
}
|
||||
ChildTemplate*& TimeSlicer::aggressive_template()
|
||||
{
|
||||
return me->aggressive_template;
|
||||
}
|
||||
ChildTemplate*& TimeSlicer::market_template()
|
||||
{
|
||||
return me->market_template;
|
||||
}
|
||||
void TimeSlicer::add_child(OrderKey k, Channel chan)
|
||||
{
|
||||
me->child_orders[k] = OrderDef{ k, me->generation, chan };
|
||||
}
|
||||
Quantity& TimeSlicer::total_filled()
|
||||
{
|
||||
return me->total_filled;
|
||||
}
|
||||
Book& TimeSlicer::last_book()
|
||||
{
|
||||
return me->last_book;
|
||||
}
|
||||
TradeVector& TimeSlicer::last_trades()
|
||||
{
|
||||
return me->last_trades;
|
||||
}
|
||||
|
||||
|
||||
TimeSlicer::TimeSlicer() : me(new PImpl()) {}
|
||||
TimeSlicer::~TimeSlicer() {}
|
||||
IAlgoServices& TimeSlicer::algo() const { return *me->algo; }
|
||||
void TimeSlicer::set_algo(IAlgoServices* value) { me->algo = value; }
|
||||
|
||||
void TimeSlicer::on_book(SecurityKey, const Book& b)
|
||||
{
|
||||
me->last_book = b;
|
||||
|
||||
LOG(OrderMan, Diag, "TimeSlicer order {} on book. BID: {}@{} ASK: {}@{}",
|
||||
algo().order_key().value(), b.side(api::SIDE_BUY)[0].size(),
|
||||
b.side(api::SIDE_BUY)[0].price(), b.side(api::SIDE_SELL)[0].size(),
|
||||
b.side(api::SIDE_SELL)[0].price());
|
||||
|
||||
switch (me->status)
|
||||
{
|
||||
case Status::WAITING_FOR_MD:
|
||||
{
|
||||
me->status = Status::WAITING_FOR_START;
|
||||
}
|
||||
break;
|
||||
case Status::WAITING_FOR_START:
|
||||
case Status::WORKING:
|
||||
case Status::DONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TimeSlicer::_do_update(const api::orderman::Update& update,
|
||||
const bts::api::orderman::CustomOrderDefinition& tactical_update,
|
||||
const bts::api::orderman::CustomOrderDefinition& aggressive_update)
|
||||
|
||||
{
|
||||
LOG(OrderMan, Diag, "TimeSlicer order {} receiving update: {}", algo().order_key().value(), utils::pb::to_string(update));
|
||||
|
||||
if (update.has_custom() && !update.custom().has_twap())
|
||||
{
|
||||
algo().terminate_error("Invalid update");
|
||||
return;
|
||||
}
|
||||
|
||||
Update child_update;
|
||||
child_update.set_price(update.price());
|
||||
child_update.set_quantity(update.quantity());
|
||||
for(auto& i : me->child_orders)
|
||||
{
|
||||
if (update.has_custom())
|
||||
{
|
||||
update_params();
|
||||
if(i.second.channel == Channel::Tactical)
|
||||
*child_update.mutable_custom() = tactical_update;
|
||||
else if(i.second.channel == Channel::Aggressive)
|
||||
*child_update.mutable_custom() = aggressive_update;
|
||||
else if(i.second.channel == Channel::Market) {}
|
||||
else
|
||||
bts_assert_msg(false, "unknown channel type");
|
||||
}
|
||||
algo().update_child(i.first, child_update);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeSlicer::on_ticker(SecurityKey, const TradeVector& vec)
|
||||
{
|
||||
me->last_trades = vec;
|
||||
LOG(OrderMan, Diag, "TimeSlicer order {} on ticker.", algo().order_key().value());
|
||||
}
|
||||
|
||||
google::protobuf::Timestamp TimeSlicer::compute_end_time()
|
||||
{
|
||||
if (me->duration.end_case() == OrderDuration::EndCase::kDurationInMinutes)
|
||||
{
|
||||
google::protobuf::Timestamp eend;
|
||||
eend.set_seconds(me->start_time.seconds() + me->duration.duration_in_minutes() * 60);
|
||||
return eend;
|
||||
}
|
||||
else if (me->duration.end_case() == OrderDuration::EndCase::kEndTimestamp)
|
||||
return me->duration.end_timestamp();
|
||||
else
|
||||
{
|
||||
algo().terminate_error("Unknown end case");
|
||||
return google::protobuf::Timestamp();
|
||||
}
|
||||
}
|
||||
|
||||
void TimeSlicer::setup_schedule()
|
||||
{
|
||||
me->status = Status::WORKING;
|
||||
me->start_time = utils::pb::pb_now();
|
||||
me->end_time = end_time();
|
||||
me->expected_generations = ( me->end_time.seconds() - me->start_time.seconds() ) / me->duration.discretization_interval_in_seconds();
|
||||
if(me->start_time.seconds() > me->end_time.seconds() || me->expected_generations <= 0 || me->expected_generations > 86400)
|
||||
algo().terminate_error("Invalid scheduling data");
|
||||
}
|
||||
|
||||
void TimeSlicer::on_timer()
|
||||
{
|
||||
switch(me->status)
|
||||
{
|
||||
case Status::WAITING_FOR_MD:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case Status::WAITING_FOR_START:
|
||||
{
|
||||
if(me->duration.has_start() && me->duration.start().seconds() > 0)
|
||||
{
|
||||
if (me->duration.start().seconds() < utils::pb::pb_now().seconds())
|
||||
return;
|
||||
}
|
||||
setup_schedule();
|
||||
return;
|
||||
}
|
||||
case Status::WORKING:
|
||||
{
|
||||
if (utils::pb::pb_now().seconds() > me->end_time.seconds())
|
||||
{
|
||||
get_done();
|
||||
return;
|
||||
}
|
||||
if(me->generation++ == 0)
|
||||
first_generation();
|
||||
else
|
||||
next_generation();
|
||||
break;
|
||||
}
|
||||
case Status::DONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeSlicer::report_status()
|
||||
{
|
||||
uint32_t fills = 0u; bool all_complete = true; double price = 0.0; int idx = 0;
|
||||
for(const auto& ch : me->child_state)
|
||||
{
|
||||
fills += ch.second.total_fills.value();
|
||||
if(ch.second.status == ChildStatus::COMPLETED )
|
||||
{
|
||||
price += ch.second.avg_price.value();
|
||||
idx++;
|
||||
}
|
||||
bool complete = (ch.second.status == ChildStatus::COMPLETED || ch.second.status == ChildStatus::CANCELED);
|
||||
if(complete)
|
||||
remove_child(ch.first);
|
||||
all_complete = all_complete && complete;
|
||||
}
|
||||
algo().update_fill_state(Quantity(fills), Price(price / idx));
|
||||
me->total_filled = Quantity(fills);
|
||||
|
||||
if(me->status == Status::DONE)
|
||||
{
|
||||
if(all_complete)
|
||||
algo().complete();
|
||||
}
|
||||
}
|
||||
|
||||
void TimeSlicer::on_child_change(OrderKey key, const ChildState& st)
|
||||
{
|
||||
me->child_state[key] = st;
|
||||
report_status();
|
||||
}
|
||||
|
||||
bool TimeSlicer::validate_price_size(Price price, Quantity size)
|
||||
{
|
||||
if(os::is_nan(price.value()) || size.value() <= 0 || size.value() > algo().quantity().value())
|
||||
{
|
||||
algo().terminate_error("Invalid price or size of gen " + std::to_string(me->generation) + " order");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TimeSlicer::remove_child(OrderKey k)
|
||||
{
|
||||
me->child_orders.erase(k);
|
||||
}
|
||||
|
||||
void TimeSlicer::cancel_and_remove_child(OrderKey k)
|
||||
{
|
||||
algo().cancel_child(k);
|
||||
me->child_orders.erase(k);
|
||||
}
|
||||
|
||||
OrderKey TimeSlicer::send_child(Price price, Quantity size, Channel chan)
|
||||
{
|
||||
OrderKey child_key = null_order_key();
|
||||
if(validate_price_size(price, size))
|
||||
{
|
||||
if(chan == Channel::Tactical)
|
||||
child_key = algo().launch_child(*me->tactical_template, Price(price), Quantity(size));
|
||||
else if(chan == Channel::Aggressive)
|
||||
child_key = algo().launch_child(*me->aggressive_template, Price(price), Quantity(size));
|
||||
else if(chan == Channel::Market)
|
||||
child_key = algo().launch_child(*me->aggressive_template, Price(price), Quantity(size));
|
||||
me->child_orders[child_key] = OrderDef{ child_key, me->generation, chan };
|
||||
}
|
||||
return child_key;
|
||||
}
|
||||
|
||||
OrderKey TimeSlicer::upgrade(OrderKey key, Price price, Channel chan)
|
||||
{
|
||||
cancel_and_remove_child(key);
|
||||
auto cs = me->child_state.find(key);
|
||||
if(cs == me->child_state.end())
|
||||
{
|
||||
algo().terminate_error("can't find child state");
|
||||
return null_order_key();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t quan = cs->second.quantity.value() - cs->second.total_fills.value();
|
||||
return send_child(Price(price), Quantity(quan), chan);
|
||||
}
|
||||
}
|
||||
|
||||
void TimeSlicer::first_generation()
|
||||
{
|
||||
bts_assert_msg(me->generation == 0, "generation 0");
|
||||
|
||||
double price = me->last_book.side( algo().definition().side() )[0].price();
|
||||
uint32_t size = algo().quantity().value() / me->expected_generations;
|
||||
if(me->duration.tactical_schedule_slippage() > 0)
|
||||
send_child(Price(price), Quantity(size), Channel::Tactical);
|
||||
else
|
||||
send_child(Price(price), Quantity(size), Channel::Aggressive);
|
||||
}
|
||||
|
||||
void TimeSlicer::next_generation()
|
||||
{
|
||||
int64_t elapsed = utils::pb::pb_now().seconds() - me->start_time.seconds();
|
||||
double gen = elapsed / me->duration.discretization_interval_in_seconds();
|
||||
if(gen <= me->generation)
|
||||
return;
|
||||
if(me->total_filled.value() >= algo().quantity().value())
|
||||
{
|
||||
get_done(); //early
|
||||
return;
|
||||
}
|
||||
|
||||
me->generation = (uint32_t)gen;
|
||||
double price = me->last_book.side( algo().definition().side() )[0].price();
|
||||
uint32_t size = algo().quantity().value() / me->expected_generations;
|
||||
for(const auto& ch : me->child_orders)
|
||||
{
|
||||
bts_assert_msg(me->generation >= ch.second.generation, "incorrect generation");
|
||||
uint32_t age = me->generation - ch.second.generation;
|
||||
if(age > me->duration.tactical_schedule_slippage())
|
||||
{
|
||||
if(ch.second.channel == Channel::Tactical) //move to aggressive
|
||||
{
|
||||
upgrade(ch.first, Price(price), Channel::Aggressive);
|
||||
}
|
||||
else if(ch.second.channel == Channel::Aggressive) //move to market
|
||||
{
|
||||
upgrade(ch.first, Price(price), Channel::Market);
|
||||
}
|
||||
}
|
||||
}
|
||||
send_child(Price(price), Quantity(size), Channel::Tactical);
|
||||
}
|
||||
|
||||
void TimeSlicer::get_done()
|
||||
{
|
||||
me->status = Status::DONE;
|
||||
|
||||
for(const auto& ch : me->child_orders)
|
||||
cancel_and_remove_child(ch.first);
|
||||
|
||||
if(me->total_filled.value() < algo().quantity().value())
|
||||
{
|
||||
uint32_t make_up = algo().quantity().value() - me->total_filled.value();
|
||||
send_child(Price(0.0), Quantity(make_up), Channel::Market);
|
||||
}
|
||||
report_status();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/orders/algo/IAlgoOrder.h"
|
||||
#include <google/protobuf/timestamp.pb.h>
|
||||
|
||||
namespace bts {
|
||||
namespace api {
|
||||
namespace orderman {
|
||||
class OrderDuration;
|
||||
}
|
||||
}
|
||||
namespace orderman {
|
||||
|
||||
class ChildTemplate;
|
||||
struct OrderDef;
|
||||
|
||||
class TimeSlicer : public IAlgoOrder
|
||||
{
|
||||
public:
|
||||
TimeSlicer();
|
||||
~TimeSlicer();
|
||||
|
||||
void on_child_change(OrderKey, const ChildState&) override;
|
||||
void on_book(SecurityKey, const Book&) override;
|
||||
void on_ticker(SecurityKey, const TradeVector&) override;
|
||||
void on_timer() override;
|
||||
|
||||
protected:
|
||||
enum class Status;
|
||||
enum class Channel { Tactical, Aggressive, Market };
|
||||
|
||||
void set_algo(IAlgoServices*);
|
||||
IAlgoServices& algo() const;
|
||||
|
||||
google::protobuf::Timestamp compute_end_time();
|
||||
void setup_schedule();
|
||||
void get_done();
|
||||
void report_status();
|
||||
|
||||
bool validate_price_size(Price price, Quantity size);
|
||||
OrderKey send_child(Price price, Quantity size, Channel chan);
|
||||
void remove_child(OrderKey k);
|
||||
void cancel_and_remove_child(OrderKey k);
|
||||
OrderKey upgrade(OrderKey key, Price price, Channel chan);
|
||||
|
||||
void _do_update(const api::orderman::Update&,
|
||||
const bts::api::orderman::CustomOrderDefinition& tactical,
|
||||
const bts::api::orderman::CustomOrderDefinition& aggressive);
|
||||
|
||||
protected:
|
||||
virtual void update_params() = 0;
|
||||
virtual void first_generation();
|
||||
virtual void next_generation();
|
||||
|
||||
protected:
|
||||
struct PImpl;
|
||||
friend struct OrderDef;
|
||||
std::unique_ptr<PImpl> me;
|
||||
protected:
|
||||
|
||||
api::orderman::OrderDuration& duration();
|
||||
Status& status();
|
||||
google::protobuf::Timestamp& start_time();
|
||||
google::protobuf::Timestamp& end_time();
|
||||
uint32_t& generation();
|
||||
uint32_t& expected_generations();
|
||||
|
||||
ChildTemplate*& tactical_template();
|
||||
ChildTemplate*& aggressive_template();
|
||||
ChildTemplate*& market_template();
|
||||
|
||||
void add_child(OrderKey k, Channel chan);
|
||||
Quantity& total_filled();
|
||||
Book& last_book();
|
||||
TradeVector& last_trades();
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,227 +0,0 @@
|
||||
#include "lib/orderman/orders/algo/algo_orders/bluex/VWAPAlgo.h"
|
||||
#include "lib/orderman/orders/algo/IAlgoServices.h"
|
||||
#include "lib/orderman/orders/algo/DynamicHelpers.h"
|
||||
|
||||
#include "lib/orderman/order_factory/IOrderFactory.h"
|
||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderUtils.h"
|
||||
#include "lib/os/os.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
enum class VWAPAlgo::Status { WAITING_FOR_MD, WAITING_TO_SCRATCH, SCRATCHED };
|
||||
|
||||
struct VWAPAlgo::PImpl
|
||||
{
|
||||
IAlgoServices *algo;
|
||||
OrderDefinition definition;
|
||||
|
||||
Quantity scratch_threshold;
|
||||
Price chase_diff;
|
||||
Status status = Status::WAITING_FOR_MD;
|
||||
OrderKey child_key = null_order_key();
|
||||
ChildTemplate *child_template = nullptr;
|
||||
Book last_book;
|
||||
Book book_at_inception;
|
||||
Price scratch_price=Price(os::nan());
|
||||
};
|
||||
|
||||
VWAPAlgo::VWAPAlgo() : me(new PImpl()) {}
|
||||
VWAPAlgo::~VWAPAlgo() {}
|
||||
IAlgoServices &VWAPAlgo::algo() const { return *me->algo; }
|
||||
|
||||
OrderOpResult VWAPAlgo::do_before_launch(IBeforeLaunchAlgoServices &serv)
|
||||
{
|
||||
const auto& def = serv.definition();
|
||||
bts_assert(def.has_custom_def());
|
||||
bts_assert(def.custom_def().has_scratch());
|
||||
// Validate the scratch part of the definition
|
||||
auto &scratch = def.custom_def().scratch();
|
||||
if (!scratch.has_child() && OrderKey(def.attach_target_order_key()) == null_order_key())
|
||||
{
|
||||
return OrderOpResult{ ORDER_ERROR_INVALID_ORDER_DEFINITON,
|
||||
"Scratch order must have either a child order definition or an order to attach to"};
|
||||
}
|
||||
if (!serv.is_attaching())
|
||||
{
|
||||
// if we are not attaching create a child template so we can
|
||||
// quickly launch our child when the time comes.
|
||||
auto child_def = def;
|
||||
*child_def.mutable_custom_def() = def.custom_def().scratch().child();
|
||||
me->child_template = &(serv.make_child_template(child_def));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void VWAPAlgo::do_launch(IAlgoServices &algo)
|
||||
{
|
||||
me->algo = &algo;
|
||||
update_scratch_threshold();
|
||||
bts_assert(me->child_template);
|
||||
me->child_key = algo.launch_child(*me->child_template, algo.price(), algo.quantity());
|
||||
algo.subscribe_book(SecurityKey(algo.security().id()));
|
||||
}
|
||||
|
||||
void VWAPAlgo::do_launch_attached(IAlgoServices &algo, OrderKey k, ChildState st)
|
||||
{
|
||||
me->algo = &algo;
|
||||
update_scratch_threshold();
|
||||
me->child_key = k;
|
||||
algo.subscribe_book(SecurityKey(algo.security().id()));
|
||||
on_child_change(k, st);
|
||||
}
|
||||
|
||||
void VWAPAlgo::do_update(api::orderman::Update const &update)
|
||||
{
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} receiving update: {}", algo().order_key().value(), utils::pb::to_string(update));
|
||||
|
||||
if (update.has_custom() && !update.custom().has_scratch())
|
||||
{
|
||||
algo().terminate_error("Invalid update");
|
||||
return;
|
||||
}
|
||||
|
||||
Update child_update;
|
||||
Price price_to_pass = get_price_to_pass(Price(update.price()));
|
||||
child_update.set_price(price_to_pass.value());
|
||||
child_update.set_quantity(update.quantity());
|
||||
if (update.has_custom())
|
||||
{
|
||||
update_scratch_threshold();
|
||||
auto &scratch_update = update.custom().scratch();
|
||||
*child_update.mutable_custom() = scratch_update.child();
|
||||
}
|
||||
algo().update_child(me->child_key, child_update);
|
||||
|
||||
// If we were not yet scratched it is possible we now can, since we
|
||||
// could have changed the scratch_threshold
|
||||
if (me->status == Status::WAITING_TO_SCRATCH)
|
||||
try_to_scratch();
|
||||
}
|
||||
|
||||
void VWAPAlgo::on_book(SecurityKey, Book const &b)
|
||||
{
|
||||
me->last_book = b;
|
||||
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} on book. BID: {}@{} ASK: {}@{}",
|
||||
algo().order_key().value(), b.side(api::SIDE_BUY)[0].size(),
|
||||
b.side(api::SIDE_BUY)[0].price(), b.side(api::SIDE_SELL)[0].size(),
|
||||
b.side(api::SIDE_SELL)[0].price());
|
||||
|
||||
switch (me->status)
|
||||
{
|
||||
case Status::WAITING_FOR_MD:
|
||||
{
|
||||
auto other_side = securities::other_side(algo().definition().side());
|
||||
auto &other_side_top = me->last_book.side(other_side)[0];
|
||||
|
||||
if (other_side_top.size() > 0)
|
||||
{
|
||||
me->status = Status::WAITING_TO_SCRATCH;
|
||||
me->book_at_inception = b;
|
||||
LOG(OrderMan, Diag,
|
||||
"ScratchOrder order {} receiving first book: {} Target: {}",
|
||||
algo().order_key().value(), me->scratch_threshold.value(),
|
||||
other_side_top.price());
|
||||
try_to_scratch();
|
||||
}
|
||||
} break;
|
||||
case Status::SCRATCHED:
|
||||
break;
|
||||
case Status::WAITING_TO_SCRATCH:
|
||||
try_to_scratch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VWAPAlgo::try_to_scratch()
|
||||
{
|
||||
bts_assert(me->status == Status::WAITING_TO_SCRATCH);
|
||||
auto my_side = algo().definition().side();
|
||||
auto other_side = securities::other_side(my_side);
|
||||
|
||||
Quantity my_quan;
|
||||
auto &my_side_psz = me->last_book.side(my_side)[0];
|
||||
auto &other_side_psz = me->last_book.side(other_side)[0];
|
||||
auto other_side_price = Price(other_side_psz.price());
|
||||
auto inception_other_side_price = Price(me->book_at_inception.side(other_side)[0].price());
|
||||
|
||||
bool market_moved = !securities::is_equal_or_better(other_side, other_side_price, inception_other_side_price);
|
||||
bool on_market = securities::is_same(Price(my_side_psz.price()), Price(algo().price()));
|
||||
if (market_moved || (on_market && my_side_psz.size() <= me->scratch_threshold.value()) )
|
||||
{
|
||||
Price scratch_price = securities::worsen_price(other_side, inception_other_side_price, me->chase_diff);
|
||||
LOG(OrderMan, Diag, "ScratchOrder order {} scratching: {}@{}",
|
||||
algo().order_key().value(), algo().quantity().value(), scratch_price);
|
||||
|
||||
// Time to scratch
|
||||
Update child_update;
|
||||
me->scratch_price = scratch_price;
|
||||
child_update.set_price(scratch_price.value());
|
||||
//we still want to try to scratch all of it
|
||||
child_update.set_quantity(algo().quantity().value());
|
||||
algo().update_child(me->child_key, child_update);
|
||||
me->status = Status::SCRATCHED;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(OrderMan, Diag,
|
||||
"ScratchOrder order {} still waiting to scratch. Order: {}@{} "
|
||||
"My side: {}@{}"
|
||||
"Thresh : {}@{}",
|
||||
algo().order_key().value(), algo().quantity().value(), algo().price().value(),
|
||||
my_side_psz.size(), my_side_psz.price(),
|
||||
me->scratch_threshold.value(), my_quan);
|
||||
}
|
||||
}
|
||||
|
||||
Price VWAPAlgo::get_price_to_pass (Price price) const
|
||||
{
|
||||
Price rv;
|
||||
switch (me->status) {
|
||||
case Status::WAITING_FOR_MD:
|
||||
case Status::WAITING_TO_SCRATCH:
|
||||
rv = price;
|
||||
break;
|
||||
case Status::SCRATCHED:
|
||||
rv = me->scratch_price;
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void VWAPAlgo::update_scratch_threshold()
|
||||
{
|
||||
if (algo().definition().custom_def().scratch().scratch_threshold().quantity_case() ==
|
||||
bts::spark::QuantityMeasure::QuantityCase::QUANTITY_NOT_SET)
|
||||
{
|
||||
algo().terminate_error("Invalid quantity, terminating");
|
||||
return;
|
||||
}
|
||||
me->scratch_threshold = SpreaderUtils::_quantity_threshold(
|
||||
algo().definition().custom_def().scratch().scratch_threshold(), algo().quantity());
|
||||
me->chase_diff = Price(securities::tick_size(
|
||||
algo().security()).value() * algo().definition().custom_def().scratch().chase_ticks());
|
||||
}
|
||||
|
||||
void VWAPAlgo::on_child_change(OrderKey, ChildState const &st)
|
||||
{
|
||||
algo().update_fill_state(st.total_fills, st.last_price);
|
||||
switch (st.status)
|
||||
{
|
||||
case ChildStatus::WORKING:
|
||||
return;
|
||||
case ChildStatus::COMPLETED:
|
||||
algo().complete();
|
||||
return;
|
||||
case ChildStatus::CANCELED:
|
||||
algo().cancel("Unexpected child cancel");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/orders/algo/IAlgoOrder.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class VWAPAlgo : public IAlgoOrder
|
||||
{
|
||||
public:
|
||||
VWAPAlgo();
|
||||
~VWAPAlgo();
|
||||
|
||||
OrderOpResult do_before_launch(IBeforeLaunchAlgoServices&) override;
|
||||
void do_launch(IAlgoServices &) override;
|
||||
void do_launch_attached(IAlgoServices&,OrderKey, ChildState) override;
|
||||
void do_update(api::orderman::Update const &) override;
|
||||
void on_book(SecurityKey, Book const &) override;
|
||||
void on_child_change(OrderKey, ChildState const &) override;
|
||||
|
||||
private:
|
||||
enum class Status;
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
IAlgoServices& algo() const;
|
||||
|
||||
void update_scratch_threshold();
|
||||
void try_to_scratch();
|
||||
Price get_price_to_pass (Price price) const;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -150,11 +150,6 @@ In gdb:
|
||||
```
|
||||
(gdb) break order_plugin_example.cpp:366
|
||||
```
|
||||
|
||||
#### In Depth Algo Descriptions
|
||||
|
||||
* [Spark Algo Descriptions](doc/algos.md)
|
||||
* Send us an email for help: api_support@bluetradesys.com
|
||||
|
||||
#### Spark windows client
|
||||
* Download spark windows executable here: <spark_client>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
+++
|
||||
title = "BTS Basic Algos"
|
||||
weight = 3
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
+++
|
||||
|
||||
|
||||
## Lean
|
||||
|
||||
The goal of the lean order is to watch the opposite-inside market size and cross when that size goes below the threshold (this also implies a cross if that size goes to zero and the market trades away from you) If the market trades toward you, you can opt into several different behaviors
|
||||
|
||||
##### Parameters
|
||||
* Cross Thresh - size thresh in absolute or ratio terms
|
||||
* Max Chase Ticks - max levels to pay up, in ticks
|
||||
|
||||
|
||||
## Join
|
||||
The goal of the join order is to watch the opposite-inside market and join when the market flips (that is, when the best offer becomes the best bid) and has at least threshold size.
|
||||
|
||||
##### Parameters
|
||||
* Join Thresh - size thresh in absolute or ratio terms
|
||||
|
||||
|
||||
## Top
|
||||
|
||||
The goal of the top order is to not trade by yourself, but the intent at the time of order entry is to get filled.If the order is on the market (say current bid price) AND the quantity on that bid price is below top thresh then cancel the order else remain working.
|
||||
|
||||
##### Parameters
|
||||
* Top Thresh - size thresh in absolute or ratio terms
|
||||
|
||||
|
||||
## Cover
|
||||
A Cover order’s purpose is to fire a hedge order (of any type) in response to fills from it’s child order on the opposite side of the market N ticks away
|
||||
|
||||
##### Parameters
|
||||
* Profit Ticks - ticks above or below fill price to place profit / cover order
|
||||
|
||||
|
||||
## OCO
|
||||
An OCO order creates a relationship between a child order and a 'stop' or 'other' order such that when one of these is cancelled, both cancel, or when one is filled, the other order's size is debited in the amount of the fill.
|
||||
|
||||
Composing this order with Cover simulates scalping functionality
|
||||
|
||||
##### Parameters
|
||||
* Stop Ticks - ticks below or above main order to place stop / other order
|
||||
Regular → Executable
File mode changed.
@@ -1,14 +1,14 @@
|
||||
qa_sprint_id=18
|
||||
qa_sprint_id=20
|
||||
|
||||
testers=(
|
||||
#'pedro.pinto'
|
||||
# 'eric.harding'
|
||||
'jake.norbut'
|
||||
'michael.harding'
|
||||
# 'jake.norbut'
|
||||
# 'michael.harding'
|
||||
'karl.ellefsen'
|
||||
'pete.fisher'
|
||||
'taha.afzal'
|
||||
'john.colvin'
|
||||
# 'taha.afzal'
|
||||
# 'john.colvin'
|
||||
'kevin.darby'
|
||||
'brian.muhr'
|
||||
)
|
||||
@@ -20,10 +20,9 @@ On Toward=No Change
|
||||
5. Select all the lean orders and change the Trade Toward Behavior to Cancel (don't commit yet).
|
||||
As the parameter is changed its name should turn Green along with a *. Revert back and it should go to
|
||||
No Change. Select a few of the leans and make sure Trade Toward Behavior is No Change. Now Change it
|
||||
to Cancel and commit. Make sure it is set to Cancel for all the lean orders.
|
||||
to Cancel and commit. Make sure it is set to Cancel for all the lean orders. This should cancel all the lean orders.
|
||||
|
||||
6. Move the ask book to 20.040. This should cancel all the leans (verifies the change
|
||||
in 5 made through). Move the market back to 20.050
|
||||
6. Move the market back to 20.050
|
||||
|
||||
7. Enter 2 leans, 4 and 6 lots (configured like 3) at 20.025 and 20.020 respectively. In the orderbook
|
||||
select both and make sure the Price and Size show as - (since they are different). Change the Trade Toward
|
||||
|
||||
Regular → Executable
File mode changed.
@@ -28,3 +28,4 @@ Sym,Mult,Exch
|
||||
"BOB",1000,CBT
|
||||
"BUB",1000,CBT
|
||||
"FNU",1000,CBT
|
||||
"SOM",500,CBT
|
||||
|
Reference in new issue
Block a user