Compare commits
42
Commits
fix_tooltips
...
ml
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbf1fad2dd | ||
|
|
1fbc1584e5 | ||
|
|
02defef93d | ||
|
|
9390fb0639 | ||
|
|
6d774d46c9 | ||
|
|
b39812aad0 | ||
|
|
f99717d880 | ||
|
|
f224b8be43 | ||
|
|
f5457e5ce4 | ||
|
|
5ba746fd59 | ||
|
|
ab5cb23062 | ||
|
|
4ebdc603c5 | ||
|
|
f4b7fbe6b5 | ||
|
|
9901ef54d4 | ||
|
|
293c13e11d | ||
|
|
be4c69fad4 | ||
|
|
2c4dc8fbe5 | ||
|
|
4ea93bc386 | ||
|
|
1c6333b07a | ||
|
|
26d543af82 | ||
|
|
99b301ad6f | ||
|
|
9cbe83e1a4 | ||
|
|
59369e1b2b | ||
|
|
7c42e75ddd | ||
|
|
b453be40fe | ||
|
|
96709c8121 | ||
|
|
5de9f63665 | ||
|
|
6089b209d1 | ||
|
|
d7a12d0dd9 | ||
|
|
2f87fe31be | ||
|
|
5a9749d551 | ||
|
|
ea950c8786 | ||
|
|
30891bfb49 | ||
|
|
34319c4536 | ||
|
|
196c518ac6 | ||
|
|
f04af5af9d | ||
|
|
8f4da463a7 | ||
|
|
f3adf780d0 | ||
|
|
664c1f28ed | ||
|
|
aae927d773 | ||
|
|
00dba92636 | ||
|
|
5a5de65292 |
No files matched your search
Vendored
+3
@@ -30,6 +30,7 @@
|
||||
"${workspaceRoot}/build/ninja_debug/src",
|
||||
"${workspaceRoot}/externals/windows/include",
|
||||
"${workspaceRoot}/externals/linux/include",
|
||||
"${workspaceRoot}/externals/linux/include/tensorflow/contrib/makefile/gen/proto",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/c++/6",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/x86_64-linux-gnu/c++/6",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/c++/6/backward",
|
||||
@@ -50,6 +51,7 @@
|
||||
"${workspaceRoot}/build/ninja_debug/src",
|
||||
"${workspaceRoot}/externals/windows/include",
|
||||
"${workspaceRoot}/externals/linux/include",
|
||||
"${workspaceRoot}/externals/linux/include/tensorflow/contrib/makefile/gen/proto",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/c++/6",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/x86_64-linux-gnu/c++/6",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/c++/6/backward",
|
||||
@@ -74,6 +76,7 @@
|
||||
"${workspaceRoot}/build/ninja_debug/src",
|
||||
"${workspaceRoot}/externals/windows/include",
|
||||
"${workspaceRoot}/externals/linux/include",
|
||||
"${workspaceRoot}/externals/linux/include/tensorflow/contrib/makefile/gen/proto",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/c++/6",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/x86_64-linux-gnu/c++/6",
|
||||
"${workspaceRoot}/externals/windows/vscode/usr/include/c++/6/backward",
|
||||
|
||||
Vendored
+41
-1
@@ -6,7 +6,7 @@
|
||||
"name": "(gdb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/build/ninja_debug/src/server/sparkd/sparkd",
|
||||
"program": "${workspaceRoot}/build/ninja_debug/server/sparkd/sparkd",
|
||||
"args": ["run"],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceRoot}/build/ninja_debug/src/server/sparkd",
|
||||
@@ -108,6 +108,46 @@
|
||||
"/home/bts/spark/": "${workspaceRoot}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "TFTest ",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "/home/bts/spark/build/ninja_debug/sdk/examples/tf_test",
|
||||
"args": [
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "/home/bts/spark/build/ninja_debug/sdk/examples/",
|
||||
"environment": [],
|
||||
"externalConsole": true,
|
||||
"MIMode": "gdb",
|
||||
"preLaunchTask": "",
|
||||
"logging": {
|
||||
"engineLogging": false
|
||||
},
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "enable pretty-printer",
|
||||
"ignoreFailures": true
|
||||
},
|
||||
{
|
||||
"description": "Skip STL",
|
||||
"text": "skip -gfi /usr/include/c++/7/bits/*.h",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
],
|
||||
"pipeTransport": {
|
||||
"pipeCwd": "${workspaceRoot}",
|
||||
"pipeProgram": "c:\\program files\\git\\usr\\bin\\ssh.exe",
|
||||
"pipeArgs": [
|
||||
"bts@sparkvm"
|
||||
],
|
||||
"debuggerPath": "/usr/bin/gdb"
|
||||
},
|
||||
"sourceFileMap": {
|
||||
"/home/bts/spark/": "${workspaceRoot}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Spreader Tests",
|
||||
"type": "cppdbg",
|
||||
|
||||
+4
-1
@@ -13,7 +13,7 @@ set (SPARK_BIN "${EXTERNALS_ROOT}/bin")
|
||||
set (SPARK_INCLUDE "${EXTERNALS_ROOT}/include")
|
||||
set (SPARK_LIB "${EXTERNALS_ROOT}/lib/${CMAKE_BUILD_TYPE}")
|
||||
|
||||
include_directories (BEFORE SYSTEM ${SPARK_INCLUDE} ${EXTERNALS_ROOT}/include/zlib)
|
||||
include_directories (BEFORE SYSTEM ${SPARK_INCLUDE} ${EXTERNALS_ROOT}/include/zlib ${TF_INCLUDE})
|
||||
link_directories (${SPARK_LIB})
|
||||
|
||||
if (WIN32)
|
||||
@@ -57,6 +57,9 @@ else ()
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/src/lib/libspark.so ${CMAKE_BINARY_DIR}/server
|
||||
COMMAND mkdir ARGS -p ${CMAKE_BINARY_DIR}/server/plugins
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/sdk/examples/order_plugin_example.so ${CMAKE_BINARY_DIR}/server/plugins/
|
||||
COMMAND ln ARGS -sf ${CMAKE_BINARY_DIR}/sdk/examples/ai_order_plugin_example.so ${CMAKE_BINARY_DIR}/server/plugins/
|
||||
COMMAND ln ARGS -sf ${EXTERNALS_ROOT}/lib/Release/libtensorflow.so ${CMAKE_BINARY_DIR}/server/plugins
|
||||
|
||||
COMMENT "Creating server runtime layout"
|
||||
DEPENDS sparkd data_files_dir)
|
||||
|
||||
|
||||
+1
-1
Submodule docker/linux updated: f6d8d59860...8ee9692597.
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"uri": "sftp://bts:BT5u53r@sparkvm:22/home/bts/",
|
||||
"name": "sparkvm"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.associations": {
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"list": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"vector": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xstring": "cpp",
|
||||
"system_error": "cpp",
|
||||
"array": "cpp",
|
||||
"string_view": "cpp",
|
||||
"xutility": "cpp",
|
||||
"*.ipp": "cpp"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.associations": {
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"list": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"vector": "cpp",
|
||||
"xhash": "cpp",
|
||||
"xstring": "cpp",
|
||||
"system_error": "cpp",
|
||||
"array": "cpp",
|
||||
"string_view": "cpp",
|
||||
"xutility": "cpp",
|
||||
"*.ipp": "cpp",
|
||||
"atomic": "cpp",
|
||||
"hash_map": "cpp",
|
||||
"hash_set": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"cctype": "cpp",
|
||||
"cfenv": "cpp",
|
||||
"chrono": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"complex": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"exception": "cpp",
|
||||
"any": "cpp",
|
||||
"optional": "cpp",
|
||||
"fstream": "cpp",
|
||||
"functional": "cpp",
|
||||
"future": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"memory": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"ostream": "cpp",
|
||||
"numeric": "cpp",
|
||||
"ratio": "cpp",
|
||||
"scoped_allocator": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"tuple": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp",
|
||||
"variant": "cpp"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,8 @@ namespace mbts.ui.spark {
|
||||
public DataTemplate JoinOrderTemplate { get; set; }
|
||||
public DataTemplate TopOrderTemplate { get; set; }
|
||||
public DataTemplate CoverOrderTemplate { get; set; }
|
||||
public DataTemplate OCOOrderTemplate { get; set; }
|
||||
public DataTemplate PricerOrderTemplate { get; set; }
|
||||
public DataTemplate OffsetOrderTemplate { get; set; }
|
||||
public DataTemplate TriggerOrderTemplate { get; set; }
|
||||
public DataTemplate IcebergOrderTemplate { get; set; }
|
||||
@@ -43,6 +45,8 @@ namespace mbts.ui.spark {
|
||||
case CustomOrderDefinition.CustomOneofCase.Join: return JoinOrderTemplate;
|
||||
case CustomOrderDefinition.CustomOneofCase.Top: return TopOrderTemplate;
|
||||
case CustomOrderDefinition.CustomOneofCase.Cover: return CoverOrderTemplate;
|
||||
case CustomOrderDefinition.CustomOneofCase.Oco : return OCOOrderTemplate;
|
||||
case CustomOrderDefinition.CustomOneofCase.Pricer: return PricerOrderTemplate;
|
||||
case CustomOrderDefinition.CustomOneofCase.Offset: return OffsetOrderTemplate;
|
||||
case CustomOrderDefinition.CustomOneofCase.Trigger: return TriggerOrderTemplate;
|
||||
case CustomOrderDefinition.CustomOneofCase.Iceberg: return IcebergOrderTemplate;
|
||||
|
||||
@@ -126,6 +126,8 @@ namespace mbts.spark
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
|
||||
public bool has_child => _order_def_tags.Any();
|
||||
|
||||
public IOrderTypeVM child_order
|
||||
{
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
using bts.api;
|
||||
using bts.api.orderman;
|
||||
using mbts.ui;
|
||||
using mbts.ui.utility;
|
||||
using mbts.utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reactive.Linq;
|
||||
using static bts.api.orderman.CustomOrderDefinition;
|
||||
|
||||
namespace mbts.spark
|
||||
{
|
||||
static partial class OrderTypeVMFactory
|
||||
{
|
||||
class InlineOCOOrderProperties
|
||||
{
|
||||
public InlineOCOOrderProperties(OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
{
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
|
||||
var othertype = CustomOneofCase.Limit;
|
||||
this.selected_other_order_type = new InlineUserProperty<OrderTemplateHeader>(new OrderTemplateHeader(othertype), true);
|
||||
this.other_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
|
||||
other_ticks = new InlineUserProperty<int>(1, false);
|
||||
other_side = new InlineUserProperty<bts.api.RelativeSide>(bts.api.RelativeSide.Same, false);
|
||||
}
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_other_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> other_order_types;
|
||||
|
||||
public readonly InlineUserProperty<int> other_ticks;
|
||||
public readonly InlineUserProperty<bts.api.RelativeSide> other_side;
|
||||
|
||||
}
|
||||
|
||||
class OCOOrderVM : OrderTypeVMBase<OCOOrderDefinition>, IHierarchicalOrderTypeVM, IDisposable
|
||||
{
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineOCOOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _other_order_choices;
|
||||
IOrderTypeVM _other_order;
|
||||
IDisposable _other_order_errors_sub;
|
||||
|
||||
public int other_ticks { get; set; } = 1;
|
||||
public bts.api.RelativeSide other_side { get; set; } = bts.api.RelativeSide.Same;
|
||||
|
||||
public OCOOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineOCOOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name)
|
||||
{ }
|
||||
|
||||
public OCOOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineOCOOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
{
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
security_md_source.OnDispatcher()
|
||||
.Subscribe(smd => _security = smd.security),
|
||||
inline_properties.OnDispatcher()
|
||||
.Subscribe(p =>
|
||||
{
|
||||
if (_order_types.Count == 0 || p.child_order_types.force_override)
|
||||
{
|
||||
_order_types.SetItems(p.child_order_types.value);
|
||||
}
|
||||
if (_child_order_choices != null && (_child_order == null || p.selected_child_order_type.force_override))
|
||||
{
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (_other_order_choices != null && (_other_order == null || p.selected_other_order_type.force_override))
|
||||
{
|
||||
_select_other_order(p.selected_other_order_type.value.key.type);
|
||||
}
|
||||
if (p.other_ticks.force_override)
|
||||
{
|
||||
other_ticks = p.other_ticks.value;
|
||||
RaisePropertyChanged(nameof(other_ticks));
|
||||
}
|
||||
if (p.other_side.force_override)
|
||||
{
|
||||
other_side = p.other_side.value;
|
||||
RaisePropertyChanged(nameof(other_side));
|
||||
}
|
||||
_inline_props = p;
|
||||
_validate();
|
||||
})
|
||||
);
|
||||
_validate();
|
||||
}
|
||||
|
||||
public override void assign_to(CustomOrderDefinition value)
|
||||
{
|
||||
if (_child_order == null)
|
||||
_select_child_order(model.factory.default_order_type(_security.Value, true));
|
||||
if (_other_order == null )
|
||||
_select_other_order(model.factory.default_order_type(_security.Value, true));
|
||||
_validate();
|
||||
if (!HasErrors)
|
||||
{
|
||||
var i = factory.oco_order();
|
||||
i.OtherTicks = other_ticks;
|
||||
i.OtherSide = other_side;
|
||||
child_order.assign_to(i.Child);
|
||||
if (other_order != null)
|
||||
other_order.assign_to(i.Other);
|
||||
value.Oco = i;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<bts.api.RelativeSide> other_side_types => EnumHelper.get_values_except<bts.api.RelativeSide>(bts.api.RelativeSide.Undefined);
|
||||
|
||||
public ICollection<IOrderTypeVM> child_order_types
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_child_order_choices == null)
|
||||
_child_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _child_order_choices;
|
||||
}
|
||||
}
|
||||
|
||||
public ICollection<IOrderTypeVM> other_order_types
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_other_order_choices == null)
|
||||
_other_order_choices = new ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader>(_order_types, ot => create(ot.key.type, ot.key.name, ot.display_name, model, _security_md_source));
|
||||
return _other_order_choices;
|
||||
}
|
||||
}
|
||||
|
||||
public IOrderTypeVM child_order
|
||||
{
|
||||
get
|
||||
{
|
||||
init();
|
||||
return _child_order;
|
||||
}
|
||||
set
|
||||
{
|
||||
Disposable.dispose(ref _child_order_errors_sub);
|
||||
_child_order = value;
|
||||
_child_order?.init();
|
||||
if (_child_order is INotifyDataErrorInfo ndei)
|
||||
{
|
||||
ndei.ErrorsChanged += on_errors_changed;
|
||||
void on_errors_changed(object s, DataErrorsChangedEventArgs e) =>
|
||||
_validate();
|
||||
_child_order_errors_sub = Disposable.Create(() => ndei.ErrorsChanged -= on_errors_changed);
|
||||
}
|
||||
_validate();
|
||||
RaisePropertyChanged(nameof(child_order));
|
||||
}
|
||||
}
|
||||
|
||||
public IOrderTypeVM other_order
|
||||
{
|
||||
get
|
||||
{
|
||||
init();
|
||||
return _other_order;
|
||||
}
|
||||
set
|
||||
{
|
||||
Disposable.dispose(ref _other_order_errors_sub);
|
||||
_other_order = value;
|
||||
_other_order?.init();
|
||||
if (_other_order is INotifyDataErrorInfo ndei)
|
||||
{
|
||||
ndei.ErrorsChanged += on_errors_changed;
|
||||
void on_errors_changed(object s, DataErrorsChangedEventArgs e) =>
|
||||
_validate();
|
||||
_other_order_errors_sub = Disposable.Create(() => ndei.ErrorsChanged -= on_errors_changed);
|
||||
}
|
||||
_validate();
|
||||
RaisePropertyChanged(nameof(other_order));
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Disposable.dispose(ref _dispose);
|
||||
if (_child_order_choices != null)
|
||||
_child_order_choices.OfType<IDisposable>().DisposeAll();
|
||||
if (_other_order_choices != null)
|
||||
_other_order_choices.OfType<IDisposable>().DisposeAll();
|
||||
}
|
||||
|
||||
public override void init()
|
||||
{
|
||||
if (_child_order == null && _security.HasValue)
|
||||
_select_child_order();
|
||||
if (_other_order == null && _security.HasValue)
|
||||
_select_other_order();
|
||||
_validate();
|
||||
}
|
||||
|
||||
void _select_child_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_child_order_type.has_value ?
|
||||
_inline_props.selected_child_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_child_order(ot);
|
||||
}
|
||||
|
||||
void _select_child_order(CustomOneofCase ot)
|
||||
{
|
||||
_child_order = child_order_types.FirstOrDefault(vm => vm.order_type == ot);
|
||||
if (_child_order == null)
|
||||
_child_order = child_order_types.FirstOrDefault();
|
||||
RaisePropertyChanged(nameof(child_order));
|
||||
}
|
||||
|
||||
void _select_other_order()
|
||||
{
|
||||
CustomOneofCase ot = _inline_props != null && _inline_props.selected_other_order_type.has_value ?
|
||||
_inline_props.selected_other_order_type.value.key.type :
|
||||
model.factory.default_order_type(_security.Value, true);
|
||||
_select_other_order(ot);
|
||||
}
|
||||
|
||||
void _select_other_order(CustomOneofCase ot)
|
||||
{
|
||||
_other_order = other_order_types.FirstOrDefault(vm => vm.order_type == ot);
|
||||
if (_other_order == null)
|
||||
_other_order = other_order_types.FirstOrDefault();
|
||||
RaisePropertyChanged(nameof(other_order));
|
||||
}
|
||||
|
||||
|
||||
void _validate()
|
||||
{
|
||||
if (_child_order == null || (_child_order is INotifyDataErrorInfo ndei && ndei.HasErrors))
|
||||
set_error(nameof(child_order), string.Empty, true);
|
||||
else clear_error(nameof(child_order));
|
||||
|
||||
if ((_other_order == null ) || (_other_order is INotifyDataErrorInfo hdei && hdei.HasErrors))
|
||||
set_error(nameof(other_order), string.Empty, true);
|
||||
else clear_error(nameof(other_order));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,12 @@ namespace mbts.spark {
|
||||
public static IOrderTypeVM stop(OrdersModel model, string id, string display_name) => new StopOrderVM(model, id, display_name);
|
||||
public static IOrderTypeVM stop_limit(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new StopLimitOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM time_box(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new TimeBoxOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM tick(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new TickOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM lean(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new LeanOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM join(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new JoinOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM top(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new TopOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM cover(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new CoverOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM oco(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new OCOOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM pricer(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new PricerOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM offset(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new OffsetOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM trigger(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new TriggerOrderVM(model, security_md_source, id, display_name);
|
||||
public static IOrderTypeVM iceberg(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name) => new IcebergOrderVM(model, security_md_source, id, display_name);
|
||||
@@ -34,11 +35,12 @@ namespace mbts.spark {
|
||||
case CustomOneofCase.Stop: return stop(model, id, display_name);
|
||||
case CustomOneofCase.StopLimit: return stop_limit(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.TimeBox: return time_box(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Tick: return tick(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Lean: return lean(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Join: return join(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Top: return top(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Cover: return cover(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Oco : return oco(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Pricer: return pricer(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Offset: return offset(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Trigger: return trigger(model, security_md_source, id, display_name);
|
||||
case CustomOneofCase.Iceberg: return iceberg(model, security_md_source, id, display_name);
|
||||
|
||||
+25
-53
@@ -15,52 +15,42 @@ namespace mbts.spark
|
||||
{
|
||||
static partial class OrderTypeVMFactory
|
||||
{
|
||||
class InlineTickOrderProperties
|
||||
class InlinePricerOrderProperties
|
||||
{
|
||||
public InlineTickOrderProperties (OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
public InlinePricerOrderProperties (OrderTemplateHeader selected_child_order_type, IReadOnlyCollection<OrderTemplateHeader> child_order_types)
|
||||
{
|
||||
ExceptionAssert.InvalidOperation.That(child_order_types.Contains(selected_child_order_type), $"Child order type {selected_child_order_type} is not in child_order_types");
|
||||
this.selected_child_order_type = new InlineUserProperty<OrderTemplateHeader>(selected_child_order_type, true);
|
||||
this.child_order_types = new InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>>(child_order_types, true);
|
||||
tick_offset_on_deploy = new InlineUserProperty<uint>(0, false);
|
||||
cross_threshold = new InlineUserProperty<bts.spark.QuantityMeasure>(
|
||||
new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1}, false);
|
||||
cross_ticks = new InlineUserProperty<uint>(0, false);
|
||||
max_chase_ticks = new InlineUserProperty<uint>(10, false);
|
||||
detach_on_toward = new InlineUserProperty<bool>(true, false);
|
||||
price_offset_ticks = new InlineUserProperty<int>(0, false);
|
||||
price_factor = new InlineUserProperty<double>(0, false);
|
||||
}
|
||||
public readonly InlineUserProperty<OrderTemplateHeader> selected_child_order_type;
|
||||
public readonly InlineUserProperty<IReadOnlyCollection<OrderTemplateHeader>> child_order_types;
|
||||
|
||||
public readonly InlineUserProperty<uint> tick_offset_on_deploy;
|
||||
public readonly InlineUserProperty<bts.spark.QuantityMeasure> cross_threshold;
|
||||
public readonly InlineUserProperty<uint> cross_ticks;
|
||||
public readonly InlineUserProperty<uint> max_chase_ticks;
|
||||
public readonly InlineUserProperty<bool> detach_on_toward;
|
||||
public readonly InlineUserProperty<int> price_offset_ticks;
|
||||
public readonly InlineUserProperty<double> price_factor;
|
||||
}
|
||||
|
||||
class TickOrderVM : OrderTypeVMBase<TickOrderDefinition>, IHierarchicalOrderTypeVM, IDisposable
|
||||
class PricerOrderVM : OrderTypeVMBase<PricerOrderDefinition>, IHierarchicalOrderTypeVM, IDisposable
|
||||
{
|
||||
readonly IObservable<SecurityMD> _security_md_source;
|
||||
SecurityImmutable? _security;
|
||||
ObservableCollection<OrderTemplateHeader> _order_types = new ObservableCollection<OrderTemplateHeader>();
|
||||
ObservableAutoWrapper<IOrderTypeVM, OrderTemplateHeader> _child_order_choices;
|
||||
InlineTickOrderProperties _inline_props;
|
||||
InlinePricerOrderProperties _inline_props;
|
||||
IOrderTypeVM _child_order;
|
||||
IDisposable _dispose, _child_order_errors_sub;
|
||||
|
||||
public uint tick_offset_on_deploy { get; set; } = 0;
|
||||
public bts.spark.QuantityMeasure cross_threshold { get; set; } = new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1 };
|
||||
public uint cross_ticks { get; set; } = 0;
|
||||
public uint max_chase_ticks { get; set; } = 10;
|
||||
public bool detach_on_toward { get; set; } = true;
|
||||
public int price_offset_ticks { get; set; } = 0;
|
||||
public double price_factor { get; set; } = 1.0;
|
||||
|
||||
public TickOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
public PricerOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source, string id, string display_name)
|
||||
: this(model, security_md_source, security_md_source.Select(smd =>
|
||||
new InlineTickOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name) { }
|
||||
new InlinePricerOrderProperties(new OrderTemplateHeader(model.factory.default_order_type(smd.security)), model.factory.default_order_types(smd.security).Select(t => new OrderTemplateHeader(t)).ToList())), id, display_name) { }
|
||||
|
||||
public TickOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlineTickOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
public PricerOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source,
|
||||
IObservable<InlinePricerOrderProperties> inline_properties, string id, string display_name) : base(model, id, display_name)
|
||||
{
|
||||
_security_md_source = security_md_source;
|
||||
_dispose = Disposable.Create(
|
||||
@@ -76,31 +66,16 @@ namespace mbts.spark
|
||||
{
|
||||
_select_child_order(p.selected_child_order_type.value.key.type);
|
||||
}
|
||||
if (p.tick_offset_on_deploy.force_override)
|
||||
if (p.price_offset_ticks.force_override)
|
||||
{
|
||||
tick_offset_on_deploy = p.tick_offset_on_deploy.value;
|
||||
RaisePropertyChanged(nameof(tick_offset_on_deploy));
|
||||
price_offset_ticks = p.price_offset_ticks.value;
|
||||
RaisePropertyChanged(nameof(price_offset_ticks));
|
||||
}
|
||||
if (p.cross_threshold.force_override)
|
||||
if (p.price_factor.force_override)
|
||||
{
|
||||
cross_threshold = p.cross_threshold.value;
|
||||
RaisePropertyChanged(nameof(cross_threshold));
|
||||
}
|
||||
if (p.cross_ticks.force_override)
|
||||
{
|
||||
cross_ticks = p.cross_ticks.value;
|
||||
RaisePropertyChanged(nameof(cross_ticks));
|
||||
}
|
||||
if (p.max_chase_ticks.force_override)
|
||||
{
|
||||
max_chase_ticks = p.max_chase_ticks.value;
|
||||
RaisePropertyChanged(nameof(max_chase_ticks));
|
||||
}
|
||||
if (p.detach_on_toward.force_override)
|
||||
{
|
||||
detach_on_toward = p.detach_on_toward.value;
|
||||
RaisePropertyChanged(nameof(detach_on_toward));
|
||||
}
|
||||
price_factor = p.price_factor.value;
|
||||
RaisePropertyChanged(nameof(price_factor));
|
||||
}
|
||||
_inline_props = p;
|
||||
_validate();
|
||||
})
|
||||
@@ -115,14 +90,11 @@ namespace mbts.spark
|
||||
_validate();
|
||||
if (!HasErrors)
|
||||
{
|
||||
var i = factory.tick_order();
|
||||
i.TickOffsetOnDeploy = tick_offset_on_deploy;
|
||||
i.CrossThreshold = cross_threshold;
|
||||
i.CrossTicks = cross_ticks;
|
||||
i.MaxChaseTicks = max_chase_ticks;
|
||||
i.DetachOnToward = detach_on_toward;
|
||||
var i = factory.pricer_order();
|
||||
i.PriceOffsetTicks = price_offset_ticks;
|
||||
i.PriceFactor = price_factor;
|
||||
child_order.assign_to(i.Child);
|
||||
value.Tick = i;
|
||||
value.Pricer = i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +211,8 @@ namespace mbts.ui {
|
||||
public static BTSColor lean_order { get { return new BTSColor(255, 170, 210); } }
|
||||
public static BTSColor join_order { get { return new BTSColor(200, 171, 232); } }
|
||||
public static BTSColor cover_order { get { return new BTSColor(134, 232, 224); } }
|
||||
public static BTSColor oco_order { get { return new BTSColor(110, 94, 11); } }
|
||||
public static BTSColor pricer_order { get { return new BTSColor(170, 132, 150); } }
|
||||
public static BTSColor trigger_order { get { return new BTSColor(172, 255, 179); } }
|
||||
public static BTSColor off_order { get { return new BTSColor(0x8a, 0x00, 0x5f); } }//8a005f
|
||||
public static BTSColor top_order { get { return new BTSColor(0xdd, 0x7a, 0x27); } }//dd7a27
|
||||
|
||||
@@ -166,51 +166,6 @@
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</usp:OrderModificationTemplateSelector.TimeBoxOrderTemplate>
|
||||
<usp:OrderModificationTemplateSelector.TickOrderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="12"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Row="1" VerticalAlignment="Center">Cross Thresh</TextBlock>
|
||||
<uag:QuantityMeasureControl Grid.Row="1" Grid.Column="2" QuantityMeasure="{Binding cross_threshold}"/>
|
||||
|
||||
<TextBlock Grid.Row="3" VerticalAlignment="Center">Cross Ticks</TextBlock>
|
||||
<c:TickUpDownUInt Grid.Row="3" Grid.Column="2" Value="{Binding cross_ticks}"/>
|
||||
<TextBlock Grid.Row="5" VerticalAlignment="Center">Max Chase Ticks</TextBlock>
|
||||
<c:TickUpDownUInt Grid.Row="5" Grid.Column="2" Value="{Binding max_chase_ticks}"/>
|
||||
<CheckBox Grid.Row="7" Grid.Column="2" VerticalAlignment="Center" Margin="0,0,0,0" IsChecked="{Binding detach_on_toward}">Detach on Toward</CheckBox>
|
||||
<TextBlock Grid.Row="9" VerticalAlignment="Center">Initial Tick Offset</TextBlock>
|
||||
<c:TickUpDownUInt Grid.Row="9" Grid.Column="2" Value="{Binding tick_offset_on_deploy}"/>
|
||||
<TextBlock Grid.Row="11">Child</TextBlock>
|
||||
<uag:OrderDetailsPopupControl
|
||||
Grid.Row="11" Grid.Column="2"
|
||||
IsOpen="{Binding child_order.editable_properties_open, FallbackValue=False}"
|
||||
ItemsSource="{Binding child_order_types}"
|
||||
SelectedItem="{Binding child_order}"
|
||||
HasEditableProperties="{Binding child_order.has_editable_properties, FallbackValue=False}"
|
||||
/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</usp:OrderModificationTemplateSelector.TickOrderTemplate>
|
||||
<usp:OrderModificationTemplateSelector.LeanOrderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
@@ -379,16 +334,16 @@
|
||||
Orientation="Horizontal"
|
||||
Grid.Row="1"
|
||||
>
|
||||
<TextBlock VerticalAlignment="Center" >Hedge Ticks</TextBlock>
|
||||
<c:HelpButton Margin="4,0,0,0" ToolTip="This is the number of ticks to offset the hedge." />
|
||||
<TextBlock VerticalAlignment="Center" >Profit Ticks</TextBlock>
|
||||
<c:HelpButton Margin="4,0,0,0" ToolTip="This is the number of ticks in your favor to offset the profit/hedge order." />
|
||||
</StackPanel>
|
||||
<c:TickUpDownInt Grid.Row="1" Grid.Column="2" Value="{Binding hedge_ticks}"/>
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Grid.Row="3"
|
||||
>
|
||||
<TextBlock VerticalAlignment="Center">Hedge</TextBlock>
|
||||
<c:HelpButton Margin="4,0,0,0" ToolTip="This is the type of the hedge order to send for each fill of Child Order." />
|
||||
<TextBlock VerticalAlignment="Center">Profit Order</TextBlock>
|
||||
<c:HelpButton Margin="4,0,0,0" ToolTip="This is the type of the profit/hedge order to send for each fill of Child Order." />
|
||||
</StackPanel>
|
||||
<uag:OrderDetailsPopupControl
|
||||
Grid.Row="3" Grid.Column="2"
|
||||
@@ -415,6 +370,68 @@
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</usp:OrderModificationTemplateSelector.CoverOrderTemplate>
|
||||
<usp:OrderModificationTemplateSelector.OCOOrderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="12"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="1" >
|
||||
<TextBlock VerticalAlignment="Center" >Stop Ticks</TextBlock>
|
||||
<c:HelpButton Margin="4,0,0,0" ToolTip="This is the number of ticks away from the main order to start the 'stop' order." />
|
||||
</StackPanel>
|
||||
<c:TickUpDownInt Grid.Row="1" Grid.Column="2" Value="{Binding other_ticks}"/>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="3" >
|
||||
<TextBlock VerticalAlignment="Center" >Stop Side</TextBlock>
|
||||
<c:HelpButton Margin="4,0,0,0" ToolTip="The Side of the 'stop' order" />
|
||||
</StackPanel>
|
||||
<ComboBox Grid.Row="3" Grid.Column="2" ItemsSource="{Binding other_side_types}" ItemTemplate="{StaticResource EnumDescriptionTemplate}" SelectedItem="{Binding other_side}"/>
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Grid.Row="5"
|
||||
>
|
||||
<TextBlock VerticalAlignment="Center">Stop Order</TextBlock>
|
||||
<c:HelpButton Margin="4,0,0,0" ToolTip="This is the type of the 'stop' order to send." />
|
||||
</StackPanel>
|
||||
<uag:OrderDetailsPopupControl
|
||||
Grid.Row="5" Grid.Column="2"
|
||||
IsOpen="{Binding other_order.editable_properties_open, FallbackValue=False}"
|
||||
ItemsSource="{Binding other_order_types}"
|
||||
SelectedItem="{Binding other_order}"
|
||||
HasEditableProperties="{Binding other_order.has_editable_properties, FallbackValue=False}"
|
||||
/>
|
||||
<StackPanel
|
||||
Orientation="Horizontal"
|
||||
Grid.Row="7"
|
||||
>
|
||||
<TextBlock VerticalAlignment="Center">Child</TextBlock>
|
||||
<c:HelpButton Margin="4,0,0,0" ToolTip="This is the type of order to be placed when the algo is triggered." />
|
||||
</StackPanel>
|
||||
|
||||
<uag:OrderDetailsPopupControl
|
||||
Grid.Row="7" Grid.Column="2"
|
||||
IsOpen="{Binding child_order.editable_properties_open, FallbackValue=False}"
|
||||
ItemsSource="{Binding child_order_types}"
|
||||
SelectedItem="{Binding child_order}"
|
||||
HasEditableProperties="{Binding child_order.has_editable_properties, FallbackValue=False}"
|
||||
/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</usp:OrderModificationTemplateSelector.OCOOrderTemplate>
|
||||
<usp:OrderModificationTemplateSelector.OffsetOrderTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
@@ -773,9 +790,11 @@
|
||||
</usp:DynamicOrderParamTemplateSelector>
|
||||
</ItemsControl.ItemTemplateSelector>
|
||||
</ItemsControl>
|
||||
<TextBlock Grid.Row="3">Child</TextBlock>
|
||||
<TextBlock Grid.Row="3"
|
||||
Visibility="{Binding has_child, Converter={StaticResource BooleanToVisibilityConverter}}" >Child</TextBlock>
|
||||
<uag:OrderDetailsPopupControl
|
||||
Grid.Row="3" Grid.Column="2"
|
||||
Grid.Row="3" Grid.Column="2"
|
||||
Visibility="{Binding has_child, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
IsOpen="{Binding child_order.editable_properties_open, FallbackValue=False}"
|
||||
ItemsSource="{Binding child_order_types}"
|
||||
SelectedItem="{Binding child_order}"
|
||||
|
||||
@@ -25,7 +25,6 @@ namespace mbts.spark.utilities {
|
||||
static readonly OrderMetadata _default_order_metadata = new OrderMetadata { KeyBinding = "", Color = BTSColors.Orders.spreader_order };
|
||||
static readonly CustomOrderDefinition.CustomOneofCase[]
|
||||
// The following standard types are not yet ready for production use:
|
||||
// CustomOrderDefinition.CustomOneofCase.Tick,
|
||||
// CustomOrderDefinition.CustomOneofCase.Dynamic,
|
||||
_standard_types = new[] {
|
||||
CustomOrderDefinition.CustomOneofCase.Market,
|
||||
@@ -37,6 +36,7 @@ namespace mbts.spark.utilities {
|
||||
CustomOrderDefinition.CustomOneofCase.Lean,
|
||||
CustomOrderDefinition.CustomOneofCase.Join,
|
||||
CustomOrderDefinition.CustomOneofCase.Cover,
|
||||
CustomOrderDefinition.CustomOneofCase.Oco,
|
||||
CustomOrderDefinition.CustomOneofCase.Offset,
|
||||
CustomOrderDefinition.CustomOneofCase.Top,
|
||||
CustomOrderDefinition.CustomOneofCase.Trigger,
|
||||
@@ -228,6 +228,15 @@ namespace mbts.spark.utilities {
|
||||
Child = custom_order(),
|
||||
Hedge = custom_order(),
|
||||
};
|
||||
public OCOOrderDefinition oco_order() => new OCOOrderDefinition
|
||||
{
|
||||
Child = custom_order(),
|
||||
Other = custom_order(),
|
||||
};
|
||||
public PricerOrderDefinition pricer_order() => new PricerOrderDefinition
|
||||
{
|
||||
Child = custom_order(),
|
||||
};
|
||||
public OffsetOrderDefinition offset_order() => new OffsetOrderDefinition
|
||||
{
|
||||
Child = custom_order(),
|
||||
@@ -262,6 +271,8 @@ namespace mbts.spark.utilities {
|
||||
case CustomOrderDefinition.CustomOneofCase.Join: rv.Join = join_order(); break;
|
||||
case CustomOrderDefinition.CustomOneofCase.Top: rv.Top = top_order(); break;
|
||||
case CustomOrderDefinition.CustomOneofCase.Cover: rv.Cover = cover_order(); break;
|
||||
case CustomOrderDefinition.CustomOneofCase.Oco: rv.Oco = oco_order(); break;
|
||||
case CustomOrderDefinition.CustomOneofCase.Pricer: rv.Pricer = pricer_order(); break;
|
||||
case CustomOrderDefinition.CustomOneofCase.Offset: rv.Offset = offset_order(); break;
|
||||
case CustomOrderDefinition.CustomOneofCase.Trigger: rv.Trigger = trigger_order(); break;
|
||||
case CustomOrderDefinition.CustomOneofCase.Spreader: rv.Spreader = spreader_order(); break;
|
||||
@@ -285,6 +296,8 @@ namespace mbts.spark.utilities {
|
||||
case CustomOrderDefinition.CustomOneofCase.Join: return new OrderMetadata { KeyBinding = "J", Color = BTSColors.Orders.join_order };
|
||||
case CustomOrderDefinition.CustomOneofCase.Top: return new OrderMetadata { KeyBinding = "D", Color = BTSColors.Orders.top_order };
|
||||
case CustomOrderDefinition.CustomOneofCase.Cover: return new OrderMetadata { KeyBinding = "C", Color = BTSColors.Orders.cover_order };
|
||||
case CustomOrderDefinition.CustomOneofCase.Oco: return new OrderMetadata { KeyBinding = "C", Color = BTSColors.Orders.oco_order };
|
||||
case CustomOrderDefinition.CustomOneofCase.Pricer: return new OrderMetadata { KeyBinding = "C", Color = BTSColors.Orders.pricer_order };
|
||||
case CustomOrderDefinition.CustomOneofCase.Offset: return new OrderMetadata { KeyBinding = "O", Color = BTSColors.Orders.tick_order };
|
||||
case CustomOrderDefinition.CustomOneofCase.Trigger: return new OrderMetadata { KeyBinding = "T", Color = BTSColors.Orders.trigger_order };
|
||||
case CustomOrderDefinition.CustomOneofCase.Spreader: goto default;
|
||||
@@ -306,6 +319,8 @@ namespace mbts.spark.utilities {
|
||||
case OrderState.CustomOneofCase.Join: return new OrderMetadata { KeyBinding = "J", Color = BTSColors.Orders.join_order };
|
||||
case OrderState.CustomOneofCase.Top: return new OrderMetadata { KeyBinding = "D", Color = BTSColors.Orders.top_order };
|
||||
case OrderState.CustomOneofCase.Cover: return new OrderMetadata { KeyBinding = "C", Color = BTSColors.Orders.cover_order };
|
||||
case OrderState.CustomOneofCase.Oco: return new OrderMetadata { KeyBinding = "C", Color = BTSColors.Orders.oco_order };
|
||||
case OrderState.CustomOneofCase.Pricer: return new OrderMetadata { KeyBinding = "C", Color = BTSColors.Orders.pricer_order };
|
||||
case OrderState.CustomOneofCase.Offset: return new OrderMetadata { KeyBinding = "O", Color = BTSColors.Orders.tick_order };
|
||||
case OrderState.CustomOneofCase.Trigger: return new OrderMetadata { KeyBinding = "T", Color = BTSColors.Orders.trigger_order };
|
||||
case OrderState.CustomOneofCase.Spreader: goto default;
|
||||
@@ -345,6 +360,8 @@ namespace mbts.spark.utilities {
|
||||
case nameof(JoinOrderDefinition): return CustomOrderDefinition.CustomOneofCase.Join;
|
||||
case nameof(TopOrderDefinition): return CustomOrderDefinition.CustomOneofCase.Top;
|
||||
case nameof(CoverOrderDefinition): return CustomOrderDefinition.CustomOneofCase.Cover;
|
||||
case nameof(OCOOrderDefinition): return CustomOrderDefinition.CustomOneofCase.Oco;
|
||||
case nameof(PricerOrderDefinition): return CustomOrderDefinition.CustomOneofCase.Pricer;
|
||||
case nameof(OffsetOrderDefinition): return CustomOrderDefinition.CustomOneofCase.Offset;
|
||||
case nameof(TriggerOrderDefinition): return CustomOrderDefinition.CustomOneofCase.Trigger;
|
||||
case nameof(DynamicOrderDefinition): return CustomOrderDefinition.CustomOneofCase.Dynamic;
|
||||
|
||||
@@ -141,4 +141,4 @@ if (WIN32)
|
||||
include(${CMAKE_SOURCE_DIR}/tools/vs_filters.cmake)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
@@ -73,6 +73,8 @@ message CustomOrderDefinition
|
||||
TriggerOrderDefinition trigger = 22;
|
||||
CoverOrderDefinition cover = 23;
|
||||
OffsetOrderDefinition offset = 24;
|
||||
OCOOrderDefinition oco = 25;
|
||||
PricerOrderDefinition pricer = 26;
|
||||
|
||||
DynamicOrderDefinition dynamic = 1000;
|
||||
}
|
||||
@@ -154,6 +156,17 @@ message OffsetOrderDefinition {
|
||||
uint32 tick_offset_on_deploy = 1;
|
||||
CustomOrderDefinition child = 6;
|
||||
}
|
||||
message OCOOrderDefinition {
|
||||
CustomOrderDefinition other = 1;
|
||||
int32 other_ticks = 2;
|
||||
api.RelativeSide other_side = 4;
|
||||
CustomOrderDefinition child = 3;
|
||||
}
|
||||
message PricerOrderDefinition {
|
||||
int32 price_offset_ticks = 1;
|
||||
double price_factor = 2;
|
||||
CustomOrderDefinition child = 3;
|
||||
}
|
||||
message DynamicOrderDefinition {
|
||||
string dynamic_order_type = 1;
|
||||
map<string, DynamicOrderParam> order_params = 2;
|
||||
@@ -203,6 +216,8 @@ message OrderState {
|
||||
TriggerOrderState trigger = 21;
|
||||
CoverOrderState cover = 22;
|
||||
OffsetOrderState offset = 24;
|
||||
OCOOrderState oco = 25;
|
||||
PricerOrderState pricer = 26;
|
||||
|
||||
DynamicOrderState dynamic = 255; // do not use anything bigger than 255, or things will break
|
||||
}
|
||||
@@ -276,6 +291,8 @@ message TopOrderState {}
|
||||
message TriggerOrderState {}
|
||||
message CoverOrderState {}
|
||||
message OffsetOrderState {}
|
||||
message OCOOrderState {}
|
||||
message PricerOrderState {}
|
||||
message DynamicOrderState {}
|
||||
|
||||
enum OrderStatus {
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
using std::vector;
|
||||
#include <google/protobuf/stubs/common.h>
|
||||
#include <google/protobuf/stubs/stringpiece.h>
|
||||
|
||||
|
||||
@@ -66,6 +66,14 @@ enum Side {
|
||||
SIDE_SELL = 50;
|
||||
}
|
||||
|
||||
enum RelativeSide {
|
||||
RELATIVESIDE_UNDEFINED = 0;
|
||||
RELATIVESIDE_OPPOSITE = 1;
|
||||
RELATIVESIDE_SAME = 2;
|
||||
RELATIVESIDE_BUY = 49;
|
||||
RELATIVESIDE_SELL = 50;
|
||||
}
|
||||
|
||||
enum PutOrCall {
|
||||
PUTORCALL_PUT = 0;
|
||||
PUTORCALL_CALL = 1;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace orderman {
|
||||
class ChildOrder {
|
||||
public:
|
||||
ChildOrder()
|
||||
: _order(nullptr), _parent_order_services(nullptr), _active(false) {}
|
||||
: _order(nullptr), _parent_order_services(nullptr), _child_order_services(nullptr), _active(false) {}
|
||||
|
||||
ChildOrder(Order &o, OrderServices &services)
|
||||
: _order(&o), _parent_order_services(&services),
|
||||
|
||||
@@ -122,6 +122,12 @@ class OrderStateUpdateEvent : public mercury::Event<OrderStateUpdateEvent> {
|
||||
case api::orderman::OrderState::kOffset:
|
||||
result.mutable_offset();
|
||||
break;
|
||||
case api::orderman::OrderState::kOco:
|
||||
result.mutable_oco();
|
||||
break;
|
||||
case api::orderman::OrderState::kPricer:
|
||||
result.mutable_pricer();
|
||||
break;
|
||||
case api::orderman::OrderState::kDynamic:
|
||||
result.mutable_dynamic();
|
||||
break;
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
#include "lib/orderman/orders/book_algos/JoinOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/LeanOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/OffsetOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/TickOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/OCOOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/PricerOrder.h"
|
||||
#include "lib/orderman/orders/book_algos/TopOrder.h"
|
||||
#include "lib/orderman/orders/spreader_orders/SpreaderOrder.h"
|
||||
|
||||
@@ -148,7 +149,7 @@ Order &OrderFactory::allocate(OrderKey k, OrderKey pk,
|
||||
order_ptr.reset(new orderman::TimeBoxOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kTick:
|
||||
order_ptr.reset(new orderman::TickOrder());
|
||||
bts_assert(false);
|
||||
break;
|
||||
case CustomOrderDefinition::kLean:
|
||||
order_ptr.reset(new orderman::LeanOrder());
|
||||
@@ -167,7 +168,13 @@ Order &OrderFactory::allocate(OrderKey k, OrderKey pk,
|
||||
break;
|
||||
case CustomOrderDefinition::kOffset:
|
||||
order_ptr.reset(new orderman::OffsetOrder());
|
||||
break;
|
||||
break;
|
||||
case CustomOrderDefinition::kOco:
|
||||
order_ptr.reset(new orderman::OCOOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kPricer:
|
||||
order_ptr.reset(new orderman::PricerOrder());
|
||||
break;
|
||||
case CustomOrderDefinition::kDynamic: {
|
||||
order_ptr = me->dynamic_order_registry.build(
|
||||
def.custom_def().dynamic().dynamic_order_type());
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "BookAlgo.h"
|
||||
#include "lib/orderman/actors/order_manager/OrderBuilder.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
#include "lib/utils/helper_macros.h"
|
||||
#include "lib/orderman/actors/order_manager/OrderBuilder.h"
|
||||
#include <google/protobuf/timestamp.pb.h>
|
||||
|
||||
namespace bts {
|
||||
@@ -9,113 +9,165 @@ namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
struct BookAlgo::PImpl {
|
||||
PImpl()
|
||||
: services(nullptr), fake_detached_child(false), supports_hedge(false),
|
||||
has_activated_child(false) {}
|
||||
|
||||
OrderServices *services;
|
||||
|
||||
struct BookAlgo::PImpl
|
||||
{
|
||||
PImpl() : services(nullptr), is_detached(false),
|
||||
supports_hedge(false), has_activated_child(false)
|
||||
{
|
||||
}
|
||||
|
||||
OrderServices* services;
|
||||
|
||||
api::orderman::OrderDefinition def;
|
||||
api::orderman::OrderState state;
|
||||
|
||||
|
||||
OrderBuilder child_builder;
|
||||
ChildOrder child;
|
||||
api::orderman::OrderState child_state;
|
||||
bool fake_detached_child;
|
||||
|
||||
bool supports_hedge;
|
||||
OrderBuilder hedge_builder;
|
||||
std::vector<ChildOrder> hedges;
|
||||
using HedgeStateMap =
|
||||
boost::container::flat_map<OrderKey, api::orderman::OrderState>;
|
||||
HedgeStateMap hedges_state;
|
||||
|
||||
ChildOrder child;
|
||||
api::orderman::OrderState child_state;
|
||||
bool is_detached;
|
||||
|
||||
bool supports_hedge;
|
||||
OrderBuilder hedge_builder;
|
||||
|
||||
BookAlgo::HedgeMap hedges;
|
||||
BookAlgo::HedgeStateMap hedges_state;
|
||||
|
||||
double tick_size;
|
||||
bool has_activated_child;
|
||||
};
|
||||
|
||||
BookAlgo::BookAlgo() : me(new PImpl()) {}
|
||||
BookAlgo::BookAlgo() : me(new PImpl())
|
||||
{
|
||||
}
|
||||
|
||||
BookAlgo::~BookAlgo() {}
|
||||
|
||||
const api::orderman::OrderDefinition &BookAlgo::definition() const {
|
||||
|
||||
|
||||
const api::orderman::OrderDefinition& BookAlgo::definition() const
|
||||
{
|
||||
return me->def;
|
||||
}
|
||||
|
||||
const api::orderman::OrderState &BookAlgo::this_state() const {
|
||||
const api::orderman::OrderState& BookAlgo::this_state() const
|
||||
{
|
||||
return me->state;
|
||||
}
|
||||
|
||||
void BookAlgo::set_price(double p) { me->state.set_price(p); }
|
||||
|
||||
void BookAlgo::set_quantity(uint32_t s) { me->state.set_quantity(s); }
|
||||
|
||||
const api::orderman::OrderState &BookAlgo::child_state() const {
|
||||
return me->child_state;
|
||||
|
||||
void BookAlgo::set_price(double p)
|
||||
{
|
||||
me->state.set_price(p);
|
||||
}
|
||||
|
||||
void BookAlgo::set_quantity(uint32_t s)
|
||||
{
|
||||
me->state.set_quantity(s);
|
||||
}
|
||||
|
||||
void BookAlgo::set_child_price(double p) { me->child_state.set_price(p); }
|
||||
const api::orderman::OrderState& BookAlgo::child_state() const
|
||||
{
|
||||
return me->child_state;
|
||||
}
|
||||
|
||||
void BookAlgo::set_child_price(double p)
|
||||
{
|
||||
me->child_state.set_price(p);
|
||||
}
|
||||
|
||||
void BookAlgo::set_child_quantity(uint32_t s) {
|
||||
void BookAlgo::set_child_quantity(uint32_t s)
|
||||
{
|
||||
me->child_state.set_quantity(s);
|
||||
}
|
||||
|
||||
void BookAlgo::activate_child(Price p, Quantity q) {
|
||||
// per Pedro, activating the child is not a synchronous calls, and he asserts
|
||||
// that this is done only once
|
||||
if (!me->has_activated_child) {
|
||||
void BookAlgo::activate_child(Price p, Quantity q)
|
||||
{
|
||||
//per Pedro, activating the child is not a synchronous calls, and he asserts that this is done only once
|
||||
if(!me->has_activated_child)
|
||||
{
|
||||
me->child.activate(p, q);
|
||||
me->has_activated_child = true;
|
||||
}
|
||||
}
|
||||
|
||||
void BookAlgo::update_child(Price p, Quantity q)
|
||||
{
|
||||
me->child.update(p, q);
|
||||
}
|
||||
|
||||
void BookAlgo::cancel_child()
|
||||
{
|
||||
me->child.cancel();
|
||||
}
|
||||
|
||||
void BookAlgo::build_and_send_hedge(Price p, Quantity q)
|
||||
{
|
||||
auto hedge = me->hedge_builder.build();
|
||||
auto key = hedge.key();
|
||||
me->hedges[key] = std::move(hedge);
|
||||
me->hedges[key].activate(p, q);
|
||||
}
|
||||
|
||||
void BookAlgo::update_child(Price p, Quantity q) { me->child.update(p, q); }
|
||||
|
||||
void BookAlgo::cancel_child() { me->child.cancel(); }
|
||||
|
||||
void BookAlgo::build_and_send_hedge(Price p, Quantity q) {
|
||||
auto hedge = me->hedge_builder.build();
|
||||
me->hedges.push_back(std::move(hedge));
|
||||
me->hedges.back().activate(p, q);
|
||||
double BookAlgo::tick_size() const
|
||||
{
|
||||
return me->tick_size;
|
||||
}
|
||||
|
||||
double BookAlgo::tick_size() const { return me->tick_size; }
|
||||
BookAlgo::HedgeStateMap& BookAlgo::hedges_state()
|
||||
{
|
||||
return me->hedges_state;
|
||||
}
|
||||
|
||||
void BookAlgo::on_init_new(const api::orderman::OrderDefinition &def,
|
||||
const PreActivationOrderServices &services) {
|
||||
BookAlgo::HedgeMap& BookAlgo::hedges()
|
||||
{
|
||||
return me->hedges;
|
||||
}
|
||||
|
||||
bool BookAlgo::is_detached() const
|
||||
{
|
||||
return me->is_detached;
|
||||
}
|
||||
|
||||
|
||||
void BookAlgo::on_init_new(const api::orderman::OrderDefinition& def,
|
||||
const PreActivationOrderServices &services)
|
||||
{
|
||||
me->services = nullptr;
|
||||
me->def = def;
|
||||
|
||||
me->child_state.set_status(ORDER_STATUS_INACTIVE);
|
||||
|
||||
me->child_state.set_status(ORDER_STATUS_INACTIVE);
|
||||
OrderDefinition child_def = def;
|
||||
setup_child(def, services, me->child_state, &child_def);
|
||||
me->child_builder = OrderBuilder(key(), child_def, services, 1);
|
||||
|
||||
OrderDefinition hedge_def = def;
|
||||
|
||||
OrderDefinition hedge_def = def;
|
||||
me->supports_hedge = setup_hedge(def, services, &hedge_def);
|
||||
if (me->supports_hedge)
|
||||
me->hedge_builder = OrderBuilder(key(), hedge_def, services, 4);
|
||||
|
||||
const bts::api::Security *sec =
|
||||
services.sec_db.resolve(SecurityKey(def.security_key()));
|
||||
if (sec) {
|
||||
if(me->supports_hedge)
|
||||
me->hedge_builder = OrderBuilder(key(), hedge_def, services, 4);
|
||||
|
||||
const bts::api::Security* sec = services.sec_db.resolve(SecurityKey(def.security_key()));
|
||||
if(sec)
|
||||
{
|
||||
me->tick_size = sec->contract_spec().low_tick();
|
||||
transition(ORDER_STATUS_INACTIVE);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
auto msg = fmt::format("Unknown security: {}", def.security_key());
|
||||
me->state.set_last_msg(msg);
|
||||
transition(ORDER_STATUS_REJECTED_BY_SPARK, msg);
|
||||
transition(ORDER_STATUS_REJECTED_BY_SPARK, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void BookAlgo::on_init_recovered(const api::orderman::OrderRecord &rec,
|
||||
const PreActivationOrderServices &) {
|
||||
void BookAlgo::on_init_recovered(const api::orderman::OrderRecord& rec,
|
||||
const PreActivationOrderServices &)
|
||||
{
|
||||
auto const &def = rec.def();
|
||||
me->def = def;
|
||||
me->state = rec.state();
|
||||
switch (me->state.status()) {
|
||||
case ORDER_STATUS_WORKING: {
|
||||
switch (me->state.status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
{
|
||||
auto msg = "System restarted with active BookAlgo";
|
||||
me->state.set_last_msg(msg);
|
||||
transition(ORDER_STATUS_ERROR, msg);
|
||||
@@ -139,24 +191,24 @@ void BookAlgo::on_init_recovered(const api::orderman::OrderRecord &rec,
|
||||
}
|
||||
}
|
||||
|
||||
void BookAlgo::on_activate(Price p, Quantity q, OrderServices &services,
|
||||
trace::CorID const &) {
|
||||
void BookAlgo::on_activate(Price p, Quantity q, OrderServices& services, trace::CorID const&)
|
||||
{
|
||||
bts_assert(!me->services);
|
||||
me->services = &services;
|
||||
switch (this_state().status()) {
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
me->child_builder.activate(services);
|
||||
if (me->supports_hedge)
|
||||
me->child_builder.activate(services);
|
||||
if(me->supports_hedge)
|
||||
me->hedge_builder.activate(services);
|
||||
|
||||
|
||||
me->child = me->child_builder.build();
|
||||
set_price(p.value());
|
||||
set_quantity(q.value());
|
||||
services.subscribe_to_child_updates(
|
||||
[this](auto const &os) { this->on_child_order_update(os); });
|
||||
services.subscribe_to_book(
|
||||
SecurityKey(me->def.security_key()),
|
||||
[this](auto const &b) { this->on_book_update(b); });
|
||||
[this](auto const &os) { this->on_child_order_update(os); });
|
||||
services.subscribe_to_book(SecurityKey(me->def.security_key()),
|
||||
[this](auto const &b) { this->on_book_update(b); });
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
break;
|
||||
|
||||
@@ -172,7 +224,7 @@ void BookAlgo::on_activate(Price p, Quantity q, OrderServices &services,
|
||||
// state)
|
||||
case ORDER_STATUS_WORKING:
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
@@ -181,11 +233,14 @@ void BookAlgo::on_activate(Price p, Quantity q, OrderServices &services,
|
||||
report_state();
|
||||
}
|
||||
|
||||
void BookAlgo::on_update(Price p, Quantity q, trace::CorID const &) {
|
||||
void BookAlgo::on_update(Price p, Quantity q, trace::CorID const&)
|
||||
{
|
||||
LOG(OrderMan, Info, "Updating BookAlgo {}", key().value());
|
||||
switch (this_state().status()) {
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (child_state().status()) {
|
||||
switch (child_state().status())
|
||||
{
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
set_price(p.value());
|
||||
set_quantity(q.value());
|
||||
@@ -193,8 +248,8 @@ void BookAlgo::on_update(Price p, Quantity q, trace::CorID const &) {
|
||||
case ORDER_STATUS_WORKING:
|
||||
set_price(p.value());
|
||||
set_quantity(q.value());
|
||||
if (!me->fake_detached_child)
|
||||
me->child.update(p, q);
|
||||
if(!me->is_detached)
|
||||
me->child.update(p,q);
|
||||
break;
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
// we launched our child but we are not yet able
|
||||
@@ -204,7 +259,7 @@ void BookAlgo::on_update(Price p, Quantity q, trace::CorID const &) {
|
||||
|
||||
// if the child was in any of these states we couldn't be
|
||||
// in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
@@ -235,22 +290,25 @@ void BookAlgo::on_update(Price p, Quantity q, trace::CorID const &) {
|
||||
report_state();
|
||||
}
|
||||
|
||||
void BookAlgo::on_crack(trace::CorID const &) {}
|
||||
void BookAlgo::on_crack(trace::CorID const&) {}
|
||||
|
||||
void BookAlgo::on_cancel(trace::CorID const &) {
|
||||
void BookAlgo::on_cancel(trace::CorID const&)
|
||||
{
|
||||
LOG(OrderMan, Info, "Canceling BookAlgo Order {}", key().value());
|
||||
|
||||
switch (this_state().status()) {
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (child_state().status()) {
|
||||
switch (child_state().status())
|
||||
{
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
transition(ORDER_STATUS_CANCELED);
|
||||
break;
|
||||
case ORDER_STATUS_WORKING:
|
||||
if (!me->fake_detached_child)
|
||||
if(!me->is_detached)
|
||||
me->child.cancel();
|
||||
for (auto &i : me->hedges)
|
||||
i.crack();
|
||||
for(auto& i : me->hedges)
|
||||
i.second.crack();
|
||||
transition(ORDER_STATUS_CANCELED);
|
||||
break;
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
@@ -259,7 +317,7 @@ void BookAlgo::on_cancel(trace::CorID const &) {
|
||||
break;
|
||||
|
||||
// child cannot be in any of these if we are in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
@@ -289,50 +347,103 @@ void BookAlgo::on_cancel(trace::CorID const &) {
|
||||
report_state();
|
||||
}
|
||||
|
||||
void BookAlgo::transition(api::orderman::OrderStatus new_status,
|
||||
std::string msg) {
|
||||
void BookAlgo::transition(api::orderman::OrderStatus new_status, std::string msg)
|
||||
{
|
||||
auto const &from = OrderStatus_Name(me->state.status());
|
||||
auto const &to = OrderStatus_Name(new_status);
|
||||
LOG(OrderMan, Info, "Transitioning BookAlgo {} from {} to {}. Msg: {}",
|
||||
key().value(), from, to, msg);
|
||||
LOG(OrderMan, Info, "Transitioning BookAlgo {} from {} to {}. Msg: {}", key().value(), from, to, msg);
|
||||
me->state.set_status(new_status);
|
||||
}
|
||||
|
||||
void BookAlgo::on_child_order_update(const OrderStateUpdateEvent &ev) {
|
||||
if (me->fake_detached_child)
|
||||
return;
|
||||
if (ev.key != me->child.key())
|
||||
void BookAlgo::on_child_order_update(const OrderStateUpdateEvent& ev)
|
||||
{
|
||||
if(me->is_detached)
|
||||
return;
|
||||
if(ev.key != me->child.key()) //hedge state change
|
||||
{
|
||||
api::orderman::OrderState orig_state = api::orderman::OrderState::default_instance(); //TODO this isn't quite right, should be hedgetype state
|
||||
auto it = me->hedges_state.find(ev.key);
|
||||
if(it != me->hedges_state.end())
|
||||
orig_state = it->second;
|
||||
me->hedges_state[ev.key] = ev.rebuild_state();
|
||||
else {
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (ev.status)
|
||||
{
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
break;
|
||||
case ORDER_STATUS_WORKING:
|
||||
process_hedge_state_change(orig_state, ev);
|
||||
break;
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
process_hedge_state_change(orig_state, ev);
|
||||
transition(ORDER_STATUS_COMPLETED);
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
process_hedge_state_change(orig_state, ev);
|
||||
transition(ORDER_STATUS_ERROR, "Unexpected child order state");
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else //child state change
|
||||
{
|
||||
api::orderman::OrderState orig_state = child_state();
|
||||
me->child_state = ev.rebuild_state();
|
||||
switch (this_state().status()) {
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (ev.status) {
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
break;
|
||||
case ORDER_STATUS_WORKING:
|
||||
if (me->supports_hedge)
|
||||
send_hedge_if_new_fills(orig_state, ev);
|
||||
break;
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
transition(ORDER_STATUS_COMPLETED);
|
||||
if (me->supports_hedge)
|
||||
send_hedge_if_new_fills(orig_state, ev);
|
||||
break;
|
||||
switch (ev.status)
|
||||
{
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
break;
|
||||
case ORDER_STATUS_WORKING:
|
||||
process_child_state_change(orig_state, ev);
|
||||
break;
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
process_child_state_change(orig_state, ev);
|
||||
transition(ORDER_STATUS_COMPLETED);
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
transition(ORDER_STATUS_ERROR, "Unexpected child order state");
|
||||
break;
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
process_child_state_change(orig_state, ev);
|
||||
transition(ORDER_STATUS_ERROR, "Unexpected child order state");
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -354,56 +465,55 @@ void BookAlgo::on_child_order_update(const OrderStateUpdateEvent &ev) {
|
||||
report_state();
|
||||
}
|
||||
|
||||
void BookAlgo::report_state() {
|
||||
auto merged_state = me->state;
|
||||
void BookAlgo::report_state()
|
||||
{
|
||||
OrderState merged_state = me->state;
|
||||
merged_state.set_filled_quantity(child_state().filled_quantity());
|
||||
merged_state.set_last_price(child_state().last_price());
|
||||
merged_state.set_avg_price(child_state().avg_price());
|
||||
merged_state.set_display_status(
|
||||
bts::api::orderman::OrderState_DisplayStatus::
|
||||
OrderState_DisplayStatus_HIDDEN);
|
||||
merged_state.set_display_status(bts::api::orderman::OrderState_DisplayStatus::OrderState_DisplayStatus_HIDDEN);
|
||||
me->services->report_state(merged_state);
|
||||
}
|
||||
|
||||
void BookAlgo::payup(const md::PriceSize &opposite,
|
||||
const bts::orderman::BookUpdateEvent &,
|
||||
uint32_t cross_ticks) {
|
||||
void BookAlgo::payup(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks)
|
||||
{
|
||||
double new_price = opposite.price() + me->tick_size * cross_ticks;
|
||||
me->child.update(Price(new_price), Quantity(this_state().quantity()));
|
||||
report_state();
|
||||
}
|
||||
|
||||
void BookAlgo::paydown(const md::PriceSize &opposite,
|
||||
const bts::orderman::BookUpdateEvent &,
|
||||
uint32_t cross_ticks) {
|
||||
void BookAlgo::paydown(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks)
|
||||
{
|
||||
double new_price = opposite.price() - me->tick_size * cross_ticks;
|
||||
me->child.update(Price(new_price), Quantity(this_state().quantity()));
|
||||
report_state();
|
||||
}
|
||||
|
||||
void BookAlgo::detach(bts::api::orderman::OrderStatus status_after_detach) {
|
||||
me->fake_detached_child = true;
|
||||
void BookAlgo::detach(bts::api::orderman::OrderStatus status_after_detach)
|
||||
{
|
||||
me->is_detached = true;
|
||||
me->child.crack();
|
||||
transition(status_after_detach);
|
||||
report_state();
|
||||
}
|
||||
|
||||
void BookAlgo::on_book_update(const bts::orderman::BookUpdateEvent &) {}
|
||||
void BookAlgo::on_book_update(const bts::orderman::BookUpdateEvent&) {}
|
||||
|
||||
bool BookAlgo::setup_hedge(const api::orderman::OrderDefinition &,
|
||||
const PreActivationOrderServices &,
|
||||
api::orderman::OrderDefinition *) {
|
||||
return false;
|
||||
bool BookAlgo::setup_hedge(const api::orderman::OrderDefinition&, const PreActivationOrderServices&, api::orderman::OrderDefinition*)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void BookAlgo::send_hedge_if_new_fills(
|
||||
const api::orderman::OrderState &orig_state,
|
||||
const OrderStateUpdateEvent &new_state) {
|
||||
UNUSED(orig_state);
|
||||
UNUSED(new_state);
|
||||
// uint32_t qty = new_state.state.filled_quantity() -
|
||||
// orig_state.filled_quantity(); UNUSED(qty);
|
||||
void BookAlgo::process_child_state_change(const api::orderman::OrderState& orig_state, const OrderStateUpdateEvent& new_state)
|
||||
{
|
||||
UNUSED(orig_state);UNUSED(new_state);
|
||||
}
|
||||
|
||||
void BookAlgo::process_hedge_state_change(const api::orderman::OrderState& orig_state, const OrderStateUpdateEvent& new_state)
|
||||
{
|
||||
UNUSED(orig_state);UNUSED(new_state);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -34,7 +34,8 @@ protected:
|
||||
api::orderman::OrderState&, api::orderman::OrderDefinition*) = 0;
|
||||
virtual bool setup_hedge(const api::orderman::OrderDefinition& parent, const PreActivationOrderServices&,
|
||||
api::orderman::OrderDefinition*);
|
||||
virtual void send_hedge_if_new_fills(const api::orderman::OrderState&, const OrderStateUpdateEvent&);
|
||||
virtual void process_child_state_change(const api::orderman::OrderState&, const OrderStateUpdateEvent&);
|
||||
virtual void process_hedge_state_change(const api::orderman::OrderState&, const OrderStateUpdateEvent&);
|
||||
|
||||
virtual void on_child_order_update(const OrderStateUpdateEvent&);
|
||||
virtual void on_book_update(const bts::orderman::BookUpdateEvent&);
|
||||
@@ -50,6 +51,7 @@ private:
|
||||
std::unique_ptr<PImpl> me;
|
||||
|
||||
protected:
|
||||
double tick_size() const;
|
||||
const api::orderman::OrderState& this_state() const;
|
||||
void set_price(double);
|
||||
void set_quantity(uint32_t);
|
||||
@@ -60,9 +62,14 @@ protected:
|
||||
void activate_child(Price p, Quantity q);
|
||||
void update_child(Price, Quantity);
|
||||
void cancel_child();
|
||||
bool is_detached() const;
|
||||
|
||||
void build_and_send_hedge(Price, Quantity);
|
||||
double tick_size() const;
|
||||
typedef boost::container::flat_map<OrderKey, ChildOrder> HedgeMap;
|
||||
typedef boost::container::flat_map<OrderKey, api::orderman::OrderState> HedgeStateMap;
|
||||
HedgeStateMap& hedges_state();
|
||||
HedgeMap& hedges();
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -10,87 +10,94 @@ namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
struct CoverOrder::PImpl {
|
||||
struct CoverOrder::PImpl
|
||||
{
|
||||
PImpl() {}
|
||||
|
||||
int hedge_ticks;
|
||||
OrderDefinition hedge_def;
|
||||
|
||||
int hedge_ticks;
|
||||
OrderDefinition hedge_def;
|
||||
};
|
||||
|
||||
|
||||
CoverOrder::CoverOrder() : me(new PImpl()) {}
|
||||
|
||||
CoverOrder::~CoverOrder() {}
|
||||
|
||||
void CoverOrder::setup_child(const api::orderman::OrderDefinition &this_def,
|
||||
const PreActivationOrderServices &,
|
||||
api::orderman::OrderState &initial_state,
|
||||
api::orderman::OrderDefinition *out_child) {
|
||||
void CoverOrder::setup_child(const api::orderman::OrderDefinition& this_def, const PreActivationOrderServices&,
|
||||
api::orderman::OrderState& initial_state, api::orderman::OrderDefinition* out_child)
|
||||
{
|
||||
initial_state.mutable_cover();
|
||||
auto const &cover_def = this_def.custom_def().cover();
|
||||
auto const &cover_def = this_def.custom_def().cover();
|
||||
*out_child->mutable_custom_def() = cover_def.child();
|
||||
|
||||
me->hedge_ticks = cover_def.hedge_ticks();
|
||||
|
||||
me->hedge_ticks = cover_def.hedge_ticks();
|
||||
}
|
||||
|
||||
bool CoverOrder::setup_hedge(const api::orderman::OrderDefinition &this_def,
|
||||
const PreActivationOrderServices &,
|
||||
api::orderman::OrderDefinition *out_hedge) {
|
||||
bool CoverOrder::setup_hedge(const api::orderman::OrderDefinition& this_def, const PreActivationOrderServices&,
|
||||
api::orderman::OrderDefinition* out_hedge)
|
||||
{
|
||||
auto const &cover_def = this_def.custom_def().cover();
|
||||
if (cover_def.has_hedge()) {
|
||||
*out_hedge->mutable_custom_def() = cover_def.hedge();
|
||||
if (definition().side() == api::SIDE_BUY)
|
||||
if(cover_def.has_hedge())
|
||||
{
|
||||
*out_hedge->mutable_custom_def() = cover_def.hedge();
|
||||
if(definition().side() == api::SIDE_BUY)
|
||||
out_hedge->set_side(api::SIDE_SELL);
|
||||
else
|
||||
out_hedge->set_side(api::SIDE_BUY);
|
||||
return true;
|
||||
} else
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void CoverOrder::send_hedge_if_new_fills(
|
||||
const api::orderman::OrderState &orig_state,
|
||||
const OrderStateUpdateEvent &new_state) {
|
||||
void CoverOrder::process_child_state_change(const api::orderman::OrderState& orig_state, const OrderStateUpdateEvent& new_state)
|
||||
{
|
||||
uint32_t qty = new_state.filled_quantity - orig_state.filled_quantity();
|
||||
if (qty > 0) {
|
||||
if(qty > 0)
|
||||
{
|
||||
double prx = new_state.last_price;
|
||||
if (definition().side() ==
|
||||
api::SIDE_BUY) // if this is a buy, I'm going to sell my hedge, nticks
|
||||
// higher than the fill price
|
||||
if(definition().side() == api::SIDE_BUY) //if this is a buy, I'm going to sell my hedge, nticks higher than the fill price
|
||||
prx = prx + tick_size() * me->hedge_ticks;
|
||||
else
|
||||
prx = prx - tick_size() * me->hedge_ticks;
|
||||
|
||||
|
||||
build_and_send_hedge(Price(prx), Quantity(qty));
|
||||
}
|
||||
}
|
||||
|
||||
void CoverOrder::on_book_update(const bts::orderman::BookUpdateEvent &) {
|
||||
switch (this_state().status()) {
|
||||
void CoverOrder::on_book_update(const bts::orderman::BookUpdateEvent& )
|
||||
{
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (child_state().status()) {
|
||||
case ORDER_STATUS_INACTIVE: {
|
||||
activate_child(Price(this_state().price()),
|
||||
Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
report_state();
|
||||
} break;
|
||||
case ORDER_STATUS_WORKING: {
|
||||
} break;
|
||||
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
switch (child_state().status())
|
||||
{
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
{
|
||||
activate_child(Price(this_state().price()), Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
report_state();
|
||||
}
|
||||
break;
|
||||
|
||||
// child cannot be in any of these states if we are in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
case ORDER_STATUS_WORKING:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
break;
|
||||
|
||||
// child cannot be in any of these states if we are in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
@@ -106,8 +113,9 @@ void CoverOrder::on_book_update(const bts::orderman::BookUpdateEvent &) {
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -22,7 +22,7 @@ protected:
|
||||
api::orderman::OrderState&, api::orderman::OrderDefinition*) override;
|
||||
bool setup_hedge(const api::orderman::OrderDefinition& parent, const PreActivationOrderServices&,
|
||||
api::orderman::OrderDefinition*) override;
|
||||
void send_hedge_if_new_fills(const api::orderman::OrderState&, const OrderStateUpdateEvent&) override;
|
||||
void process_child_state_change(const api::orderman::OrderState&, const OrderStateUpdateEvent&) override;
|
||||
void on_book_update(const bts::orderman::BookUpdateEvent&) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
#include "OCOOrder.h"
|
||||
|
||||
#include "lib/orderman/actors/order_manager/OrderBuilder.h"
|
||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderUtils.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
#include "lib/utils/helper_macros.h"
|
||||
#include <google/protobuf/timestamp.pb.h>
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
struct OCOOrder::PImpl
|
||||
{
|
||||
PImpl() {}
|
||||
|
||||
int other_ticks;
|
||||
bts::api::RelativeSide other_side;
|
||||
OrderDefinition other_def;
|
||||
bool hedge_sent;
|
||||
};
|
||||
|
||||
|
||||
OCOOrder::OCOOrder() : me(new PImpl()) {}
|
||||
|
||||
OCOOrder::~OCOOrder() {}
|
||||
|
||||
void OCOOrder::setup_child(const api::orderman::OrderDefinition& this_def, const PreActivationOrderServices&,
|
||||
api::orderman::OrderState& initial_state, api::orderman::OrderDefinition* out_child)
|
||||
{
|
||||
initial_state.mutable_oco();
|
||||
auto const &oco_def = this_def.custom_def().oco();
|
||||
*out_child->mutable_custom_def() = oco_def.child();
|
||||
|
||||
me->other_ticks = oco_def.other_ticks();
|
||||
me->other_side = oco_def.other_side();
|
||||
me->hedge_sent = false;
|
||||
}
|
||||
|
||||
//hedge here means 'other'
|
||||
bool OCOOrder::setup_hedge(const api::orderman::OrderDefinition& this_def, const PreActivationOrderServices&,
|
||||
api::orderman::OrderDefinition* out_hedge)
|
||||
{
|
||||
auto const &oco_def = this_def.custom_def().oco();
|
||||
if(oco_def.has_other())
|
||||
{
|
||||
*out_hedge->mutable_custom_def() = oco_def.other();
|
||||
bts_assert_msg(me->other_side != api::RELATIVESIDE_UNDEFINED, "undefined relativeside");
|
||||
|
||||
if(oco_def.other_side() == api::RELATIVESIDE_BUY)
|
||||
out_hedge->set_side(api::SIDE_BUY);
|
||||
else if(oco_def.other_side() == api::RELATIVESIDE_SELL)
|
||||
out_hedge->set_side(api::SIDE_SELL);
|
||||
else if(oco_def.other_side() == api::RELATIVESIDE_SAME)
|
||||
out_hedge->set_side(definition().side());
|
||||
else if(oco_def.other_side() == api::RELATIVESIDE_OPPOSITE)
|
||||
{
|
||||
if(definition().side() == api::SIDE_BUY)
|
||||
out_hedge->set_side(api::SIDE_SELL);
|
||||
else
|
||||
out_hedge->set_side(api::SIDE_BUY);
|
||||
}
|
||||
else
|
||||
bts_assert_msg(false, "unknown relativeside");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void OCOOrder::process_child_state_change(const api::orderman::OrderState& orig_state, const OrderStateUpdateEvent& new_state)
|
||||
{
|
||||
uint32_t fill_qty = new_state.filled_quantity - orig_state.filled_quantity();
|
||||
const auto& the_state = hedges_state();
|
||||
auto& the_hedges = hedges();
|
||||
for(const auto& i : the_state)
|
||||
{
|
||||
const auto& hedge_state = i.second;
|
||||
|
||||
uint32_t working_qty = hedge_state.quantity() - hedge_state.filled_quantity();
|
||||
uint32_t newqty = working_qty - std::min(fill_qty, working_qty);
|
||||
bts_assert(newqty <= working_qty);
|
||||
|
||||
auto it = the_hedges.find(i.first);
|
||||
if(it != the_hedges.end())
|
||||
{
|
||||
if(newqty != working_qty)
|
||||
{
|
||||
if(newqty > 0)
|
||||
{
|
||||
LOG(OrderMan, Info, "OCO reducing hedge qty from {} to {}", working_qty, newqty);
|
||||
it->second.update(Price(hedge_state.price()), Quantity(newqty));
|
||||
}
|
||||
else
|
||||
it->second.cancel();
|
||||
}
|
||||
else if(new_state.status != api::orderman::OrderStatus::ORDER_STATUS_PENDING_WORKING &&
|
||||
new_state.status != api::orderman::OrderStatus::ORDER_STATUS_WORKING)
|
||||
{
|
||||
it->second.cancel();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(OrderMan, Error, "OCO Can't find hedge order {}", i.first);
|
||||
cancel_child();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OCOOrder::process_hedge_state_change(const api::orderman::OrderState& orig_state, const OrderStateUpdateEvent& new_state)
|
||||
{
|
||||
uint32_t fill_qty = new_state.filled_quantity - orig_state.filled_quantity();
|
||||
uint32_t working_qty = child_state().quantity() - child_state().filled_quantity();
|
||||
uint32_t newqty = working_qty - std::min(fill_qty, working_qty);
|
||||
bts_assert(newqty <= working_qty);
|
||||
if(newqty != working_qty)
|
||||
{
|
||||
if(newqty > 0)
|
||||
{
|
||||
LOG(OrderMan, Info, "OCO reducing child qty from {} to {}", working_qty, newqty);
|
||||
update_child(Price(child_state().price()), Quantity(newqty));
|
||||
}
|
||||
else
|
||||
cancel_child();
|
||||
}
|
||||
else if(new_state.status != api::orderman::OrderStatus::ORDER_STATUS_PENDING_WORKING &&
|
||||
new_state.status != api::orderman::OrderStatus::ORDER_STATUS_WORKING)
|
||||
{
|
||||
cancel_child();
|
||||
}
|
||||
}
|
||||
|
||||
void OCOOrder::on_book_update(const bts::orderman::BookUpdateEvent& )
|
||||
{
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (child_state().status())
|
||||
{
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
{
|
||||
activate_child(Price(this_state().price()), Quantity(this_state().quantity()));
|
||||
|
||||
if(!me->hedge_sent)
|
||||
{
|
||||
double prx = this_state().price();
|
||||
if(definition().side() == api::SIDE_BUY)
|
||||
prx = prx + tick_size() * me->other_ticks;
|
||||
else
|
||||
prx = prx - tick_size() * me->other_ticks;
|
||||
build_and_send_hedge( Price(prx), Quantity(this_state().quantity()) );
|
||||
me->hedge_sent = true;
|
||||
}
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
report_state();
|
||||
}
|
||||
break;
|
||||
case ORDER_STATUS_WORKING:
|
||||
{
|
||||
}
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
break;
|
||||
|
||||
// child cannot be in any of these states if we are in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OCOOrder::on_cancel(trace::CorID const&)
|
||||
{
|
||||
LOG(OrderMan, Info, "Canceling OCOOrder Order {}", key().value());
|
||||
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (child_state().status())
|
||||
{
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
transition(ORDER_STATUS_CANCELED);
|
||||
break;
|
||||
case ORDER_STATUS_WORKING:
|
||||
if(!is_detached())
|
||||
{
|
||||
cancel_child();
|
||||
for(auto& i : hedges())
|
||||
i.second.cancel();
|
||||
}
|
||||
transition(ORDER_STATUS_CANCELED);
|
||||
break;
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
// child is running but it cannot be canceled at this point
|
||||
transition(this_state().status(), "Cannot cancel order");
|
||||
break;
|
||||
|
||||
// child cannot be in any of these if we are in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
transition(this_state().status(), "Cannot cancel order");
|
||||
break;
|
||||
|
||||
// these are unreacheable for this order type
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
report_state();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/orders/book_algos/BookAlgo.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class OrderStateUpdateEvent;
|
||||
class BookUpdateEvent;
|
||||
|
||||
//OCOOrder initializes the child order as normal
|
||||
//it also initializes a 'hedge' or 'other' at the same time, the child and the hedge are managed with OCO semantics:
|
||||
//when one fills the other's quantity is reduced (or cancelled on a full fill)
|
||||
|
||||
class OCOOrder : public BookAlgo
|
||||
{
|
||||
public:
|
||||
OCOOrder();
|
||||
virtual ~OCOOrder();
|
||||
|
||||
void on_cancel(trace::CorID const&) override ;
|
||||
protected:
|
||||
void setup_child(const api::orderman::OrderDefinition&, const PreActivationOrderServices&,
|
||||
api::orderman::OrderState&, api::orderman::OrderDefinition*) override;
|
||||
bool setup_hedge(const api::orderman::OrderDefinition& parent, const PreActivationOrderServices&,
|
||||
api::orderman::OrderDefinition*) override;
|
||||
void process_child_state_change(const api::orderman::OrderState&, const OrderStateUpdateEvent&) override;
|
||||
void process_hedge_state_change(const api::orderman::OrderState&, const OrderStateUpdateEvent&) override;
|
||||
void on_book_update(const bts::orderman::BookUpdateEvent&) override;
|
||||
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -10,65 +10,75 @@ namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
struct OffsetOrder::PImpl {
|
||||
struct OffsetOrder::PImpl
|
||||
{
|
||||
PImpl() {}
|
||||
|
||||
uint32_t tick_offset_on_deploy;
|
||||
|
||||
uint32_t tick_offset_on_deploy;
|
||||
};
|
||||
|
||||
|
||||
OffsetOrder::OffsetOrder() : me(new PImpl()) {}
|
||||
|
||||
OffsetOrder::~OffsetOrder() {}
|
||||
|
||||
void OffsetOrder::setup_child(const api::orderman::OrderDefinition &this_def,
|
||||
const PreActivationOrderServices &,
|
||||
api::orderman::OrderState &initial_state,
|
||||
api::orderman::OrderDefinition *out_child) {
|
||||
initial_state.mutable_tick();
|
||||
auto const &offset_def = this_def.custom_def().offset();
|
||||
void OffsetOrder::setup_child(const api::orderman::OrderDefinition& this_def, const PreActivationOrderServices&,
|
||||
api::orderman::OrderState& initial_state, api::orderman::OrderDefinition* out_child)
|
||||
{
|
||||
initial_state.mutable_offset();
|
||||
auto const &offset_def = this_def.custom_def().offset();
|
||||
*out_child->mutable_custom_def() = offset_def.child();
|
||||
|
||||
me->tick_offset_on_deploy = offset_def.tick_offset_on_deploy();
|
||||
|
||||
me->tick_offset_on_deploy = offset_def.tick_offset_on_deploy();
|
||||
}
|
||||
|
||||
void OffsetOrder::on_book_update(const bts::orderman::BookUpdateEvent &book) {
|
||||
switch (this_state().status()) {
|
||||
|
||||
void OffsetOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
|
||||
{
|
||||
switch (this_state().status())
|
||||
{
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (child_state().status()) {
|
||||
case ORDER_STATUS_INACTIVE: {
|
||||
if (definition().side() == api::SIDE_BUY) {
|
||||
const auto &same = book.book.side(api::Side::SIDE_BUY)[0];
|
||||
double price =
|
||||
same.price() - tick_size() * me->tick_offset_on_deploy;
|
||||
activate_child(Price(price), Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
} else {
|
||||
const auto &same = book.book.side(api::Side::SIDE_SELL)[0];
|
||||
double price =
|
||||
same.price() + tick_size() * me->tick_offset_on_deploy;
|
||||
activate_child(Price(price), Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
switch (child_state().status())
|
||||
{
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
{
|
||||
if(definition().side() == api::SIDE_BUY)
|
||||
{
|
||||
const auto& same = book.book.side(api::Side::SIDE_BUY)[0];
|
||||
double price = same.price() - tick_size() * me->tick_offset_on_deploy;
|
||||
activate_child(Price(price), Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& same = book.book.side(api::Side::SIDE_SELL)[0];
|
||||
double price = same.price() + tick_size() * me->tick_offset_on_deploy;
|
||||
activate_child(Price(price), Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
}
|
||||
report_state();
|
||||
}
|
||||
report_state();
|
||||
} break;
|
||||
case ORDER_STATUS_WORKING: {
|
||||
detach();
|
||||
} break;
|
||||
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
break;
|
||||
|
||||
// child cannot be in any of these states if we are in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
case ORDER_STATUS_WORKING:
|
||||
{
|
||||
detach();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
break;
|
||||
|
||||
// child cannot be in any of these states if we are in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
@@ -84,8 +94,9 @@ void OffsetOrder::on_book_update(const bts::orderman::BookUpdateEvent &book) {
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -0,0 +1,40 @@
|
||||
#include "PricerOrder.h"
|
||||
|
||||
#include "lib/orderman/actors/order_manager/OrderBuilder.h"
|
||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderUtils.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
#include <google/protobuf/timestamp.pb.h>
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
struct PricerOrder::PImpl
|
||||
{
|
||||
PImpl() {}
|
||||
|
||||
int32_t price_offset_ticks;
|
||||
double price_factor;
|
||||
};
|
||||
|
||||
|
||||
PricerOrder::PricerOrder() : me(new PImpl()) {}
|
||||
|
||||
PricerOrder::~PricerOrder() {}
|
||||
|
||||
void PricerOrder::setup_child(const api::orderman::OrderDefinition& this_def, const PreActivationOrderServices&,
|
||||
api::orderman::OrderState& initial_state, api::orderman::OrderDefinition* out_child)
|
||||
{
|
||||
initial_state.mutable_pricer();
|
||||
auto const &pricer_def = this_def.custom_def().pricer();
|
||||
*out_child->mutable_custom_def() = pricer_def.child();
|
||||
|
||||
me->price_offset_ticks = pricer_def.price_offset_ticks();
|
||||
me->price_factor = pricer_def.price_factor();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/orders/book_algos/BookAlgo.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class OrderStateUpdateEvent;
|
||||
class BookUpdateEvent;
|
||||
|
||||
//PricerOrder matches the bid (for buy) or offer (for sell) price of it's target security times a factor plus a constant
|
||||
|
||||
class PricerOrder : public BookAlgo
|
||||
{
|
||||
public:
|
||||
PricerOrder();
|
||||
virtual ~PricerOrder();
|
||||
|
||||
protected:
|
||||
void setup_child(const api::orderman::OrderDefinition& this_def, const PreActivationOrderServices&,
|
||||
api::orderman::OrderState&, api::orderman::OrderDefinition*) override;
|
||||
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -1,172 +0,0 @@
|
||||
#include "TickOrder.h"
|
||||
|
||||
#include "lib/orderman/actors/order_manager/OrderBuilder.h"
|
||||
#include "lib/orderman/orders/spreader_orders/spreader/SpreaderUtils.h"
|
||||
#include "lib/utils/PBUtils.h"
|
||||
#include <google/protobuf/timestamp.pb.h>
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
using namespace api::orderman;
|
||||
|
||||
struct TickOrder::PImpl {
|
||||
PImpl() {}
|
||||
|
||||
uint32_t tick_offset_on_deploy;
|
||||
spark::QuantityMeasure cross_threshold;
|
||||
uint32_t cross_ticks;
|
||||
uint32_t max_chase_ticks;
|
||||
bool detach_on_toward;
|
||||
|
||||
md::PriceSize opposite_at_inception;
|
||||
};
|
||||
|
||||
TickOrder::TickOrder() : me(new PImpl()) {}
|
||||
|
||||
TickOrder::~TickOrder() {}
|
||||
|
||||
void TickOrder::setup_child(const api::orderman::OrderDefinition &this_def,
|
||||
const PreActivationOrderServices &,
|
||||
api::orderman::OrderState &initial_state,
|
||||
api::orderman::OrderDefinition *out_child) {
|
||||
initial_state.mutable_tick();
|
||||
auto const &tick_def = this_def.custom_def().tick();
|
||||
*out_child->mutable_custom_def() = tick_def.child();
|
||||
|
||||
me->tick_offset_on_deploy = tick_def.tick_offset_on_deploy();
|
||||
me->cross_threshold = tick_def.cross_threshold();
|
||||
me->cross_ticks = tick_def.cross_ticks();
|
||||
me->max_chase_ticks = tick_def.max_chase_ticks();
|
||||
me->cross_threshold = tick_def.cross_threshold();
|
||||
me->detach_on_toward = tick_def.detach_on_toward();
|
||||
}
|
||||
|
||||
void TickOrder::payup(const md::PriceSize &opposite,
|
||||
const bts::orderman::BookUpdateEvent &,
|
||||
uint32_t cross_ticks) {
|
||||
double new_price = opposite.price() + tick_size() * cross_ticks;
|
||||
double limit =
|
||||
me->opposite_at_inception.price() + tick_size() * me->max_chase_ticks;
|
||||
if (new_price <= limit)
|
||||
update_child(Price(new_price), Quantity(this_state().quantity()));
|
||||
else {
|
||||
update_child(Price(limit), Quantity(this_state().quantity()));
|
||||
detach();
|
||||
}
|
||||
report_state();
|
||||
}
|
||||
|
||||
void TickOrder::paydown(const md::PriceSize &opposite,
|
||||
const bts::orderman::BookUpdateEvent &,
|
||||
uint32_t cross_ticks) {
|
||||
double new_price = opposite.price() - tick_size() * cross_ticks;
|
||||
double limit =
|
||||
me->opposite_at_inception.price() - tick_size() * me->max_chase_ticks;
|
||||
if (new_price >= limit)
|
||||
update_child(Price(new_price), Quantity(this_state().quantity()));
|
||||
else {
|
||||
update_child(Price(limit), Quantity(this_state().quantity()));
|
||||
detach();
|
||||
}
|
||||
report_state();
|
||||
}
|
||||
|
||||
void TickOrder::on_book_update(const bts::orderman::BookUpdateEvent &book) {
|
||||
switch (this_state().status()) {
|
||||
case ORDER_STATUS_WORKING:
|
||||
switch (child_state().status()) {
|
||||
case ORDER_STATUS_INACTIVE: {
|
||||
if (definition().side() == api::SIDE_BUY) {
|
||||
me->opposite_at_inception = book.book.side(api::Side::SIDE_SELL)[0];
|
||||
if (me->tick_offset_on_deploy > 0) {
|
||||
double price = me->opposite_at_inception.price() -
|
||||
tick_size() * me->tick_offset_on_deploy;
|
||||
activate_child(Price(price), Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
} else {
|
||||
activate_child(Price(this_state().price()),
|
||||
Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
}
|
||||
} else {
|
||||
me->opposite_at_inception = book.book.side(api::Side::SIDE_BUY)[0];
|
||||
if (me->tick_offset_on_deploy > 0) {
|
||||
double price = me->opposite_at_inception.price() +
|
||||
tick_size() * me->tick_offset_on_deploy;
|
||||
activate_child(Price(price), Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
} else {
|
||||
activate_child(Price(this_state().price()),
|
||||
Quantity(this_state().quantity()));
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
}
|
||||
}
|
||||
report_state();
|
||||
} break;
|
||||
case ORDER_STATUS_WORKING: {
|
||||
Quantity thresh = SpreaderUtils::_quantity_threshold(
|
||||
me->cross_threshold, Quantity(this_state().quantity()));
|
||||
if (definition().side() == api::SIDE_BUY) {
|
||||
const auto &opposite = book.book.side(api::Side::SIDE_SELL)[0];
|
||||
if (opposite.price() < me->opposite_at_inception.price()) {
|
||||
if (me->detach_on_toward)
|
||||
detach();
|
||||
else
|
||||
me->opposite_at_inception = opposite;
|
||||
} else if (opposite.price() > me->opposite_at_inception.price())
|
||||
payup(opposite, book, me->cross_ticks);
|
||||
else {
|
||||
if (opposite.size() <= thresh.value())
|
||||
payup(opposite, book, me->cross_ticks);
|
||||
}
|
||||
} else {
|
||||
const auto &opposite = book.book.side(api::Side::SIDE_BUY)[0];
|
||||
if (opposite.price() > me->opposite_at_inception.price()) {
|
||||
if (me->detach_on_toward)
|
||||
detach();
|
||||
else
|
||||
me->opposite_at_inception = opposite;
|
||||
} else if (opposite.price() < me->opposite_at_inception.price())
|
||||
paydown(opposite, book, me->cross_ticks);
|
||||
else {
|
||||
if (opposite.size() <= thresh.value())
|
||||
paydown(opposite, book, me->cross_ticks);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
break;
|
||||
|
||||
// child cannot be in any of these states if we are in the working state
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace orderman
|
||||
} // namespace bts
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "lib/orderman/orders/book_algos/BookAlgo.h"
|
||||
|
||||
namespace bts {
|
||||
namespace orderman {
|
||||
|
||||
class OrderStateUpdateEvent;
|
||||
class BookUpdateEvent;
|
||||
|
||||
//TickOrder deploys N ticks away from the initial opposite inside market and watches for it to trade below a certain size.
|
||||
//If that size goes below a threshold or the market moves away, TickOrder Pays up once.
|
||||
//The process repeats until the algo has paid up a max of N ticks from the original opposite inside order.
|
||||
//If the market moves toward, the algo either starts watching the new inside market and keeps going or detaches depending on a parameter
|
||||
|
||||
class TickOrder : public BookAlgo
|
||||
{
|
||||
public:
|
||||
TickOrder();
|
||||
virtual ~TickOrder();
|
||||
|
||||
protected:
|
||||
void setup_child(const api::orderman::OrderDefinition& this_def, const PreActivationOrderServices&,
|
||||
api::orderman::OrderState&, api::orderman::OrderDefinition*) override;
|
||||
void on_book_update(const bts::orderman::BookUpdateEvent&) override;
|
||||
private:
|
||||
void payup(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks) override;
|
||||
void paydown(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks) override;
|
||||
|
||||
private:
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
};
|
||||
|
||||
}}
|
||||
@@ -32,6 +32,8 @@ void init_plugins(SparkServices &services) {
|
||||
auto &f = *iter;
|
||||
|
||||
auto pl = f.path().string();
|
||||
if(pl.find("tensorflow.so") != std::string::npos)
|
||||
continue;
|
||||
LOG(Plugin, Info, "Attempting to initialize plugin {}", pl);
|
||||
try {
|
||||
auto init_plugin = boost::dll::import<void(SparkServices &)>(
|
||||
|
||||
@@ -12,6 +12,10 @@ add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/sdk
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/examples/build_examples.sh
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/examples/md_publisher_example.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/examples/order_plugin_example.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/examples/ai_order_plugin_example.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/examples/tf_test.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tensorflow/tfapi.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tensorflow/tfapi.h
|
||||
server_layout)
|
||||
|
||||
add_custom_target(sdk_dir ALL DEPENDS ${CMAKE_BINARY_DIR}/sdk)
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
#include "../tensorflow/tfapi.h"
|
||||
|
||||
#include "spark/lib/logging/logging.h"
|
||||
#include "spark/lib/orderman/orders/DynamicOrder.h"
|
||||
#include "spark/lib/plugin/SparkServices.h"
|
||||
#include "spark/lib/orderman/actors/order_manager/ChildOrder.h"
|
||||
#include "spark/lib/orderman/actors/order_manager/OrderBuilder.h"
|
||||
#include "spark/lib/orderman/orders/DynamicOrder.h"
|
||||
#include "spark/lib/utils/PBUtils.h"
|
||||
#include "lib/config/protos/system.pb.h"
|
||||
#include "lib/config/config.h"
|
||||
|
||||
using namespace bts::api::orderman;
|
||||
using namespace bts::orderman;
|
||||
using std::vector;
|
||||
|
||||
namespace bts {
|
||||
namespace order_example {
|
||||
|
||||
class AISampleOrder : public DynamicOrder {
|
||||
public:
|
||||
AISampleOrder();
|
||||
~AISampleOrder();
|
||||
OrderDefinition const &definition() const override;
|
||||
void on_init_new(OrderDefinition const &,
|
||||
const PreActivationOrderServices &) override;
|
||||
void on_init_recovered(OrderRecord const &,
|
||||
const PreActivationOrderServices &) override;
|
||||
void on_activate(Price, Quantity, OrderServices &,
|
||||
trace::CorID const&) override;
|
||||
void on_update(Price, Quantity, trace::CorID const&) override;
|
||||
void on_crack(trace::CorID const &) override;
|
||||
void on_cancel(trace::CorID const &) override;
|
||||
|
||||
private:
|
||||
void report_state();
|
||||
void send_next_child_order();
|
||||
|
||||
void merge_states(OrderState const &iceberg_state,
|
||||
OrderState const &child_state, OrderState *merged);
|
||||
|
||||
void on_child_order_update(OrderStateUpdateEvent const &);
|
||||
void transition(OrderStatus new_state, std::string const &msg);
|
||||
void transition(OrderStatus new_state);
|
||||
|
||||
struct ActiveChild;
|
||||
struct PImpl;
|
||||
std::unique_ptr<PImpl> me;
|
||||
};
|
||||
|
||||
struct AISampleOrder::ActiveChild {
|
||||
ActiveChild() {}
|
||||
ChildOrder order;
|
||||
api::orderman::OrderState state;
|
||||
void clear() { state = api::orderman::OrderState(); }
|
||||
};
|
||||
|
||||
struct AISampleOrder::PImpl {
|
||||
PImpl() : services(nullptr), child() {}
|
||||
|
||||
OrderServices *services;
|
||||
api::orderman::OrderDefinition def;
|
||||
api::orderman::OrderState state;
|
||||
OrderBuilder child_builder;
|
||||
ActiveChild child;
|
||||
Quantity show_quantity;
|
||||
};
|
||||
|
||||
AISampleOrder::AISampleOrder() : me(new PImpl()) {}
|
||||
AISampleOrder::~AISampleOrder() {}
|
||||
api::orderman::OrderDefinition const &AISampleOrder::definition() const {
|
||||
return me->def;
|
||||
}
|
||||
|
||||
void AISampleOrder::on_init_new(
|
||||
api::orderman::OrderDefinition const &def,
|
||||
const PreActivationOrderServices &services) {
|
||||
|
||||
me->def = def;
|
||||
me->state.mutable_dynamic();
|
||||
|
||||
auto const &iceberg_def = def.custom_def().dynamic();
|
||||
me->show_quantity =
|
||||
Quantity(iceberg_def.order_params().at("show_size").as_uint32());
|
||||
|
||||
auto child_def = def;
|
||||
*child_def.mutable_custom_def() =
|
||||
iceberg_def.order_params().at("child").as_order_def();
|
||||
if (me->show_quantity.value() != 0) {
|
||||
me->child_builder = OrderBuilder(
|
||||
key(), child_def, services,
|
||||
std::max((size_t)1, (size_t)(me->show_quantity).value() / 10));
|
||||
transition(ORDER_STATUS_INACTIVE);
|
||||
} else {
|
||||
auto msg = fmt::format("Show quantity must be greater than 0");
|
||||
me->state.set_last_msg(msg);
|
||||
transition(ORDER_STATUS_REJECTED_BY_SPARK, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void AISampleOrder::on_init_recovered(
|
||||
api::orderman::OrderRecord const &rec, const PreActivationOrderServices &) {
|
||||
auto const &def = rec.def();
|
||||
me->def = def;
|
||||
me->state = rec.state();
|
||||
|
||||
switch (me->state.status()) {
|
||||
|
||||
case ORDER_STATUS_WORKING:
|
||||
case ORDER_STATUS_DISCONNECTED: {
|
||||
auto msg = "System restarted with active iceberg order";
|
||||
me->state.set_last_msg(msg);
|
||||
transition(ORDER_STATUS_ERROR, msg);
|
||||
break;
|
||||
}
|
||||
// terminal states
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AISampleOrder::on_activate(Price p, Quantity q,
|
||||
OrderServices &services,
|
||||
trace::CorID const &) {
|
||||
bts_assert(!me->services);
|
||||
me->services = &services;
|
||||
me->child_builder.activate(services);
|
||||
|
||||
switch (me->state.status()) {
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
me->state.set_price(p.value());
|
||||
me->state.set_quantity(q.value());
|
||||
services.subscribe_to_child_updates(
|
||||
[this](auto const &os) { this->on_child_order_update(os); });
|
||||
transition(ORDER_STATUS_WORKING);
|
||||
send_next_child_order();
|
||||
break;
|
||||
|
||||
// these are not possible since the on_init_recovered code
|
||||
// would have transitioned us to error already
|
||||
case ORDER_STATUS_WORKING:
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_DISCONNECTED: {
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
// terminal states
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
break;
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
report_state();
|
||||
}
|
||||
|
||||
void AISampleOrder::on_update(Price p, Quantity q, trace::CorID const &) {
|
||||
switch (me->state.status()) {
|
||||
case ORDER_STATUS_WORKING:
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
LOG(Plugin, Info,
|
||||
"Updating DynamicIceberg order {} to price {} quantity {}",
|
||||
key().value(), p.value(), q.value());
|
||||
me->state.set_price(p.value());
|
||||
me->state.set_quantity(q.value());
|
||||
break;
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
transition(me->state.status(), "Cannot update order");
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
report_state();
|
||||
}
|
||||
|
||||
void AISampleOrder::on_crack(trace::CorID const &) {}
|
||||
|
||||
void AISampleOrder::on_cancel(trace::CorID const &) {
|
||||
switch (me->state.status()) {
|
||||
case ORDER_STATUS_WORKING:
|
||||
LOG(Plugin, Info, "Canceling DynamicIceberg Order {}", key().value());
|
||||
me->child.order.cancel();
|
||||
transition(ORDER_STATUS_CANCELED);
|
||||
break;
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
transition(me->state.status(), "Cannot cancel order");
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
report_state();
|
||||
}
|
||||
|
||||
void AISampleOrder::report_state() {
|
||||
if (me->child.state.filled_quantity()) {
|
||||
api::orderman::OrderState merged_state;
|
||||
merge_states(me->state, me->child.state, &merged_state);
|
||||
me->services->report_state(merged_state);
|
||||
} else
|
||||
me->services->report_state(me->state);
|
||||
}
|
||||
|
||||
void AISampleOrder::merge_states(
|
||||
api::orderman::OrderState const &iceberg_state,
|
||||
api::orderman::OrderState const &child_state,
|
||||
api::orderman::OrderState *merged) {
|
||||
auto child_order_fills = child_state.filled_quantity();
|
||||
auto child_order_avg_price = child_state.avg_price();
|
||||
auto child_order_last_price = child_state.last_price();
|
||||
|
||||
auto iceberg_fills = iceberg_state.filled_quantity();
|
||||
auto iceberg_avg_price = iceberg_state.avg_price();
|
||||
|
||||
*merged = iceberg_state;
|
||||
merged->set_filled_quantity(child_order_fills + iceberg_fills);
|
||||
merged->set_last_price(child_order_last_price);
|
||||
merged->set_avg_price((child_order_fills * child_order_avg_price +
|
||||
iceberg_fills * iceberg_avg_price) /
|
||||
(child_order_fills + iceberg_fills));
|
||||
}
|
||||
|
||||
void AISampleOrder::send_next_child_order() {
|
||||
bts_assert(me->state.quantity() > me->state.filled_quantity());
|
||||
|
||||
auto remaining = me->state.quantity() - me->state.filled_quantity();
|
||||
auto to_send = std::min(remaining, me->show_quantity.value());
|
||||
me->child.order = me->child_builder.build();
|
||||
LOG(Plugin, Info,
|
||||
"DynamicIceberg order {} creating new child order {} with size "
|
||||
"{} price {}. Filled {} so far out of {}",
|
||||
key().value(), me->child.order.key().value(), to_send, me->state.price(),
|
||||
me->state.filled_quantity(), me->state.quantity());
|
||||
|
||||
me->child.order.activate(Price(me->state.price()), Quantity(to_send));
|
||||
}
|
||||
|
||||
void AISampleOrder::on_child_order_update(
|
||||
OrderStateUpdateEvent const &ev) {
|
||||
switch (me->state.status()) {
|
||||
case ORDER_STATUS_WORKING:
|
||||
if (ev.key == me->child.order.key()) {
|
||||
me->child.state = ev.rebuild_state();
|
||||
|
||||
switch (me->child.state.status()) {
|
||||
|
||||
case ORDER_STATUS_WORKING:
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
// nothing to do but report new state
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_COMPLETED: {
|
||||
api::orderman::OrderState merged_state;
|
||||
merge_states(me->state, me->child.state, &merged_state);
|
||||
me->state = merged_state;
|
||||
me->child.clear();
|
||||
if (me->state.quantity() > me->state.filled_quantity())
|
||||
send_next_child_order();
|
||||
else
|
||||
transition(ORDER_STATUS_COMPLETED);
|
||||
break;
|
||||
}
|
||||
|
||||
case ORDER_STATUS_CANCELED:
|
||||
LOG(Plugin, Info,
|
||||
"Unexpected cancel of child {} in DynamicIceberg Order {}. "
|
||||
"Canceling parent",
|
||||
ev.key.value(), key().value());
|
||||
transition(ORDER_STATUS_CANCELED);
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_ERROR:
|
||||
me->child.clear();
|
||||
transition(ORDER_STATUS_ERROR, "Unexpected child order state");
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG(Plugin, Info,
|
||||
"DynamicIceberg order {} received update for non active child "
|
||||
"order{} . update state = {} ",
|
||||
key().value(), me->child.order.key().value(),
|
||||
utils::pb::to_string(ev.rebuild_state()));
|
||||
}
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_CANCELED:
|
||||
case ORDER_STATUS_ERROR:
|
||||
case ORDER_STATUS_DISCONNECTED:
|
||||
case ORDER_STATUS_COMPLETED:
|
||||
break;
|
||||
|
||||
case ORDER_STATUS_PENDING_WORKING:
|
||||
case ORDER_STATUS_REJECTED_BY_SPARK:
|
||||
case ORDER_STATUS_INACTIVE:
|
||||
case OrderStatus_INT_MIN_SENTINEL_DO_NOT_USE_:
|
||||
case OrderStatus_INT_MAX_SENTINEL_DO_NOT_USE_:
|
||||
bts_assert(false);
|
||||
break;
|
||||
}
|
||||
report_state();
|
||||
}
|
||||
|
||||
void AISampleOrder::transition(api::orderman::OrderStatus new_status,
|
||||
std::string const &msg) {
|
||||
auto const &from = OrderStatus_Name(me->state.status());
|
||||
auto const &to = OrderStatus_Name(new_status);
|
||||
LOG(Plugin, Info,
|
||||
"Transitioning dynamic iceberg order {} from {} to {}. Msg: {}",
|
||||
key().value(), from, to, msg);
|
||||
me->state.set_last_msg(msg);
|
||||
me->state.set_status(new_status);
|
||||
}
|
||||
|
||||
void AISampleOrder::transition(api::orderman::OrderStatus new_status) {
|
||||
auto const &from = OrderStatus_Name(me->state.status());
|
||||
auto const &to = OrderStatus_Name(new_status);
|
||||
LOG(OrderMan, Info, "Transitioning dynamic iceberg order {} from {} to {}",
|
||||
key().value(), from, to);
|
||||
me->state.set_status(new_status);
|
||||
}
|
||||
|
||||
|
||||
} // namespace order_example
|
||||
} // namespace bts
|
||||
|
||||
DynamicOrderDescriptor get_order_desc()
|
||||
{
|
||||
DynamicOrderDescriptor desc;
|
||||
|
||||
// order type name
|
||||
desc.set_dynamic_order_type("AISampleOrder");
|
||||
|
||||
// show size
|
||||
auto param = desc.add_param_desc();
|
||||
param->set_param_name("show_size");
|
||||
param->mutable_param_type()->set_primitive(DYNAMIC_ORDER_PRIMITIVE_UINT);
|
||||
|
||||
// child order
|
||||
param = desc.add_param_desc();
|
||||
param->set_param_name("child");
|
||||
param->mutable_param_type()->set_primitive(DYNAMIC_ORDER_PRIMITIVE_ORDER_DEF);
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
extern "C" void init_spark_plugin(bts::SparkServices &serv) {
|
||||
using namespace bts;
|
||||
|
||||
if (config::get<config::DeploymentType>().type() == "dev") {
|
||||
serv.register_dynamic_order(get_order_desc(),
|
||||
[]() { return std::make_unique<bts::order_example::AISampleOrder>(); });
|
||||
LOG(Plugin,Info, "Initialized ai_order_plugin_example.so");
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ g++ -isystem ../externals/include \
|
||||
-l spark \
|
||||
-llttng-ust \
|
||||
-ldl
|
||||
|
||||
|
||||
g++ -isystem ../externals/include \
|
||||
-I ../include \
|
||||
-I ../include/spark \
|
||||
@@ -22,5 +22,46 @@ g++ -isystem ../externals/include \
|
||||
-o order_plugin_example.so \
|
||||
order_plugin_example.cpp \
|
||||
-Wl,-rpath,.. \
|
||||
-L ../lib \
|
||||
-L ../lib \
|
||||
-l spark
|
||||
|
||||
|
||||
g++ -isystem ../externals/include \
|
||||
-I ../include \
|
||||
-I ../include/spark \
|
||||
-I ../externals/include \
|
||||
-std=c++1z \
|
||||
-fPIC \
|
||||
-g \
|
||||
-shared \
|
||||
-o ai_order_plugin_example.so \
|
||||
ai_order_plugin_example.cpp \
|
||||
../tensorflow/tfapi.cpp \
|
||||
-Wl,-rpath,. \
|
||||
-Wl,-rpath,.. \
|
||||
-Wl,-rpath,../lib/ \
|
||||
-Wl,-rpath,./plugins \
|
||||
-L ../lib \
|
||||
-l spark \
|
||||
-L ../externals/lib \
|
||||
-l tensorflow
|
||||
|
||||
g++ -isystem ../externals/include \
|
||||
-I ../include \
|
||||
-I ../include/spark \
|
||||
-I ../externals/include \
|
||||
-I ../externals/include/tensorflow/contrib/makefile/gen/proto \
|
||||
-std=c++1z \
|
||||
-o tf_test \
|
||||
tf_test.cpp \
|
||||
../tensorflow/tfapi.cpp \
|
||||
-Wl,-rpath,. \
|
||||
-Wl,-rpath,../lib \
|
||||
-Wl,-rpath,../externals/lib \
|
||||
-L ../lib \
|
||||
-l spark \
|
||||
-L ../externals/lib \
|
||||
-l tensorflow \
|
||||
-lpthread \
|
||||
-llttng-ust \
|
||||
-ldl
|
||||
@@ -72,6 +72,7 @@ api::orderman::OrderDefinition const &DynamicIcebergOrder::definition() const {
|
||||
void DynamicIcebergOrder::on_init_new(
|
||||
api::orderman::OrderDefinition const &def,
|
||||
const PreActivationOrderServices &services) {
|
||||
|
||||
me->def = def;
|
||||
me->state.mutable_dynamic();
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "../tensorflow/tfapi.h"
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
using namespace tensorflow;
|
||||
using namespace tensorflow::c;
|
||||
|
||||
int main()
|
||||
{
|
||||
// int argc = 0;
|
||||
// tensorflow::port::InitMain("", &argc, nullptr);
|
||||
// const char* ver = TF_Version();
|
||||
// cout << ver;
|
||||
|
||||
std::cout << "pre";
|
||||
TF_Session* session = nullptr;
|
||||
TFStatus status = bts::ml::create_tf_session(session);
|
||||
if (!status.ok()) {
|
||||
cout << status.code << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
cout << "loading saved model" << "\n";
|
||||
TFStatus status2 = bts::ml::load_tf_model("/home/bts/rnn_saved_model/", session);
|
||||
cout << "loaded saved model" << "\n";
|
||||
if (!status2.ok()) {
|
||||
cout << status2.code << "\n" << status2.error;
|
||||
return 1;
|
||||
}
|
||||
cout << "Session successfully created.\n";
|
||||
}
|
||||
+4
-1
@@ -26,13 +26,16 @@ ln -sf $1/server $1/sdk/lib
|
||||
mkdir $1/sdk/examples
|
||||
cp $2/examples/* $1/sdk/examples
|
||||
cp $2/doc/* $1/sdk/doc
|
||||
mkdir $1/sdk/tensorflow
|
||||
cp $2/tensorflow/* $1/sdk/tensorflow
|
||||
|
||||
cp $2/sdk_shell.sh $1/sdk/sdk_shell.sh
|
||||
cp $2/update_github.sh $1/sdk/update_github.sh
|
||||
cp $2/README.md $1/sdk/README.md
|
||||
|
||||
# ln -sf $1/sdk/lib/defaults $1/sdk/examples/defaults
|
||||
chmod +x $1/sdk/examples/build_examples.sh
|
||||
chmod +x $1/sdk/sdk_shell.sh
|
||||
chmod +x $1/sdk/update_github.sh
|
||||
(cd $1/sdk/examples && ./build_examples.sh && ./md_publisher_example >/dev/null)
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "tfapi.h"
|
||||
#include "lib/utils/helper_macros.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
//no c++ api yet
|
||||
//https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/label_image/main.cc
|
||||
|
||||
|
||||
namespace tensorflow
|
||||
{
|
||||
namespace c
|
||||
{
|
||||
TFStatus::TFStatus(TF_Status& stat)
|
||||
{
|
||||
std::string msg(TF_Message(&stat));
|
||||
this->error = msg;
|
||||
this->code = TF_GetCode(&stat);
|
||||
}
|
||||
|
||||
bool TFStatus::ok() const
|
||||
{
|
||||
return (int)code == 0;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
using namespace tensorflow::c;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace bts
|
||||
{
|
||||
namespace ml
|
||||
{
|
||||
|
||||
const std::string input_default_tag = "input";
|
||||
const std::string output_default_tag = "output";
|
||||
const std::string serving_default_tag = "serve";
|
||||
|
||||
|
||||
tensorflow::c::TFStatus create_tf_session(TF_Session*& session)
|
||||
{
|
||||
TF_Graph* graph = TF_NewGraph();
|
||||
TF_SessionOptions* options = TF_NewSessionOptions();
|
||||
TF_Status* status = TF_NewStatus();
|
||||
session = TF_NewSession(graph, options, status);
|
||||
TFStatus stat(*status);
|
||||
TF_DeleteStatus(status);
|
||||
return stat;
|
||||
}
|
||||
|
||||
tensorflow::c::TFStatus load_tf_model(const std::string& export_dir, TF_Session*& session)
|
||||
{
|
||||
std::unordered_set<std::string> tags({serving_default_tag});
|
||||
return load_tf_model(export_dir, tags, session);
|
||||
}
|
||||
|
||||
|
||||
tensorflow::c::TFStatus load_tf_model(const std::string& export_dir, const std::unordered_set<std::string>& tags,
|
||||
TF_Session*& session)
|
||||
{
|
||||
vector<char*> ctags;
|
||||
for(auto& t : tags)
|
||||
ctags.push_back(const_cast<char*>(t.c_str()));
|
||||
|
||||
TF_SessionOptions* session_options = TF_NewSessionOptions();
|
||||
TF_Buffer* run_options = nullptr;
|
||||
TF_Buffer* meta_graph_def = TF_NewBuffer(); //TODO get the protos here
|
||||
TF_Graph* graph = TF_NewGraph();
|
||||
TF_Status* status = TF_NewStatus();
|
||||
session = TF_LoadSessionFromSavedModel(session_options, run_options, export_dir.c_str(), &ctags[0], ctags.size(),
|
||||
graph, meta_graph_def, status);
|
||||
TFStatus stat(*status);
|
||||
|
||||
TF_DeleteSessionOptions(session_options);
|
||||
TF_DeleteBuffer(run_options);
|
||||
TF_DeleteBuffer(meta_graph_def);
|
||||
TF_DeleteStatus(status);
|
||||
return stat;
|
||||
}
|
||||
|
||||
// tensorflow::c::TFStatus execute(TF_Session& session,
|
||||
// const vector<std::pair<std::string, TF_Tensor> >& inputs,
|
||||
// const vector<std::string>& output_tensor_names,
|
||||
// const vector<std::string>& target_node_names,
|
||||
// vector<tensorflow::Tensor>* outputs)
|
||||
// {
|
||||
// TF_Buffer* run_options = nullptr;
|
||||
// TF_SessionRun(&session, run_options,
|
||||
// session.
|
||||
|
||||
// tensorflow::RunMetadata* run_metadata = nullptr;
|
||||
// tensorflow::RunOptions run_options;
|
||||
// Status status = bundle.session->Run(run_options, inputs, output_tensor_names, target_node_names, outputs, run_metadata);
|
||||
// return status;
|
||||
// }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// tensorflow::Status load_tf_model(const std::string& export_dir, const std::unordered_set<string>& tags, SavedModelBundle* const bundle)
|
||||
// {
|
||||
// tensorflow::SessionOptions session_options; //defaults
|
||||
// tensorflow::RunOptions run_options;
|
||||
// UNUSED(export_dir);
|
||||
// UNUSED(tags);
|
||||
// UNUSED(bundle);
|
||||
|
||||
// Status status = LoadSavedModel(session_options, run_options, export_dir, tags, bundle);
|
||||
// return status;
|
||||
|
||||
// //return tensorflow::Status();
|
||||
// }
|
||||
|
||||
// tensorflow::Status load_tf_model(const string& export_dir, const std::unordered_set<string>& tags, std::unique_ptr<SavedModelBundle>* bundle)
|
||||
// {
|
||||
// SessionBundleConfig config;
|
||||
// for(auto& i : tags)
|
||||
// config.add_saved_model_tags(i);
|
||||
// std::unique_ptr<SavedModelBundleFactory> factory;
|
||||
// Status stat = SavedModelBundleFactory::Create(config, &factory);
|
||||
// if(stat.ok())
|
||||
// {
|
||||
// stat = factory->CreateSavedModelBundle(export_dir, bundle);
|
||||
// }
|
||||
// return stat;
|
||||
// }
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace tensorflow
|
||||
{
|
||||
namespace c
|
||||
{
|
||||
#include "tensorflow/c/c_api.h"
|
||||
#undef LOG
|
||||
|
||||
struct TFStatus
|
||||
{
|
||||
TFStatus(TF_Status&);
|
||||
bool ok() const;
|
||||
|
||||
std::string error;
|
||||
TF_Code code;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
namespace bts
|
||||
{
|
||||
namespace ml
|
||||
{
|
||||
extern const std::string input_default_tag;
|
||||
extern const std::string output_default_tag;
|
||||
extern const std::string serving_default_tag;
|
||||
|
||||
tensorflow::c::TFStatus create_tf_session(tensorflow::c::TF_Session*& session);
|
||||
|
||||
tensorflow::c::TFStatus load_tf_model(const std::string& export_dir, tensorflow::c::TF_Session*& session);
|
||||
tensorflow::c::TFStatus load_tf_model(const std::string& export_dir, const std::unordered_set<std::string>& tags,
|
||||
tensorflow::c::TF_Session*& session);
|
||||
|
||||
|
||||
// tensorflow::c::TFStatus execute(const tensorflow::c::TF_Session& session,
|
||||
// const std::vector<std::pair<std::string, tensorflow::c::TF_Tensor> >& inputs,
|
||||
// const std::vector<std::string>& output_tensor_names,
|
||||
// const std::vector<std::string>& target_node_names,
|
||||
// std::vector<tensorflow::Tensor>* outputs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
- Set
|
||||
ExchangeSim {value {merge_with_md:false}}
|
||||
|
||||
in your spark.conf
|
||||
|
||||
- Use the order ticket to put in a 10 lot 55 dollar bid
|
||||
- Open up a ladder for SIM:CLZ9 and put in 10 lot offers at 55.10, 55.11, 55.12 and 1 lot bids at 54.99 and 54.98
|
||||
- Select OCO order from the menu.
|
||||
|
||||
-Set Stop Side to Same, Stop Type and Child type to Limit
|
||||
-Set Stop Ticks to -1
|
||||
-Put in a 1 lot bid at 54.93, you should see another 1 lot bid go in one tick worse
|
||||
-Move these orders independently (but don't get filled)
|
||||
-Cancel one order, the other should cancel
|
||||
-Check that an order goes in 1 tick better than where you click if you set the Stop Ticks to 1
|
||||
|
||||
|
||||
-Now set Stop Side to Opposite and Stop ticks to 3, send a 5 lot bid at 55.02
|
||||
-You should see a 5 lot buy go in at 55.02 and a 5 lot sell at 55.05.
|
||||
-Move the bid up to 55.03, the offer should not move
|
||||
-Move the offer up to 55.06, the bid should stay put
|
||||
- Cancel either the bid or the offer, the other will cancel. Set it up again and cancel the other side.
|
||||
|
||||
-Keep Stop Side at Opposite and Stop ticks to 3, send a 5 lot bid at 55.03
|
||||
-Switch to normal limit orders, send a 1 lot buy at 55.06. You should see a fill at 06 and the 5 lot bid at 03 should reduce to 4
|
||||
-Still with limit orders, send a 2 lot sell at 55.03. You should see a fill at 04 and the 4 lot offer at 06 should reduce to 2
|
||||
- (you might see the sell order have 1/2 in the badge. This means 1 fill / 2 total quantity, however I think this is a bug because we are working 2 still and that is correct)
|
||||
-Finally send a 2 lot buy (limit) at 55.06, you should see both the sell side OCO fill and the buy side OCO cancel
|
||||
-Flip this section around buy vs sell and make sure it does the same thing
|
||||
|
||||
Now compose a bracket order (extra credit if you make a template for it in the new guis)
|
||||
Select Cover
|
||||
Set Profit ticks to 1,
|
||||
Profit Order = OCO
|
||||
Child=Limit
|
||||
|
||||
For the OCO
|
||||
Stop Ticks = 3
|
||||
Stop Side = Same
|
||||
Stop Order = Trigger
|
||||
Child = Limit
|
||||
|
||||
Send in a buy of this order at 55.05
|
||||
Fill a 1 lot of this order at 55.05 (by putting in a Limit 55.05 sell)
|
||||
You should see a 1 lot sell order go in at 55.06 and a 1 lot sell trigger at 55.03
|
||||
Cancel one of those orders and the other should go away
|
||||
+3
-1
@@ -1 +1,3 @@
|
||||
@"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\Tools\VsDevCmd.bat"
|
||||
rem @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\Tools\VsDevCmd.bat"
|
||||
|
||||
@"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Auxiliary\Build\vcvars64.bat"
|
||||
Reference in new issue
Block a user