Compare commits
30
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1ed33c2ee | ||
|
|
8bc1455813 | ||
|
|
ecaa04ecf8 | ||
|
|
44e3070544 | ||
|
|
1815950835 | ||
|
|
8762fbf7ce | ||
|
|
0459171d6e | ||
|
|
fcdf72c5d9 | ||
|
|
f5caf0b7ba | ||
|
|
a0f2673b3a | ||
|
|
ba3439b049 | ||
|
|
ae4d7f719b | ||
|
|
64916f6bfc | ||
|
|
1a9dd1c37a | ||
|
|
d77925c568 | ||
|
|
f1f1b68ffb | ||
|
|
835f453f03 | ||
|
|
0eb9518485 | ||
|
|
b5c70fc34e | ||
|
|
a1dba1d7d0 | ||
|
|
efdea5256f | ||
|
|
5df1e5f383 | ||
|
|
99750da31d | ||
|
|
49247dba3f | ||
|
|
a25257cb33 | ||
|
|
b1c180d663 | ||
|
|
6afb16abcb | ||
|
|
995fa3df35 | ||
|
|
18eb28dfd2 | ||
|
|
99cdfadf8d |
No files matched your search
@@ -1 +1 @@
|
||||
set(sources /home/ppinto/Dropbox/bts/spark/doc/user/build.sh;content/_index.md;content/bts_spark/Glossary/_index.md;content/bts_spark/Help/_index.md;content/bts_spark/Help/about_spark.png;content/bts_spark/Help/image39.png;content/bts_spark/Help/image58.png;content/bts_spark/Launcher/_index.md;content/bts_spark/Launcher/image38.png;content/bts_spark/Launcher/image68.png;content/bts_spark/Logging-In-to-the-System/_index.md;content/bts_spark/Logging-In-to-the-System/image3.png;content/bts_spark/Logging-In-to-the-System/image64.png;content/bts_spark/Market/_index.md;content/bts_spark/Market/change_securities.png;content/bts_spark/Market/image11.png;content/bts_spark/Market/image14.png;content/bts_spark/Market/image20.png;content/bts_spark/Market/image21.png;content/bts_spark/Market/image23.png;content/bts_spark/Market/image24.png;content/bts_spark/Market/image34.png;content/bts_spark/Market/image49.png;content/bts_spark/Market/image53.png;content/bts_spark/Market/image66.png;content/bts_spark/Market/image69.png;content/bts_spark/Market/market_view.png;content/bts_spark/Market/settings_icon.png;content/bts_spark/Market/time_and_sales.png;content/bts_spark/My-Windows/_index.md;content/bts_spark/My-Windows/image15.png;content/bts_spark/My-Windows/image16.png;content/bts_spark/My-Windows/image37.png;content/bts_spark/Settings/_index.md;content/bts_spark/Settings/image51.png;content/bts_spark/Settings/image9.png;content/bts_spark/Spreader/_index.md;content/bts_spark/Spreader/image10.png;content/bts_spark/Spreader/image13.png;content/bts_spark/Spreader/image18.png;content/bts_spark/Spreader/image19.png;content/bts_spark/Spreader/image28.png;content/bts_spark/Spreader/image29.png;content/bts_spark/Spreader/image31.png;content/bts_spark/Spreader/image35.png;content/bts_spark/Spreader/image40.png;content/bts_spark/Spreader/image43.png;content/bts_spark/Spreader/image54.png;content/bts_spark/Spreader/image55.png;content/bts_spark/Spreader/image56.png;content/bts_spark/Spreader/image6.png;content/bts_spark/Spreader/image7.png;content/bts_spark/Spreader/image70.png;content/bts_spark/Spreader/image72.png;content/bts_spark/Spreader/image8.png;content/bts_spark/Trading/OrderTypes/index.md;content/bts_spark/Trading/_index.md;content/bts_spark/Trading/algo_studio.png;content/bts_spark/Trading/collapse_all_icon.png;content/bts_spark/Trading/cover_algo_control.png;content/bts_spark/Trading/expand_all_icon.png;content/bts_spark/Trading/image1.png;content/bts_spark/Trading/image17.png;content/bts_spark/Trading/image2.png;content/bts_spark/Trading/image25.png;content/bts_spark/Trading/image27.png;content/bts_spark/Trading/image33.png;content/bts_spark/Trading/image42.png;content/bts_spark/Trading/image44.png;content/bts_spark/Trading/image47.png;content/bts_spark/Trading/image48.png;content/bts_spark/Trading/image5.png;content/bts_spark/Trading/image50.png;content/bts_spark/Trading/image52.png;content/bts_spark/Trading/image57.png;content/bts_spark/Trading/image59.png;content/bts_spark/Trading/image60.png;content/bts_spark/Trading/image61.png;content/bts_spark/Trading/image62.png;content/bts_spark/Trading/image73.png;content/bts_spark/Trading/image74.png;content/bts_spark/Trading/join_algo_control.png;content/bts_spark/Trading/ladder.png;content/bts_spark/Trading/ladder_badges.png;content/bts_spark/Trading/ladder_main_part.png;content/bts_spark/Trading/lean_algo_control.png;content/bts_spark/Trading/mini_orderbook.png;content/bts_spark/Trading/oco_algo_control.png;content/bts_spark/Trading/offset_algo_control.png;content/bts_spark/Trading/pnl_calculation.png;content/bts_spark/Trading/pnl_window.png;content/bts_spark/Trading/recreate_icon.png;content/bts_spark/Trading/settings_icon.png;content/bts_spark/Trading/spark_menu_order_book.png;content/bts_spark/Trading/top_algo_control.png;content/bts_spark/Trading/trigger_algo_control.png;content/bts_spark/_index.md;content/release_notes/_index.md;content/system_requirements/_index.md;static/book.js;static/favicon.ico;static/image.js;templates/index.html;templates/page.html;templates/section.html;templates/shortcodes/back_button.html)
|
||||
set(sources /home/ppinto/Dropbox/bts/spark/doc/user/build.sh;content/_index.md;content/bts_spark/Algos/_index.md;content/bts_spark/Glossary/index.md;content/bts_spark/Help/about_spark.png;content/bts_spark/Help/image39.png;content/bts_spark/Help/image58.png;content/bts_spark/Help/index.md;content/bts_spark/Launcher/image38.png;content/bts_spark/Launcher/image68.png;content/bts_spark/Launcher/index.md;content/bts_spark/Logging-In-to-the-System/image3.png;content/bts_spark/Logging-In-to-the-System/image64.png;content/bts_spark/Logging-In-to-the-System/index.md;content/bts_spark/Market/change_securities.png;content/bts_spark/Market/image11.png;content/bts_spark/Market/image14.png;content/bts_spark/Market/image20.png;content/bts_spark/Market/image21.png;content/bts_spark/Market/image23.png;content/bts_spark/Market/image24.png;content/bts_spark/Market/image34.png;content/bts_spark/Market/image49.png;content/bts_spark/Market/image53.png;content/bts_spark/Market/image66.png;content/bts_spark/Market/image69.png;content/bts_spark/Market/index.md;content/bts_spark/Market/market_view.png;content/bts_spark/Market/settings_icon.png;content/bts_spark/Market/time_and_sales.png;content/bts_spark/My-Windows/image15.png;content/bts_spark/My-Windows/image16.png;content/bts_spark/My-Windows/image37.png;content/bts_spark/My-Windows/index.md;content/bts_spark/Settings/image51.png;content/bts_spark/Settings/image9.png;content/bts_spark/Settings/index.md;content/bts_spark/Spreader/image10.png;content/bts_spark/Spreader/image13.png;content/bts_spark/Spreader/image18.png;content/bts_spark/Spreader/image19.png;content/bts_spark/Spreader/image28.png;content/bts_spark/Spreader/image29.png;content/bts_spark/Spreader/image31.png;content/bts_spark/Spreader/image35.png;content/bts_spark/Spreader/image40.png;content/bts_spark/Spreader/image43.png;content/bts_spark/Spreader/image54.png;content/bts_spark/Spreader/image55.png;content/bts_spark/Spreader/image56.png;content/bts_spark/Spreader/image6.png;content/bts_spark/Spreader/image7.png;content/bts_spark/Spreader/image70.png;content/bts_spark/Spreader/image72.png;content/bts_spark/Spreader/image8.png;content/bts_spark/Spreader/index.md;content/bts_spark/Trading/algo_studio.png;content/bts_spark/Trading/collapse_all_icon.png;content/bts_spark/Trading/cover_algo_control.png;content/bts_spark/Trading/expand_all_icon.png;content/bts_spark/Trading/image1.png;content/bts_spark/Trading/image17.png;content/bts_spark/Trading/image2.png;content/bts_spark/Trading/image25.png;content/bts_spark/Trading/image27.png;content/bts_spark/Trading/image33.png;content/bts_spark/Trading/image42.png;content/bts_spark/Trading/image44.png;content/bts_spark/Trading/image47.png;content/bts_spark/Trading/image48.png;content/bts_spark/Trading/image5.png;content/bts_spark/Trading/image50.png;content/bts_spark/Trading/image52.png;content/bts_spark/Trading/image57.png;content/bts_spark/Trading/image59.png;content/bts_spark/Trading/image60.png;content/bts_spark/Trading/image61.png;content/bts_spark/Trading/image62.png;content/bts_spark/Trading/image73.png;content/bts_spark/Trading/image74.png;content/bts_spark/Trading/index.md;content/bts_spark/Trading/join_algo_control.png;content/bts_spark/Trading/ladder.png;content/bts_spark/Trading/ladder_badges.png;content/bts_spark/Trading/ladder_main_part.png;content/bts_spark/Trading/lean_algo_control.png;content/bts_spark/Trading/mini_orderbook.png;content/bts_spark/Trading/oco_algo_control.png;content/bts_spark/Trading/offset_algo_control.png;content/bts_spark/Trading/pnl_calculation.png;content/bts_spark/Trading/pnl_window.png;content/bts_spark/Trading/recreate_icon.png;content/bts_spark/Trading/settings_icon.png;content/bts_spark/Trading/spark_menu_order_book.png;content/bts_spark/Trading/top_algo_control.png;content/bts_spark/Trading/trigger_algo_control.png;content/bts_spark/_index.md;content/release_notes/_index.md;content/system_requirements/_index.md;static/book.js;static/favicon.ico;static/image.js;templates/index.html;templates/page.html;templates/section.html;templates/shortcodes/back_button.html)
|
||||
@@ -4,17 +4,6 @@ weight = 3
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
+++
|
||||
## 2.8.3
|
||||
### Bug Fixes
|
||||
- Fixed a bug that could cause an OrderBook's Security column filter to be blank
|
||||
- Fixed a bug that could cause a UI failure when clearing a filter selection on a filtering widget
|
||||
## 2.8.2
|
||||
### Bug Fixes
|
||||
- Added proper display factors for SOM spreads
|
||||
- Fixed a bug that could cause a UI failure when trying to change settings in a synthetic ladder
|
||||
## 2.8.1
|
||||
### Bug fixes
|
||||
- Fixed an error in the UI grids filtering widget
|
||||
## 2.8.0
|
||||
### User Visible Changes
|
||||
- Added ProRata and Scratch algos
|
||||
@@ -27,7 +16,6 @@ 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: b09d4c035b...e13bb5d8df.
+1
-1
Submodule externals updated: 6b8c745fb2...67a79263ba.
+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().OnDispatcher().SubscribeEach(a => {
|
||||
algo == null ? null : new CompositeDisposable(algo.observe_algo_root().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().OnDispatcher().SubscribeEach(a => {
|
||||
s.subscribe_selected_algo().SubscribeEach(a => {
|
||||
s.value = a;
|
||||
child_rows.clear_collections();
|
||||
return _wrap_rows(a, selector_wrapper, child_rows, include_algo_type_rows);
|
||||
|
||||
@@ -194,27 +194,20 @@ 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, 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))) { }
|
||||
public LadderFavoriteAlgosSettings(AlgoKey[] favorite_algos, int column_count)
|
||||
: this(ArrayHelper.safe_convert(favorite_algos, k => new bts.persist.algo.AlgoPersistedKey(k.persisted)), column_count) { }
|
||||
|
||||
LadderFavoriteAlgosSettings(bts.persist.algo.AlgoPersistedKey[] favorite_algos, int column_count, bts.persist.algo.AlgoPersistedKey[] stickied_algos) {
|
||||
LadderFavoriteAlgosSettings(bts.persist.algo.AlgoPersistedKey[] favorite_algos, int column_count) {
|
||||
_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) &&
|
||||
stickied_algos.SequenceEqual(other.stickied_algos);
|
||||
favorite_algos.SequenceEqual(other.favorite_algos);
|
||||
|
||||
public override bool Equals(object obj) =>
|
||||
EqualityComparer.equals_obj(this, obj);
|
||||
@@ -222,8 +215,7 @@ namespace mbts.spark {
|
||||
public override int GetHashCode() =>
|
||||
EqualityComparer.aggregate_hash(
|
||||
column_count,
|
||||
EqualityComparer.aggregate_hash_limited(favorite_algos),
|
||||
EqualityComparer.aggregate_hash_limited(stickied_algos));
|
||||
EqualityComparer.aggregate_hash_limited(favorite_algos));
|
||||
|
||||
public static bool operator ==(LadderFavoriteAlgosSettings a, LadderFavoriteAlgosSettings b) => a.Equals(b);
|
||||
public static bool operator !=(LadderFavoriteAlgosSettings a, LadderFavoriteAlgosSettings b) => !a.Equals(b);
|
||||
@@ -281,7 +273,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, null);
|
||||
favorite_algos = new LadderFavoriteAlgosSettings(null, 2);
|
||||
show_warn_on_cross = _default_show_warn_on_cross;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ 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;
|
||||
@@ -23,7 +22,6 @@ 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;
|
||||
@@ -40,7 +38,7 @@ namespace bts.shell {
|
||||
OrdersModel orders_model,
|
||||
MBOService mbo)
|
||||
|
||||
: base(owner, "SparkLadder", 2) {
|
||||
: base(owner, "SparkLadder") {
|
||||
_bus = bus;
|
||||
_wm = wm;
|
||||
_settings_hub = settings_hub;
|
||||
@@ -62,16 +60,6 @@ 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,7 +2,6 @@
|
||||
using bts.api;
|
||||
using bts.api.orderman;
|
||||
using bts.collections;
|
||||
using bts.persist.algo;
|
||||
using bts.shell.orderbook;
|
||||
using bts.utils;
|
||||
using mbts.collections;
|
||||
@@ -137,7 +136,7 @@ namespace mbts.spark {
|
||||
c.PropertyChanged -= on_prop_changed;
|
||||
}
|
||||
AccountTuple? account_factory(KeyValuePair<uint, string> kv) => new AccountTuple(kv.Key, kv.Value);
|
||||
AlgoDefinitionVM algo_factory(AlgoData data) => AlgoDefinitionVM.create(_model, data, is_synthetic ? AlgoFormats.Spreader : AlgoFormats.Exchange);
|
||||
AlgoDefinitionVM algo_factory(AlgoData data) => AlgoDefinitionVM.create(_model, data);
|
||||
}
|
||||
|
||||
public event Action result_changed;
|
||||
@@ -724,15 +723,12 @@ 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; }
|
||||
@@ -749,17 +745,6 @@ 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() =>
|
||||
@@ -768,13 +753,7 @@ namespace mbts.spark {
|
||||
.Where(k => k.HasValue && k.Value.is_persisted)
|
||||
.Select(k => k.Value)
|
||||
.ToArray(),
|
||||
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());
|
||||
column_count);
|
||||
|
||||
FavoriteAlgoItem _item_factory() =>
|
||||
new FavoriteAlgoItem(_algo_definitions, new ListCollectionView<AlgoDefinitionVM>(_algo_definitions) {
|
||||
@@ -787,7 +766,6 @@ namespace mbts.spark {
|
||||
public static readonly FavoriteAlgoItem AddButtonPlaceholderItem = new _AddButtonPlaceholderItem();
|
||||
|
||||
internal readonly KeyedItemSelector<AlgoDefinitionVM, AlgoKey> selector;
|
||||
bool _is_sticky;
|
||||
|
||||
protected FavoriteAlgoItem() { }
|
||||
|
||||
@@ -798,7 +776,6 @@ 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,11 +1,9 @@
|
||||
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;
|
||||
@@ -34,7 +32,6 @@ 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;
|
||||
@@ -136,7 +133,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 AsyncCommand<(double price, Side? side, MouseButton button)>(send_order_async);
|
||||
send_order_command = new DelegateCommand<(double price, Side? side, MouseButton button)>(send_order);
|
||||
cancel_command = new AsyncCommand<LadderModel.CancelType>(_model.cancel_orders, true);
|
||||
show_book_command = new DelegateCommand(_show_book);
|
||||
show_ticket_command = new DelegateCommand(_show_ticket);
|
||||
@@ -226,10 +223,7 @@ 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 => {
|
||||
_sticky_algos.SetItems(s.favorite_algos.stickied_algos);
|
||||
order_properties_vm.on_favorite_algos(s.favorite_algos);
|
||||
}),
|
||||
settings.OnDispatcher().Subscribe(s => order_properties_vm.on_favorite_algos(s.favorite_algos)),
|
||||
order_properties_vm,
|
||||
position_src.OnDispatcher().Subscribe(pos => {
|
||||
double total, day;
|
||||
@@ -406,19 +400,20 @@ namespace mbts.spark {
|
||||
settings_invalidated?.Invoke();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task send_order_async(Side side, uint size, double price) {
|
||||
@@ -438,13 +433,6 @@ 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,7 +805,6 @@
|
||||
<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}">
|
||||
@@ -815,7 +814,6 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<CheckBox Grid.Column="2" VerticalAlignment="Center" VerticalContentAlignment="Center" IsChecked="{Binding is_sticky}"> Stay Enabled?</CheckBox>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</u:KeyedTemplateSelector.Default>
|
||||
@@ -825,7 +823,6 @@
|
||||
<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,54 +631,25 @@ 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 = 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,
|
||||
};
|
||||
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);
|
||||
|
||||
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,7 +60,6 @@ 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;
|
||||
@@ -69,7 +68,6 @@ 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);
|
||||
@@ -239,15 +237,11 @@ 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)
|
||||
@@ -283,18 +277,6 @@ 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 {
|
||||
@@ -371,7 +353,6 @@ 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) =>
|
||||
@@ -390,4 +371,4 @@ namespace mbts.spark {
|
||||
algo_definitions_view.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,14 +34,13 @@ 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 try_upgrade_state(load_stream, version);
|
||||
return null;
|
||||
}
|
||||
public void save(T data, Stream output) {
|
||||
var header = new ShellSerializationHeader() {
|
||||
|
||||
@@ -110,11 +110,10 @@ namespace mbts.spark.filters {
|
||||
|
||||
class DynamicItemsFilter<TRow, TValue, TState> : FilterVMBase<TRow, TValue, TState>, IDisposable {
|
||||
readonly IEqualityComparer<TValue> _equality_comparer;
|
||||
readonly IComparer<TValue> _comparer;
|
||||
readonly Func<ISet<TValue>, TState> _get_state;
|
||||
readonly Func<TState, IObservable<IEnumerable<TValue>>> _load_state;
|
||||
readonly HashSet<TValue> _items_set, _selected_items_set;
|
||||
readonly ObservableCollection<TValue> _items = new ObservableCollection<TValue>();
|
||||
readonly ObservableCollection<TValue> _unsorted_items;
|
||||
bool _override_desired_selection;
|
||||
IDisposable _desired_items_sub, _items_sub;
|
||||
|
||||
@@ -130,7 +129,7 @@ namespace mbts.spark.filters {
|
||||
//
|
||||
_items_sub = items.OnDispatcher().Subscribe(new_items => {
|
||||
_items_set.SetItems(new_items.Concat(_selected_items_set));
|
||||
_sync_items();
|
||||
_unsorted_items.sync_with(_items_set);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -149,7 +148,7 @@ namespace mbts.spark.filters {
|
||||
_items_set.Remove(v);
|
||||
foreach (var v in update.added)
|
||||
_items_set.Add(v);
|
||||
_sync_items();
|
||||
_unsorted_items.sync_with(_items_set);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -165,12 +164,11 @@ namespace mbts.spark.filters {
|
||||
_get_state = get_state;
|
||||
_load_state = load_state;
|
||||
_equality_comparer = equality_comparer;
|
||||
_comparer = comparer;
|
||||
_selected_items_set = new HashSet<TValue>(_equality_comparer);
|
||||
_items_set = new HashSet<TValue>(_equality_comparer);
|
||||
items = ObservableAutoWrapper.create_read_only_wrapper(_items);
|
||||
_unsorted_items = new ObservableCollection<TValue>();
|
||||
items = comparer != null ? ObservableAutoWrapper.create_sorted_wrapper(_unsorted_items, comparer) : ObservableAutoWrapper.create_read_only_wrapper(_unsorted_items);
|
||||
selected_items.CollectionChanged += _on_selected_items_CollectionChanged;
|
||||
_sync_items();
|
||||
}
|
||||
|
||||
public IReadOnlyObservableCollection<TValue> items { get; }
|
||||
@@ -240,11 +238,9 @@ namespace mbts.spark.filters {
|
||||
var copy = new HashSet<TValue>(_selected_items_set, _equality_comparer);
|
||||
_selected_items_set.SetItems(dsi);
|
||||
using (selected_items.SuspendHandler(_on_selected_items_CollectionChanged)) {
|
||||
var to_add = _selected_items_set.Where(_items_set.Add);
|
||||
if (_comparer != null) {
|
||||
_items.InsertSorted(to_add, _comparer);
|
||||
} else {
|
||||
_items.AddRange(to_add);
|
||||
foreach (var item in _selected_items_set) {
|
||||
if (_items_set.Add(item))
|
||||
_unsorted_items.Add(item);
|
||||
}
|
||||
selected_items.sync_with(_selected_items_set);
|
||||
}
|
||||
@@ -252,14 +248,6 @@ namespace mbts.spark.filters {
|
||||
_raise_filter_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void _sync_items() {
|
||||
if (_comparer != null) {
|
||||
_items.sync_with(_items_set.Ordered(_comparer));
|
||||
} else {
|
||||
_items.sync_with(_items_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TableUpdateItemsFilter<TRow, TValue, TKey, TState> : FilterVMBase<TRow, TValue, TState>, IObserver<TableUpdate<TValue, TKey>> where TKey : struct, IEquatable<TKey> {
|
||||
|
||||
@@ -101,8 +101,7 @@ namespace mbts.ui.controls
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
if (e.OldItems != null) foreach (var item in e.OldItems) _set_is_selected(item, false);
|
||||
if (e.NewItems != null) foreach (var item in e.NewItems) _set_is_selected(item, true); break;
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
if (ItemsSource != null) foreach (var item in ItemsSource) _set_is_selected(item, false); break;
|
||||
case NotifyCollectionChangedAction.Reset: foreach (var item in ItemsSource) _set_is_selected(item, false); break;
|
||||
}
|
||||
_update_is_all_selected();
|
||||
}
|
||||
|
||||
@@ -236,12 +236,12 @@ namespace mbts.ui {
|
||||
throw new NotImplementedException("This ICommand does not implement IRaiseCanExecuteChanged");
|
||||
}
|
||||
|
||||
public static Task ExecuteAsync(this ICommand command, object parameter) {
|
||||
public static async Task ExecuteAsync(this ICommand command, object parameter) {
|
||||
ExceptionAssert.Argument.NotNull(command, nameof(command));
|
||||
if (command is IAsyncCommand acmd)
|
||||
return acmd.Execute(parameter);
|
||||
await acmd.Execute(parameter);
|
||||
else
|
||||
return Task.Run(() => command.Execute(parameter));
|
||||
await 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, target_value: ns.value));
|
||||
profiles.Add(_local_profile = new ProfileVM(0, vm_factory(init), "Custom", template_key: ShellSettingsDialog.LocalProfileItemTemplateKey, target_value: init));
|
||||
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));
|
||||
_selected_profile = backing(nameof(selected_profile), _local_profile);
|
||||
// dialog skirt items
|
||||
_apply_item = new DialogSkirtItem("Apply", new DelegateCommand(apply));
|
||||
@@ -325,37 +325,26 @@ 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, T target_value = null) {
|
||||
public ProfileVM(uint id, TVM value, string name, SecurityCriteria security_criteria = null, string template_key = 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 {
|
||||
@@ -391,26 +380,21 @@ 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() {
|
||||
@@ -418,7 +402,6 @@ namespace mbts.spark {
|
||||
_load_from(_committed);
|
||||
_last_result = _committed;
|
||||
}
|
||||
_on_value_changed();
|
||||
}
|
||||
|
||||
public IObservable<bool> subscribe_is_dirty() => _is_dirty.observe_current(true);
|
||||
@@ -431,7 +414,6 @@ namespace mbts.spark {
|
||||
public override string ToString() => _name;
|
||||
|
||||
void _load_from(SettingsProfile<T> data) {
|
||||
_target_value = data.value;
|
||||
name = data.name;
|
||||
security_criteria = data.security_criteria;
|
||||
value.load_from(data.value);
|
||||
|
||||
@@ -197,7 +197,6 @@ namespace mbts.spark {
|
||||
static class TickStore {
|
||||
public static readonly RegionalTickFactors default_rtf = new RegionalTickFactors(new TickFactors(1000, 1), new TickFactors(1000, 1), double.MaxValue);
|
||||
static readonly ConcurrentDictionary<SpecKey, RegionalTickFactors> _exchange_ticks = new ConcurrentDictionary<SpecKey, RegionalTickFactors>();
|
||||
static readonly bool _som_ticks_fix_enabled = config.Configuration.get<bts.config.toggles.SOMTicksFix>().enabled;
|
||||
|
||||
public static RegionalTickFactors get(ContractSpecification spec) =>
|
||||
_exchange_ticks.GetOrAdd(new SpecKey(spec), _create_rtf);
|
||||
@@ -250,23 +249,8 @@ namespace mbts.spark {
|
||||
var tf = _try_create_tf(tick_size, tick_base);
|
||||
if (tf != null && display_digits_override > 0) {
|
||||
int display_digit_diff = (int)display_digits_override - tf.display_digits();
|
||||
if (_som_ticks_fix_enabled) {
|
||||
// we can always add display_digits (i.e. dislpay_digit_diff > 0), of course the ticks can be expressed precisely with extra 0s.
|
||||
// but if we are going to remove display_digits (i.e display_digit_diff < 0), we must make sure the tick_unit is large enough to be expressed precisely with that many fewer digits
|
||||
// - "-display_digit_diff <= Math.Ceiling(Math.Log10(tf.tick_unit))" will tell us if the digits can be removed without compromising precision
|
||||
// - unfortunately, we cannot rely on the exchange's ContractSpec for this, there is 1 known case where the data they give us is incorrect
|
||||
// SOM spreads ContractSpec (from the exchange):
|
||||
// LowTick: 0.0025 (aka 1/400, or 2/800)
|
||||
// MainFraction: 8
|
||||
// SubFraction: 0
|
||||
// PriceDisplayFormat: 1
|
||||
// - as you can see, this cannot possibly be formatted with 1 display digit, it ticks in increments of 1/400
|
||||
// - in practice, to maintain the '8' base, we format this in increments of 2/800 (e.g. 1-000, 1-002, 1-004, and so on up to 1-778, 2-000)
|
||||
if (display_digit_diff > 0 || (display_digit_diff < 0 && -display_digit_diff <= Math.Ceiling(Math.Log10(tf.tick_unit))))
|
||||
tf = _inflate_to_base(tf, tf.tick_base * Math.Pow(10, display_digit_diff));
|
||||
} else if (display_digit_diff != 0) {
|
||||
if (display_digit_diff != 0)
|
||||
tf = _inflate_to_base(tf, tf.tick_base * Math.Pow(10, display_digit_diff));
|
||||
}
|
||||
}
|
||||
return tf;
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;jetfix/codec/FIXArray.cpp;jetfix/common/OutFIX.cpp;jetfix/connection/AsyncReader.cpp;jetfix/connection/IConnection.cpp;jetfix/connection/SocketConnection.cpp;jetfix/gateway/CoreGateway.cpp;jetfix/gateway/JetFIXGateway.cpp;jetfix/gateway/Session.cpp;jetfix/store/FIXFileStore.cpp;jetfix/store/session_name.cpp;jetfix/tests/async_reader_tests.cpp;jetfix/tests/decoding_tests.cpp;jetfix/tests/fix_encoding_stream_tests.cpp;jetfix/tests/fix_fragment_tests.cpp;jetfix/tests/jetfix_performance_tests.cpp;jetfix/tests/sample_fix.cpp;jetfix/tests/store_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;mercury/actors/IPollableActor.cpp;mercury/broker/Broker.cpp;mercury/broker/BrokerProxy.cpp;mercury/broker/ILocalBroker.cpp;mercury/broker/IRemoteBroker.cpp;mercury/common/mercury_common.cpp;mercury/events/TimerEvent.cpp;mercury/executor/Executor.cpp;mercury/topics/Topic.cpp;metrics/metrics.cpp;metrics/system_metrics.cpp;orderman/actors/AsyncFactory.cpp;orderman/actors/ExecutionGateway.cpp;orderman/actors/FillStore.cpp;orderman/actors/MDSupplementarySource.cpp;orderman/actors/OrderStore.cpp;orderman/actors/SODPosition.cpp;orderman/actors/SecuritySrc.cpp;orderman/actors/ServiceBridge.cpp;orderman/actors/order_manager/OrderBuilder.cpp;orderman/actors/order_manager/OrderMLine truncated
|
||||
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;jetfix/codec/FIXArray.cpp;jetfix/common/OutFIX.cpp;jetfix/connection/AsyncReader.cpp;jetfix/connection/IConnection.cpp;jetfix/connection/SocketConnection.cpp;jetfix/gateway/CoreGateway.cpp;jetfix/gateway/JetFIXGateway.cpp;jetfix/gateway/Session.cpp;jetfix/store/FIXFileStore.cpp;jetfix/store/session_name.cpp;jetfix/tests/async_reader_tests.cpp;jetfix/tests/decoding_tests.cpp;jetfix/tests/fix_encoding_stream_tests.cpp;jetfix/tests/fix_fragment_tests.cpp;jetfix/tests/jetfix_performance_tests.cpp;jetfix/tests/sample_fix.cpp;jetfix/tests/store_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;mercury/actors/IPollableActor.cpp;mercury/broker/Broker.cpp;mercury/broker/BrokerProxy.cpp;mercury/broker/ILocalBroker.cpp;mercury/broker/IRemoteBroker.cpp;mercury/common/mercury_common.cpp;mercury/events/TimerEvent.cpp;mercury/executor/Executor.cpp;mercury/topics/Topic.cpp;metrics/metrics.cpp;metrics/system_metrics.cpp;orderman/actors/AsyncFactory.cpp;orderman/actors/ExecutionGateway.cpp;orderman/actors/FillStore.cpp;orderman/actors/MDSupplementarySource.cpp;orderman/actors/OrderStore.cpp;orderman/actors/SODPosition.cpp;orderman/actors/SecuritySrc.cpp;orderman/actors/ServiceBridge.cpp;orderman/actors/order_manager/OrderBuilder.cpp;orderman/actors/order_manager/OrderMLine truncated
|
||||
@@ -1 +1 @@
|
||||
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/service_helpers/AlgoServiceUtils.cpp;api/services/AdminService.proto;api/services/AlgoDefinitionService.proto;api/services/AlgoService.proto;api/services/ApiUnitTestService.proto;api/services/AuthService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MBOService.proto;api/services/MarginService.proto;api/services/MarketDataAuxiliaryService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cme_reference_data.conf;config/defaults/edge.conf;config/defaults/jetfix.conf;config/defaults/keycode.conf;config/defaults/logging.conf;config/defaults/orderman_cfg.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/span.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/threads.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cme_reference_data.proto;config/protos/jetfix.proto;config/protos/keycode.proto;config/protos/logging.proto;config/protos/mercury_cfg.proto;config/protos/orderman_cfg.proto;config/protos/orders_fills_cleanup.proto;config/protos/perflog_cfg.proto;config/protos/quickbus_cfg.proto;config/protos/span.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/threads.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPeriodicDumper.cpp;md/Diag/ShmDumper.cpp;md/MBOProcessor.cpp;md/MBOServiceServer.cpp;md/MDClient.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityCache.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SecurityMapper.cpp;md/SecurityOracle.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/ice/ICEUtils.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/mbo_tests.cpp;md/test/md2_tests.cpp;md/test/md_test_utils.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/AuthSessionManager.cpp;utils/AuthToken.cpp;utils/Dispatcher.cpp;utils/GrowableSPSCQueue.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/crypto/CipherType.cpp;utils/crypto/CryptoInit.cpp;utils/crypto/Digest.cpp;utils/crypto/KeyCodeHelper.cpp;utils/crypto/PasswordCallback.cpp;utils/crypto/PrivaLine truncated
|
||||
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
|
||||
@@ -141,4 +141,3 @@ if (WIN32)
|
||||
include(${CMAKE_SOURCE_DIR}/tools/vs_filters.cmake)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
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,6 +105,11 @@ message CustomOrderDefinition
|
||||
ScratchOrderDefinition scratch = 31;
|
||||
ProRataOrderDefinition prorata = 32;
|
||||
|
||||
TWAPOrderDefinition twap = 100;
|
||||
VWAPOrderDefinition vwap = 101;
|
||||
POVOrderDefinition pov = 102;
|
||||
ArrivalPriceOrderDefinition arrival = 103;
|
||||
|
||||
DynamicOrderDefinition dynamic = 1000;
|
||||
}
|
||||
}
|
||||
@@ -230,6 +235,89 @@ 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;
|
||||
@@ -286,6 +374,11 @@ 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
|
||||
}
|
||||
}
|
||||
@@ -366,6 +459,10 @@ message ProRataOrderState {}
|
||||
message DynamicOrderState {}
|
||||
message QueueHolderState {}
|
||||
message SplitterOrderState {}
|
||||
message TWAPOrderState {}
|
||||
message VWAPOrderState {}
|
||||
message POVOrderState {}
|
||||
message ArrivalPriceOrderState {}
|
||||
|
||||
enum OrderStatus {
|
||||
|
||||
|
||||
@@ -94,14 +94,3 @@ MDBootDelayWindow {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DisplayFactorOverride {
|
||||
value {
|
||||
override {
|
||||
symbol: "SOM"
|
||||
exchange: "GLBX"
|
||||
type: "SPREAD"
|
||||
price_multiplier: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
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,6 +90,8 @@ 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 }
|
||||
@@ -161,7 +163,6 @@ 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 }
|
||||
@@ -169,7 +170,6 @@ 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: "AEB" value: 1000 }
|
||||
cpp_entry { key: "AEJ" value: 960 }
|
||||
cpp_entry { key: "AEP" value: 25 }
|
||||
cpp_entry { key: "AET" value: 1000 }
|
||||
cpp_entry { key: "AEZ" value: 42000 }
|
||||
@@ -222,6 +222,7 @@ 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 }
|
||||
@@ -345,6 +346,7 @@ 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 }
|
||||
@@ -355,12 +357,13 @@ CppConfig
|
||||
cpp_entry { key: "BOO" value: 6350 }
|
||||
cpp_entry { key: "BOS" value: 250 }
|
||||
cpp_entry { key: "BR7" value: 1000 }
|
||||
cpp_entry { key: "BSF" value: 25 }
|
||||
cpp_entry { key: "BSW" value: 136 }
|
||||
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 }
|
||||
@@ -391,7 +394,6 @@ 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 }
|
||||
@@ -404,11 +406,9 @@ 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,6 +431,7 @@ 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 }
|
||||
@@ -460,9 +461,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: 264 }
|
||||
cpp_entry { key: "DEP" value: 252 }
|
||||
cpp_entry { key: "DFL" value: 100 }
|
||||
cpp_entry { key: "DFN" value: 100 }
|
||||
cpp_entry { key: "DFT" value: 100 }
|
||||
cpp_entry { key: "DG2" value: 100 }
|
||||
cpp_entry { key: "DG3" value: 100 }
|
||||
cpp_entry { key: "DGH" value: 1000 }
|
||||
@@ -471,6 +472,7 @@ 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 }
|
||||
@@ -501,6 +503,7 @@ 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 }
|
||||
@@ -539,6 +542,7 @@ 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 }
|
||||
@@ -664,24 +668,17 @@ 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 }
|
||||
@@ -706,16 +703,11 @@ 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 }
|
||||
@@ -727,6 +719,7 @@ 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 }
|
||||
@@ -734,12 +727,11 @@ CppConfig
|
||||
cpp_entry { key: "IPT" value: 10 }
|
||||
cpp_entry { key: "IS" value: 50 }
|
||||
cpp_entry { key: "ITB" value: 744 }
|
||||
cpp_entry { key: "ITP" value: 264 }
|
||||
cpp_entry { key: "ITP" value: 252 }
|
||||
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 }
|
||||
@@ -748,7 +740,7 @@ CppConfig
|
||||
cpp_entry { key: "JKB" value: 10000 }
|
||||
cpp_entry { key: "JKF" value: 10000 }
|
||||
cpp_entry { key: "JKM" value: 10000 }
|
||||
cpp_entry { key: "JML" value: 480 }
|
||||
cpp_entry { key: "JML" value: 200 }
|
||||
cpp_entry { key: "JNC" value: 1000 }
|
||||
cpp_entry { key: "JNG" value: 10000 }
|
||||
cpp_entry { key: "JNL" value: 80 }
|
||||
@@ -817,9 +809,6 @@ 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 }
|
||||
@@ -850,11 +839,10 @@ 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 }
|
||||
@@ -891,7 +879,6 @@ 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 }
|
||||
@@ -923,7 +910,6 @@ 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 }
|
||||
@@ -941,6 +927,7 @@ 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 }
|
||||
@@ -954,14 +941,10 @@ 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 }
|
||||
@@ -1001,7 +984,7 @@ CppConfig
|
||||
cpp_entry { key: "NYR" value: 42000 }
|
||||
cpp_entry { key: "NYT" value: 1000 }
|
||||
cpp_entry { key: "NZDUSC" value: 1 }
|
||||
cpp_entry { key: "NZDUSD" value: 1 }
|
||||
cpp_entry { key: "NZN" value: 2500 }
|
||||
cpp_entry { key: "OAD" value: 1 }
|
||||
cpp_entry { key: "ODO" value: 1000 }
|
||||
cpp_entry { key: "OFF" value: 5 }
|
||||
@@ -1017,7 +1000,6 @@ 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 }
|
||||
@@ -1038,6 +1020,7 @@ 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 }
|
||||
@@ -1099,8 +1082,6 @@ 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 }
|
||||
@@ -1110,7 +1091,6 @@ 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 }
|
||||
@@ -1139,15 +1119,13 @@ 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: 1760 }
|
||||
cpp_entry { key: "SDD" value: 1600 }
|
||||
cpp_entry { key: "SDG" value: 250 }
|
||||
cpp_entry { key: "SDI" value: 1000 }
|
||||
cpp_entry { key: "SDM" value: 100 }
|
||||
@@ -1179,14 +1157,12 @@ 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: "SRB" value: 1000 }
|
||||
cpp_entry { key: "SRT" value: 1760 }
|
||||
cpp_entry { key: "SRT" value: 1600 }
|
||||
cpp_entry { key: "SSI" value: 1000 }
|
||||
cpp_entry { key: "SSP" value: 5000 }
|
||||
cpp_entry { key: "SSW" value: 1000 }
|
||||
@@ -1197,31 +1173,25 @@ 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: "T15" value: 800 }
|
||||
cpp_entry { key: "T16" value: 800 }
|
||||
cpp_entry { key: "T17" value: 800 }
|
||||
cpp_entry { key: "T18" value: 800 }
|
||||
cpp_entry { key: "T19" value: 800 }
|
||||
cpp_entry { key: "T1U" value: 1000 }
|
||||
cpp_entry { key: "T20" value: 800 }
|
||||
cpp_entry { key: "T21" value: 800 }
|
||||
cpp_entry { key: "T22" value: 800 }
|
||||
cpp_entry { key: "T23" value: 800 }
|
||||
cpp_entry { key: "T24" value: 800 }
|
||||
cpp_entry { key: "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: "T30" value: 800 }
|
||||
cpp_entry { key: "T31" value: 800 }
|
||||
cpp_entry { key: "T3B" value: 1000 }
|
||||
cpp_entry { key: "T3L" value: 80 }
|
||||
cpp_entry { key: "T4B" value: 1000 }
|
||||
@@ -1237,7 +1207,6 @@ 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 }
|
||||
@@ -1247,7 +1216,6 @@ 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 }
|
||||
@@ -1284,6 +1252,7 @@ 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 }
|
||||
@@ -1293,12 +1262,10 @@ 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: "UFV" value: 100 }
|
||||
cpp_entry { key: "UFZ" value: 100 }
|
||||
cpp_entry { key: "UGG" value: 42000 }
|
||||
cpp_entry { key: "UKG" value: 310 }
|
||||
cpp_entry { key: "ULB" value: 42000 }
|
||||
@@ -1309,12 +1276,10 @@ 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 }
|
||||
@@ -1344,7 +1309,6 @@ 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 }
|
||||
@@ -1374,7 +1338,6 @@ 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 }
|
||||
@@ -1427,7 +1390,6 @@ 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 }
|
||||
@@ -1545,6 +1507,8 @@ 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 }
|
||||
@@ -1616,7 +1580,6 @@ 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 }
|
||||
@@ -1624,7 +1587,6 @@ 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 }
|
||||
@@ -1638,7 +1600,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "AE5" value: NYMEX }
|
||||
cme_mic { key: "AE8" value: NYMEX }
|
||||
cme_mic { key: "AE9" value: NYMEX }
|
||||
cme_mic { key: "AEB" value: NYMEX }
|
||||
cme_mic { key: "AEJ" value: NYMEX }
|
||||
cme_mic { key: "AEP" value: COMEX }
|
||||
cme_mic { key: "AET" value: NYMEX }
|
||||
cme_mic { key: "AEZ" value: NYMEX }
|
||||
@@ -1677,6 +1639,7 @@ 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 }
|
||||
@@ -1800,6 +1763,7 @@ 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 }
|
||||
@@ -1810,12 +1774,13 @@ CmeSymbolMics
|
||||
cme_mic { key: "BOO" value: NYMEX }
|
||||
cme_mic { key: "BOS" value: CME }
|
||||
cme_mic { key: "BR7" value: NYMEX }
|
||||
cme_mic { key: "BSF" value: CBT }
|
||||
cme_mic { key: "BSW" 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 }
|
||||
@@ -1846,7 +1811,6 @@ 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 }
|
||||
@@ -1859,11 +1823,9 @@ 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 }
|
||||
@@ -1886,6 +1848,7 @@ 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 }
|
||||
@@ -1917,7 +1880,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "DEN" value: CME }
|
||||
cme_mic { key: "DEP" value: NYMEX }
|
||||
cme_mic { key: "DFL" value: CBT }
|
||||
cme_mic { key: "DFN" value: CBT }
|
||||
cme_mic { key: "DFT" value: CBT }
|
||||
cme_mic { key: "DG2" value: CBT }
|
||||
cme_mic { key: "DG3" value: CBT }
|
||||
cme_mic { key: "DGH" value: DME }
|
||||
@@ -1926,6 +1889,7 @@ 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 }
|
||||
@@ -1956,6 +1920,7 @@ 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 }
|
||||
@@ -1994,6 +1959,7 @@ 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 }
|
||||
@@ -2119,24 +2085,17 @@ 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 }
|
||||
@@ -2161,16 +2120,11 @@ 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 }
|
||||
@@ -2182,6 +2136,7 @@ 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 }
|
||||
@@ -2194,7 +2149,6 @@ 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 }
|
||||
@@ -2272,9 +2226,6 @@ 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 }
|
||||
@@ -2305,11 +2256,10 @@ 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 }
|
||||
@@ -2346,7 +2296,6 @@ 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 }
|
||||
@@ -2378,7 +2327,6 @@ 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 }
|
||||
@@ -2396,6 +2344,7 @@ 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 }
|
||||
@@ -2409,14 +2358,10 @@ 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 }
|
||||
@@ -2456,7 +2401,7 @@ CmeSymbolMics
|
||||
cme_mic { key: "NYR" value: NYMEX }
|
||||
cme_mic { key: "NYT" value: NYMEX }
|
||||
cme_mic { key: "NZDUSC" value: CME }
|
||||
cme_mic { key: "NZDUSD" value: FXS }
|
||||
cme_mic { key: "NZN" value: NYMEX }
|
||||
cme_mic { key: "OAD" value: NYMEX }
|
||||
cme_mic { key: "ODO" value: DME }
|
||||
cme_mic { key: "OFF" value: NYMEX }
|
||||
@@ -2472,7 +2417,6 @@ 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 }
|
||||
@@ -2493,6 +2437,7 @@ 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 }
|
||||
@@ -2554,8 +2499,6 @@ 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 }
|
||||
@@ -2565,7 +2508,6 @@ 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 }
|
||||
@@ -2594,11 +2536,9 @@ 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 }
|
||||
@@ -2634,13 +2574,11 @@ 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 }
|
||||
@@ -2652,31 +2590,25 @@ 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: "T15" value: NYMEX }
|
||||
cme_mic { key: "T16" value: NYMEX }
|
||||
cme_mic { key: "T17" value: NYMEX }
|
||||
cme_mic { key: "T18" value: NYMEX }
|
||||
cme_mic { key: "T19" value: NYMEX }
|
||||
cme_mic { key: "T1U" value: CBT }
|
||||
cme_mic { key: "T20" value: NYMEX }
|
||||
cme_mic { key: "T21" value: NYMEX }
|
||||
cme_mic { key: "T22" value: NYMEX }
|
||||
cme_mic { key: "T23" value: NYMEX }
|
||||
cme_mic { key: "T24" value: NYMEX }
|
||||
cme_mic { key: "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: "T30" value: NYMEX }
|
||||
cme_mic { key: "T31" value: NYMEX }
|
||||
cme_mic { key: "T3B" value: NYMEX }
|
||||
cme_mic { key: "T3L" value: NYMEX }
|
||||
cme_mic { key: "T4B" value: NYMEX }
|
||||
@@ -2692,7 +2624,6 @@ 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 }
|
||||
@@ -2702,7 +2633,6 @@ 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 }
|
||||
@@ -2739,6 +2669,7 @@ 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 }
|
||||
@@ -2748,12 +2679,10 @@ 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: "UFV" value: CBT }
|
||||
cme_mic { key: "UFZ" value: CBT }
|
||||
cme_mic { key: "UGG" value: NYMEX }
|
||||
cme_mic { key: "UKG" value: NYMEX }
|
||||
cme_mic { key: "ULB" value: NYMEX }
|
||||
@@ -2764,12 +2693,10 @@ 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 }
|
||||
@@ -2799,7 +2726,6 @@ 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 }
|
||||
@@ -2829,7 +2755,6 @@ 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 }
|
||||
@@ -2882,7 +2807,6 @@ CmeSymbolMics
|
||||
cme_mic { key: "YWE" value: NYMEX }
|
||||
cme_mic { key: "YWF" value: NYMEX }
|
||||
cme_mic { key: "YWK" value: NYMEX }
|
||||
cme_mic { key: "Z00000" value: CME }
|
||||
cme_mic { key: "Z1B" value: NYMEX }
|
||||
cme_mic { key: "Z3N" value: CBT }
|
||||
cme_mic { key: "Z4" value: NYMEX }
|
||||
|
||||
@@ -216,13 +216,3 @@ message CMETradingSchedule {
|
||||
message SecurityExpirationCutoff {
|
||||
optional uint32 max_days_after_expiration =1 [default = 7];
|
||||
}
|
||||
|
||||
message DisplayFactorOverride {
|
||||
message Override {
|
||||
required string symbol = 1;
|
||||
required string exchange = 2;
|
||||
optional string type = 3;
|
||||
optional double price_multiplier = 10;
|
||||
}
|
||||
repeated Override override = 1;
|
||||
}
|
||||
@@ -143,4 +143,11 @@ 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;
|
||||
}
|
||||
@@ -48,10 +48,6 @@ message RejectStopAndStopLimitOrders {
|
||||
optional bool enabled = 1 [default = true];
|
||||
}
|
||||
|
||||
message SOMTicksFix {
|
||||
optional bool enabled = 1 [default = true];
|
||||
}
|
||||
|
||||
message EnsureOnScreenWithWorkAreaRect {
|
||||
// Defaulting to false bc this is near the end of the cycle (04/27/2019),
|
||||
// and the new ensure_onscreen code has only been tested with a single monitor arrangement.
|
||||
|
||||
+12
-16
@@ -16,12 +16,12 @@ namespace md {
|
||||
// Owns shared memory for a single symbol+type
|
||||
class MDProducerImpl {
|
||||
public:
|
||||
MDProducerImpl(const string& symbol, SecurityType type, Venue exchange, Platform platform, MDProducerFlags flags) :
|
||||
MDProducerImpl(const string& symbol, SecurityType type, Venue exchange, Platform platform, bool shared) :
|
||||
_symbol(symbol),
|
||||
_type(type),
|
||||
_exchange(exchange),
|
||||
_hot(hot_segment_name(symbol, type, exchange, platform), 1024, 1024, flags & MDProducerFlags::Shared),
|
||||
_cold(cold_segment_name(symbol, type, exchange, platform), 8192, 2048, flags & MDProducerFlags::Shared),
|
||||
_hot(hot_segment_name(symbol, type, exchange, platform), 1024, 1024, shared),
|
||||
_cold(cold_segment_name(symbol, type, exchange, platform), 8192, 2048, shared),
|
||||
_trades(_cold.header().trade_buffer, BTS_ARRAYSIZE(_cold.header().trade_buffer), true),
|
||||
_rfqs(_cold.header().rfq_buffer, BTS_ARRAYSIZE(_cold.header().rfq_buffer), true)
|
||||
{
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
// static_assert(sizeof(HotEntry) <= 32,"HotEntry should be less than 32 bytes");
|
||||
}
|
||||
|
||||
MDProducerHandle add_security(const FixedSecurity& security, SecurityMapper& smapper) {
|
||||
MDProducerHandle add_security(const FixedSecurity& security) {
|
||||
void* h_entry = nullptr;
|
||||
if (has_depth()) {
|
||||
h_entry = new (_hot.add(sizeof(HotDepthEntry))) HotDepthEntry();
|
||||
@@ -45,7 +45,6 @@ public:
|
||||
// Calculating the size for the variable sized entries is tricky
|
||||
ColdEntry* c_entry = new (_cold.add(ColdEntry::fixed_size() + security.size)) ColdEntry(security.size);
|
||||
memcpy(&c_entry->security, &security, security.size);
|
||||
smapper.apply(c_entry->security);
|
||||
|
||||
MDProducerHandle handle(_cold.header(), _hot.header(), *c_entry, h_entry, MDProducerChannel(*this));
|
||||
|
||||
@@ -103,30 +102,27 @@ private:
|
||||
// MDProducer
|
||||
//
|
||||
|
||||
MDProducer::MDProducer(Platform platform, MDProducerFlags flags) :
|
||||
MDProducer::MDProducer(Platform platform, bool shared) :
|
||||
_mutex(new std::mutex()),
|
||||
_producers(),
|
||||
_id_recorder(),
|
||||
_platform(platform),
|
||||
_flags(flags),
|
||||
_smapper(flags & MDProducerFlags::SecurityMapper)
|
||||
_shared(shared)
|
||||
{ }
|
||||
#ifndef WIN32
|
||||
MDProducer::MDProducer(Platform platform, SecurityIDRecorder recorder, MDProducerFlags flags) :
|
||||
MDProducer::MDProducer(Platform platform, SecurityIDRecorder recorder, bool shared) :
|
||||
_mutex(new std::mutex()),
|
||||
_producers(),
|
||||
_id_recorder(std::make_unique<SecurityIDRecorder>(recorder)),
|
||||
_platform(platform),
|
||||
_flags(flags),
|
||||
_smapper(flags & MDProducerFlags::SecurityMapper)
|
||||
_shared(shared)
|
||||
{ }
|
||||
#endif
|
||||
MDProducer::MDProducer(MDProducer&& other) :
|
||||
_mutex(std::move(other._mutex)),
|
||||
_producers(std::move(other._producers)),
|
||||
_platform(other._platform),
|
||||
_flags(other._flags),
|
||||
_smapper(_flags & MDProducerFlags::SecurityMapper)
|
||||
_shared(other._shared)
|
||||
{}
|
||||
|
||||
MDProducer::~MDProducer() {}
|
||||
@@ -145,10 +141,10 @@ MDProducerImpl& MDProducer::get_producer(const char* symbol, SecurityType type,
|
||||
unique_ptr<MDProducerImpl> newp;
|
||||
if (type == api::SECURITYTYPE_SYNTHETIC) {
|
||||
// synthetics are special. We don't want to allocate a separate section for each one so we put them all in one
|
||||
newp.reset(new MDProducerImpl(SYNTHETIC_SYMBOL, api::SECURITYTYPE_SYNTHETIC, Venue::VENUE_BTS, _platform, _flags));
|
||||
newp.reset(new MDProducerImpl(SYNTHETIC_SYMBOL, api::SECURITYTYPE_SYNTHETIC, Venue::VENUE_BTS, _platform, _shared));
|
||||
}
|
||||
else {
|
||||
newp.reset(new MDProducerImpl(symbol, type, exchange, _platform, _flags));
|
||||
newp.reset(new MDProducerImpl(symbol, type, exchange, _platform, _shared));
|
||||
}
|
||||
_producers.push_back(move(newp));
|
||||
return *_producers.back();
|
||||
@@ -159,7 +155,7 @@ MDProducerHandle MDProducer::add_security(const FixedSecurity& security) {
|
||||
bts_assert(security.size >= sizeof(FixedSecurity));
|
||||
std::lock_guard<std::mutex> lock(*_mutex);
|
||||
auto& impl = get_producer(security.symbol(), security.type, security.exchange);
|
||||
auto result = impl.add_security(security, _smapper);
|
||||
auto result = impl.add_security(security);
|
||||
if (security.key != invalid_security_key) { result.set_key(security.key); }
|
||||
else if(_id_recorder) {
|
||||
_id_recorder->ensure_key(result);
|
||||
|
||||
+3
-17
@@ -7,7 +7,6 @@
|
||||
#include "MDProducerHandle.h"
|
||||
#include "MDProducerChannel.h"
|
||||
#include "Shm/FixedSecurity.h"
|
||||
#include "SecurityMapper.h"
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -18,23 +17,11 @@ namespace md {
|
||||
class MDProducerImpl;
|
||||
class SecurityIDRecorder;
|
||||
|
||||
enum class MDProducerFlags {
|
||||
None = 0x0,
|
||||
Shared = 0x1,
|
||||
SecurityMapper = 0x2,
|
||||
};
|
||||
|
||||
constexpr MDProducerFlags operator+(MDProducerFlags a, MDProducerFlags b) { return (MDProducerFlags)((uint32_t)a | (uint32_t)b); }
|
||||
constexpr MDProducerFlags operator-(MDProducerFlags a, MDProducerFlags b) { return (MDProducerFlags)((uint32_t)a | (uint32_t)b); }
|
||||
constexpr bool operator&(const MDProducerFlags a, const MDProducerFlags b) { return ((uint32_t)a & (uint32_t)b) == (uint32_t)b; }
|
||||
|
||||
constexpr MDProducerFlags DefaultMDProducerFlags = MDProducerFlags::Shared + MDProducerFlags::SecurityMapper;
|
||||
|
||||
class BTS_EXPORT MDProducer
|
||||
{
|
||||
public:
|
||||
MDProducer(Platform platform, MDProducerFlags flags=DefaultMDProducerFlags);
|
||||
MDProducer(Platform platform, SecurityIDRecorder recorder, MDProducerFlags flags=DefaultMDProducerFlags);
|
||||
MDProducer(Platform platform, bool shared=true);
|
||||
MDProducer(Platform platform, SecurityIDRecorder recorder, bool shared=true);
|
||||
MDProducer(MDProducer&& other);
|
||||
~MDProducer();
|
||||
|
||||
@@ -58,8 +45,7 @@ private:
|
||||
std::vector<std::unique_ptr<MDProducerImpl>> _producers;
|
||||
std::unique_ptr<SecurityIDRecorder> _id_recorder;
|
||||
Platform _platform;
|
||||
MDProducerFlags _flags;
|
||||
SecurityMapper _smapper;
|
||||
bool _shared;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#include "SecurityMapper.h"
|
||||
#include "UserSymbol.h"
|
||||
#include "PriceSize.h"
|
||||
#include "lib/config/config.h"
|
||||
#include "lib/config/protos/MarketData.pb.h"
|
||||
#include "lib/domain_model/Security.h"
|
||||
#include "lib/utils/parse_enum.h"
|
||||
#ifndef _WIN32
|
||||
#include "google/btree/btree_map.h"
|
||||
|
||||
namespace bts {
|
||||
namespace md {
|
||||
struct DisplayFactorMapper : public ISecurityMapper
|
||||
{
|
||||
btree::btree_map<UserSymbol, int> _mapped;
|
||||
DisplayFactorMapper() : _mapped() {
|
||||
for (const auto& ov : config::get<DisplayFactorOverride>().override()) {
|
||||
if (ov.has_price_multiplier()) {
|
||||
auto venue = parse_enum<api::Venue>(ov.exchange(), "VENUE", api::Venue_Parse);
|
||||
bts_assert_msg(venue, fmt::format("Invalid venue `{}`", ov.exchange()));
|
||||
auto type = parse_enum<SecurityType>(ov.type(), "SECURITYTYPE", api::SecurityType_Parse);
|
||||
|
||||
if (type) {
|
||||
_mapped.insert(
|
||||
std::make_pair(
|
||||
UserSymbol { uppercase_copy(ov.symbol()), *venue, *type },
|
||||
-to_exponent(ov.price_multiplier())));
|
||||
}
|
||||
else {
|
||||
for (auto t : {
|
||||
SecurityType::SECURITYTYPE_FUTURE,
|
||||
SecurityType::SECURITYTYPE_SPREAD,
|
||||
SecurityType::SECURITYTYPE_OPTION }) {
|
||||
_mapped.insert(
|
||||
std::make_pair(
|
||||
UserSymbol { uppercase_copy(ov.symbol()), *venue, t },
|
||||
-to_exponent(ov.price_multiplier())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void apply(FixedSecurity& f) const override {
|
||||
UserSymbol key { f.symbol(), f.exchange, f.type };
|
||||
auto iter = _mapped.find(key);
|
||||
if (iter != _mapped.end()) {
|
||||
f.display_factor = iter->second;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SecurityMapper::SecurityMapper(bool enabled): _impl() {
|
||||
if (enabled) {
|
||||
_impl.push_back(std::make_unique<DisplayFactorMapper>());
|
||||
// Register more mappers HERE
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
namespace bts {
|
||||
namespace md {
|
||||
SecurityMapper::SecurityMapper(bool): _impl() {}
|
||||
#endif
|
||||
|
||||
SecurityMapper::~SecurityMapper() { }
|
||||
void SecurityMapper::apply(FixedSecurity& security) {
|
||||
for (const auto& m : _impl) {
|
||||
m->apply(security);
|
||||
}
|
||||
}
|
||||
}} //namespace
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
#include "Shm/FixedSecurity.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace bts {
|
||||
namespace md {
|
||||
|
||||
struct ISecurityMapper {
|
||||
virtual void apply(FixedSecurity&) const = 0;
|
||||
};
|
||||
|
||||
class SecurityMapper {
|
||||
std::vector<std::unique_ptr<ISecurityMapper>> _impl;
|
||||
public:
|
||||
SecurityMapper(bool enabled);
|
||||
~SecurityMapper();
|
||||
// apply various mappings to the security
|
||||
void apply(FixedSecurity&);
|
||||
};
|
||||
|
||||
|
||||
}} //namespace
|
||||
@@ -140,7 +140,7 @@ std::string security_descriptor(const api::Security& security) {
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void get_contract_spec(const FixedSecurity& source, /*out*/ api::ContractSpecification& spec) {
|
||||
void get_contract_spec(const FixedSecurity& source, api::ContractSpecification& spec) {
|
||||
spec.set_price_break(source.price_break);
|
||||
spec.set_low_tick(source.low_tick);
|
||||
spec.set_high_tick(source.high_tick);
|
||||
|
||||
@@ -100,9 +100,7 @@ public:
|
||||
MDProducer& ensure_producer(Platform platform) {
|
||||
auto find_result = _producers.find(platform);
|
||||
if (find_result == _producers.end()) {
|
||||
// relay never wants to enable SecurityMapper. Securities should always match the relay source.
|
||||
auto flags = _shared ? MDProducerFlags::Shared : MDProducerFlags::None;
|
||||
auto result = _producers.insert(make_pair(platform, MDProducer(platform, flags)));
|
||||
auto result = _producers.insert(make_pair(platform, MDProducer(platform, _shared)));
|
||||
if (result.second) {
|
||||
return result.first->second;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ extern "C" BTS_EXPORT TestProducer* co2_produce_test_md() {
|
||||
" }"
|
||||
"}");
|
||||
auto* tp = new TestProducer();
|
||||
tp->md = std::make_shared<MDProducer>(PLATFORM_SIM, MDProducerFlags::None);
|
||||
tp->md = std::make_shared<MDProducer>(PLATFORM_SIM, false);
|
||||
tp->handles = create_test_securities(*(tp->md));
|
||||
auto& producers = tp->handles;
|
||||
assign_ids(producers.begin(), producers.end());
|
||||
|
||||
@@ -156,6 +156,18 @@ 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,6 +23,11 @@
|
||||
#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"
|
||||
@@ -205,6 +210,22 @@ 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());
|
||||
@@ -215,6 +236,7 @@ Order &OrderFactory::allocate(OrderKey k, OrderKey pk,
|
||||
order_ptr.reset(new orderman::DynamicOrder());
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case CustomOrderDefinition::kComposite:
|
||||
order_ptr.reset(new orderman::CompositeOrder());
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
#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
|
||||
@@ -0,0 +1,32 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,227 @@
|
||||
#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
|
||||
@@ -0,0 +1,32 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,109 @@
|
||||
#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
|
||||
@@ -0,0 +1,27 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,380 @@
|
||||
#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
|
||||
@@ -0,0 +1,78 @@
|
||||
#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();
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -0,0 +1,227 @@
|
||||
#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
|
||||
@@ -0,0 +1,32 @@
|
||||
#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;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -3065,7 +3065,7 @@ TEST_CASE ("spreader_perf_2legs", "[spreader]")
|
||||
}
|
||||
TEST_CASE ("spreader_perf_4legs", "[spreader]")
|
||||
{
|
||||
bool recomp = false;//gen_rand(0,10) > 5;
|
||||
bool recomp = gen_rand(0,10) > 5;
|
||||
bts::orderman::OrderKey order_key(0);
|
||||
Price spreader_price = Price (40);
|
||||
Quantity spreader_quantity = Quantity (250);
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
// An incomplete version of std::optional which should work well enough on Windows until it catch up
|
||||
#ifdef _WIN32
|
||||
#include <exception>
|
||||
namespace std {
|
||||
class bad_optional_access : exception { };
|
||||
|
||||
template <class T>
|
||||
class optional {
|
||||
bool _has_value;
|
||||
union {
|
||||
T _value;
|
||||
int _unused;
|
||||
};
|
||||
public:
|
||||
optional(const T& value) : _has_value(true), _value(value) { }
|
||||
optional(T&& value) : _has_value(true), _value(value) { }
|
||||
optional() : _has_value(false)
|
||||
~optional() { reset(); }
|
||||
bool has_value() const { return _has_value; }
|
||||
operator bool() { return b.has_value(); }
|
||||
T& operator *() {
|
||||
if (has_value()) {
|
||||
return _value;
|
||||
}
|
||||
else throw std::bad_optional_access();
|
||||
}
|
||||
const T& operator*() const { return **this; }
|
||||
T& operator->() { return **this; }
|
||||
const T& operator->() const { return **this; }
|
||||
bool operator==(const std::optional<T>& other) const {
|
||||
if (!_has_value && !other.has_value()) return true;
|
||||
return _has_value == other._has_value && _value == other.value();
|
||||
}
|
||||
bool operator!=(const std::optional<T>& other) const { return !(*this == other); }
|
||||
T& value() { return **this; }
|
||||
const T& value() const { return **this; }
|
||||
T value_or(T default_value) {
|
||||
if (has_value()) return _value;
|
||||
else return default_value;
|
||||
}
|
||||
void reset() {
|
||||
if (has_value()) {
|
||||
_value.~T();
|
||||
_has_value = false;
|
||||
}
|
||||
}
|
||||
// This class is incomplete. Add methods as necessary
|
||||
};
|
||||
|
||||
template <class T>
|
||||
constexpr optional<T> nullopt = {};
|
||||
}
|
||||
#else
|
||||
#include <optional>
|
||||
#endif
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "lib/utils/optional.h"
|
||||
namespace bts {
|
||||
|
||||
inline std::string uppercase_copy(const std::string& cs) {
|
||||
std::string s = cs;
|
||||
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class T, class T2>
|
||||
std::optional<T> parse_enum(const std::string& value, const std::string& prefix, T2 parse) {
|
||||
auto temp = value;
|
||||
T result;
|
||||
if (temp.find(prefix) == std::string::npos) {
|
||||
temp = prefix + "_" + temp;
|
||||
}
|
||||
if(parse(temp, &result)) {
|
||||
return {result};
|
||||
}
|
||||
else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,6 +150,11 @@ 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>
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
+++
|
||||
title = "BTS Basic Algos"
|
||||
weight = 3
|
||||
sort_by = "weight"
|
||||
insert_anchor_links = "right"
|
||||
+++
|
||||
|
||||
|
||||
## Lean
|
||||
|
||||
The goal of the lean order is to watch the opposite-inside market size and cross when that size goes below the threshold (this also implies a cross if that size goes to zero and the market trades away from you) If the market trades toward you, you can opt into several different behaviors
|
||||
|
||||
##### Parameters
|
||||
* Cross Thresh - size thresh in absolute or ratio terms
|
||||
* Max Chase Ticks - max levels to pay up, in ticks
|
||||
|
||||
|
||||
## Join
|
||||
The goal of the join order is to watch the opposite-inside market and join when the market flips (that is, when the best offer becomes the best bid) and has at least threshold size.
|
||||
|
||||
##### Parameters
|
||||
* Join Thresh - size thresh in absolute or ratio terms
|
||||
|
||||
|
||||
## Top
|
||||
|
||||
The goal of the top order is to not trade by yourself, but the intent at the time of order entry is to get filled.If the order is on the market (say current bid price) AND the quantity on that bid price is below top thresh then cancel the order else remain working.
|
||||
|
||||
##### Parameters
|
||||
* Top Thresh - size thresh in absolute or ratio terms
|
||||
|
||||
|
||||
## Cover
|
||||
A Cover order’s purpose is to fire a hedge order (of any type) in response to fills from it’s child order on the opposite side of the market N ticks away
|
||||
|
||||
##### Parameters
|
||||
* Profit Ticks - ticks above or below fill price to place profit / cover order
|
||||
|
||||
|
||||
## OCO
|
||||
An OCO order creates a relationship between a child order and a 'stop' or 'other' order such that when one of these is cancelled, both cancel, or when one is filled, the other order's size is debited in the amount of the fill.
|
||||
|
||||
Composing this order with Cover simulates scalping functionality
|
||||
|
||||
##### Parameters
|
||||
* Stop Ticks - ticks below or above main order to place stop / other order
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "lib/md/SecurityDB.h"
|
||||
#include "server/sparkd/exchange_sim/ExchangeSim.h"
|
||||
#include "lib/utils/thread_manager.h"
|
||||
#include "lib/utils/parse_enum.h"
|
||||
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
@@ -170,14 +169,16 @@ string& uppercase(string& s) {
|
||||
return s;
|
||||
}
|
||||
template <class T, class T2>
|
||||
bool parse_enum(const string& value, const string& prefix, T2 parse, T default_value, T* result) {
|
||||
auto opt = ::bts::parse_enum<T>(value, prefix, parse);
|
||||
if (opt) {
|
||||
*result = opt.value();
|
||||
bool parse_enum(const string& value, const string& prefix, T2 parse, T default_value, T* presult) {
|
||||
string temp = value;
|
||||
if (temp.find(prefix) == string::npos) {
|
||||
temp = prefix + "_" + temp;
|
||||
}
|
||||
if(parse(temp, presult)) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
*result = default_value;
|
||||
*presult = default_value;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -207,14 +208,13 @@ struct MDArgs {
|
||||
MDArgs parse_md_args(const vector<string>& args) {
|
||||
using namespace api;
|
||||
using namespace co2;
|
||||
auto venue = VENUE_UNSET;
|
||||
auto venue = VENUE_UNSET; // Default to glbx. If you change this change below (used) also
|
||||
auto platform = PLATFORM_UNSET;
|
||||
auto type = SECURITYTYPE_UNSET;
|
||||
bool hot = false;
|
||||
long number = 0;
|
||||
std::string symbol;
|
||||
for (auto str : args) {
|
||||
// Iterate through each argument and see if it parses to one of these enums
|
||||
uppercase(str);
|
||||
bool used =
|
||||
(venue == VENUE_UNSET && parse_enum(str, "VENUE", Venue_Parse, venue, &venue)) ||
|
||||
|
||||
Executable → Regular
File mode changed.
@@ -1,14 +1,14 @@
|
||||
qa_sprint_id=20
|
||||
qa_sprint_id=18
|
||||
|
||||
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,9 +20,10 @@ 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. This should cancel all the lean orders.
|
||||
to Cancel and commit. Make sure it is set to Cancel for all the lean orders.
|
||||
|
||||
6. Move the market back to 20.050
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
Executable → Regular
File mode changed.
@@ -28,4 +28,3 @@ Sym,Mult,Exch
|
||||
"BOB",1000,CBT
|
||||
"BUB",1000,CBT
|
||||
"FNU",1000,CBT
|
||||
"SOM",500,CBT
|
||||
|
@@ -2,6 +2,6 @@
|
||||
if [ -f /.dockerenv ]; then
|
||||
ninja
|
||||
else
|
||||
cid=`docker ps | grep -P "emacs_ide|bluetradingsystems/linux_docker" | awk '{print $1}'`
|
||||
cid=`docker ps | grep bluetradingsystems/linux_docker | awk '{print $1}'`
|
||||
docker exec $cid /bin/bash -c "cd build/clang_debug/ && ninja"
|
||||
fi
|
||||
Reference in new issue
Block a user