Compare commits

...
9 Commits
20 changed files with 256 additions and 64 deletions

No files matched your search

@@ -25,14 +25,14 @@ namespace mbts.spark
cross_threshold = new InlineUserProperty<bts.spark.QuantityMeasure>(
new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1}, false);
max_chase_ticks = new InlineUserProperty<uint>(2, false);
detach_on_toward = new InlineUserProperty<bool>(true, false);
trade_toward_behavior = new InlineUserProperty<LeanOrderDefinition.Types.OnToward>(LeanOrderDefinition.Types.OnToward.Cancel, false);
}
public readonly InlineUserProperty<CustomOneofCase> selected_child_order_type;
public readonly InlineUserProperty<IReadOnlyCollection<CustomOneofCase>> child_order_types;
public readonly InlineUserProperty<bts.spark.QuantityMeasure> cross_threshold;
public readonly InlineUserProperty<uint> max_chase_ticks;
public readonly InlineUserProperty<bool> detach_on_toward;
public readonly InlineUserProperty<LeanOrderDefinition.Types.OnToward> trade_toward_behavior;
}
class LeanOrderVM : OrderTypeVMBase<LeanOrderDefinition>, IHierarchicalOrderTypeVM, IDisposable
@@ -47,7 +47,7 @@ namespace mbts.spark
public bts.spark.QuantityMeasure cross_threshold { get; set; } = new bts.spark.QuantityMeasure() { Ratio = 1.0, Absolute = 1 };
public uint max_chase_ticks { get; set; } = 2;
public bool detach_on_toward { get; set; } = true;
public LeanOrderDefinition.Types.OnToward trade_toward_behavior { get; set; } = LeanOrderDefinition.Types.OnToward.Cancel;
public LeanOrderVM(OrdersModel model, IObservable<SecurityMD> security_md_source)
: this(model, security_md_source, security_md_source.Select(smd =>
@@ -80,10 +80,10 @@ namespace mbts.spark
max_chase_ticks = p.max_chase_ticks.value;
RaisePropertyChanged(nameof(max_chase_ticks));
}
if (p.detach_on_toward.force_override)
if (p.trade_toward_behavior.force_override)
{
detach_on_toward = p.detach_on_toward.value;
RaisePropertyChanged(nameof(detach_on_toward));
trade_toward_behavior = p.trade_toward_behavior.value;
RaisePropertyChanged(nameof(trade_toward_behavior));
}
_inline_props = p;
_validate();
@@ -102,11 +102,13 @@ namespace mbts.spark
var i = factory.lean_order();
i.CrossThreshold = cross_threshold;
i.MaxChaseTicks = max_chase_ticks;
i.DetachOnToward = detach_on_toward;
i.TradeTowardBehavior = trade_toward_behavior;
child_order.assign_to(i.Child);
value.Lean = i;
}
}
}
public IEnumerable<LeanOrderDefinition.Types.OnToward> trade_toward_types => EnumHelper.get_values_except<LeanOrderDefinition.Types.OnToward>();
public ICollection<IOrderTypeVM> child_order_types
{
@@ -235,7 +235,8 @@
<uag:QuantityMeasureControl Grid.Row="1" Grid.Column="2" QuantityMeasure="{Binding cross_threshold}"/>
<TextBlock Grid.Row="3" VerticalAlignment="Center">Max Chase Ticks</TextBlock>
<c:TickUpDownUInt Grid.Row="3" Grid.Column="2" Value="{Binding max_chase_ticks}"/>
<CheckBox Grid.Row="5" Grid.Column="2" VerticalAlignment="Center" Margin="0,0,0,0" IsChecked="{Binding detach_on_toward}">Detach on Toward</CheckBox>
<TextBlock Grid.Row="5">On Toward</TextBlock>
<ComboBox Grid.Row="5" Grid.Column="2" ItemsSource="{Binding trade_toward_types}" ItemTemplate="{StaticResource EnumDescriptionTemplate}" SelectedItem="{Binding trade_toward_behavior}"/>
<TextBlock Grid.Row="7">Child</TextBlock>
<uag:OrderDetailsPopupControl
Grid.Row="7" Grid.Column="2"
@@ -0,0 +1,37 @@
using bts.api.core;
using bts.api.persistence;
using bts.api.user;
using bts.test;
using mbts.persist;
using mbts.ui.shell;
using System;
using System.Linq;
namespace bts.settings {
public class SettingsManagerTool {
public static void run() {
var sc = new ServiceContext();
var users = sc.locate<UserService>();
var persist = sc.locate<PersistenceService>("settings");
var user_list = users.get_users(new GetUsersRequest());
var user_names = user_list.Users.Select(u => u.Login);
var from = ConsoleEx.prompt("From User", user_names);
var from_persist = new UserUISettings(user_list.Users.First(u => u.Login == from).Id, persist, null);
var workspaces = from_persist.query<WorkspaceDefinition>(WorkspacesModel.WORKSPACE_NAMESPACE, ".*").Result;
var selected_ws = ConsoleEx.prompt("Choose workspace:", workspaces.Select(w => w.key));
var to = ConsoleEx.prompt("To User", user_names);
var name = ConsoleEx.input_prompt("Rename workspace?", selected_ws);
var confirm = ConsoleEx.prompt($"copy workspace '{selected_ws}' from {from} to {to} and name it '{name}'. Confirm?", "Yes", "No");
if (confirm == "Yes") {
var ws_blob = workspaces.First(w => w.key == selected_ws).value;
var to_persist = new UserUISettings(user_list.Users.First(u => u.Login == to).Id, persist, null);
to_persist.set(WorkspacesModel.WORKSPACE_NAMESPACE, name, ws_blob).Wait();
Console.WriteLine("Done");
}
}
}
}
+28 -9
View File
@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace bts.test {
public static class ConsoleEx {
@@ -21,17 +23,34 @@ namespace bts.test {
}
public static T prompt<T>(string prompt, params T[] options) {
Console.WriteLine(prompt);
for (int x = 1; x <= options.Length; ++x) {
return ConsoleEx.prompt(prompt, (IEnumerable<T>)options);
}
public static T prompt<T>(string prompt, IEnumerable<T> options) {
WriteLine(prompt, ConsoleColor.Yellow);
for (int x = 0; x < options.Count(); ++x) {
Write($"{x}. ", ConsoleColor.Yellow);
WriteLine(options[x].ToString());
WriteLine(options.ElementAt(x).ToString());
}
int response;
do {
Int32.TryParse(Console.ReadKey().ToString(), out response);
if (response > options.Length) response = 0;
} while (response == 0);
return options[response];
int response = 0;
bool success = false;
while(!success) {
var key = Console.ReadKey();
success = Int32.TryParse(key.KeyChar.ToString(), out response);
if (response > options.Count()) success = false;
}
var value = options.ElementAt(response);
Console.WriteLine(" >> " + value.ToString());
Console.WriteLine();
return value;
}
public static string input_prompt(string prompt, string default_result) {
Write(prompt + " (", ConsoleColor.Yellow);
Write(default_result, ConsoleColor.White);
Write(") ", ConsoleColor.Yellow);
var result = Console.ReadLine();
if (string.IsNullOrWhiteSpace(result)) return default_result;
return result;
}
@@ -0,0 +1,20 @@
using ManyConsole;
using System.Reflection;
namespace bts {
public class SettinsManagerCommand : ConsoleCommand {
public SettinsManagerCommand() {
IsCommand("SettingsManager", "Copy workspaces around");
}
public override int Run(string[] remainingArguments) {
var asm = Assembly.Load("spark");
var type = asm.GetType("bts.settings.SettingsManagerTool");
var run = type.GetMethod("run", BindingFlags.Static | BindingFlags.Public);
run.Invoke(null, new object[0]);
return 0;
}
}
}
+1 -1
View File
@@ -1 +1 @@
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/services/AdminService.proto;api/services/ApiUnitTestService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/services/UserService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/Executor.conf;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cpp_config.conf;config/defaults/dynamic_orders.conf;config/defaults/edge.conf;config/defaults/expiration_display_offset.conf;config/defaults/jetfix.conf;config/defaults/logging.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cpp_config.proto;config/protos/dynamic_orders.proto;config/protos/environment.proto;config/protos/expiration_display_offset.proto;config/protos/jetfix.proto;config/protos/logging.proto;config/protos/orders_fills_cleanup.proto;config/protos/quickbus_cfg.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPriceLantencyTester.cpp;md/Diag/ShmDumper.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MDRecoverableConsumer.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/md2_tests.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/Dispatcher.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/datetime.cpp;utils/download.cpp;utils/file_utils.cpp;utils/init_spark_lib.cpp;utils/is_unittest_environment.cpp)
set(sources api/apicore.proto;api/apigateway.proto;api/apioptions.proto;api/core/ApiClientInterop.cpp;api/core/ApiServerInterop.cpp;api/public/ApiServer.cpp;api/public/ClientChannel.cpp;api/public/QuickbusClientChannel.cpp;api/public/ServerChannel.cpp;api/public/ServiceContext.cpp;api/service_helpers/AdminServiceUtils.cpp;api/services/AdminService.proto;api/services/ApiUnitTestService.proto;api/services/ErrorReportService.proto;api/services/HelloService.proto;api/services/MarketDataRelay.proto;api/services/OrderService.proto;api/services/OutOfProcessURLListener.proto;api/services/PersistenceService.proto;api/services/PositionService.proto;api/services/ShellDiagnosticService.proto;api/services/ShellLatencyService.proto;api/services/SyntheticSecurityService.proto;api/services/UserService.proto;api/test/ApiTests.cpp;api/test/HelloServiceServer.cpp;config/ConfigCheck.cpp;config/ConfigDownloader.cpp;config/ConfigErrorCollector.cpp;config/ConfigLog.cpp;config/ConfigPropertyEvaluator.cpp;config/ConfigValueQueue.cpp;config/ConfigurationException.cpp;config/ConfigurationState.cpp;config/PreprocessInputStream.cpp;config/config.cpp;config/defaults/Executor.conf;config/defaults/MarketData.conf;config/defaults/Ports.conf;config/defaults/Symbols.conf;config/defaults/cpp_config.conf;config/defaults/dynamic_orders.conf;config/defaults/edge.conf;config/defaults/expiration_display_offset.conf;config/defaults/jetfix.conf;config/defaults/logging.conf;config/defaults/orders_fills_cleanup.conf;config/defaults/spreader.conf;config/defaults/testkeys.conf;config/defaults/toggles.conf;config/extensions/extensions.proto;config/invalid/invalid.proto;config/protos/ExchangeSimCfg.proto;config/protos/MarketData.proto;config/protos/Ports.proto;config/protos/Symbols.proto;config/protos/UI.proto;config/protos/cpp_config.proto;config/protos/dynamic_orders.proto;config/protos/expiration_display_offset.proto;config/protos/jetfix.proto;config/protos/logging.proto;config/protos/orders_fills_cleanup.proto;config/protos/quickbus_cfg.proto;config/protos/spreader.proto;config/protos/system.proto;config/protos/testkeys.proto;config/protos/toggles.proto;config/tests/HTTPServer.cpp;config/tests/config_ref_tests.cpp;config/tests/config_tests.cpp;config/text_format/text_format.cpp;domain_model/Security.cpp;domain_model/Security.proto;domain_model/SecurityTests.cpp;domain_model/tests/domain_tests.cpp;expression/BooleanGrammar.cpp;expression/ExpressionEvaluator.cpp;expression/ParserExceptions.cpp;expression/Value.cpp;expression/tests/expression_parser_tests.cpp;logging/LoggerHub.cpp;logging/Sink.cpp;logging/logging.cpp;logging/tests/logging_tests.cpp;md/Diag/MDPriceLantencyTester.cpp;md/Diag/ShmDumper.cpp;md/MDConsumer.cpp;md/MDConsumerHandle.cpp;md/MDConsumerInterop.cpp;md/MDProducer.cpp;md/MDProducerHandle.cpp;md/MDRecoverableConsumer.cpp;md/MemorySegmentUtils.cpp;md/PlatformLoader.cpp;md/PriceSize.cpp;md/SecurityDB.cpp;md/SecurityIDRecorder.cpp;md/SettlementRecorder.cpp;md/Shm/FixedSecurity.cpp;md/SyntheticSecurityService.cpp;md/cme/MDP3Utils.cpp;md/common.cpp;md/protos/co2.proto;md/relay/QueryServer.cpp;md/relay/RelayClient.cpp;md/relay/RelayRecorder.cpp;md/test/Co2ManagedTestHelper.cpp;md/test/Co2TestInstrument.cpp;md/test/md2_tests.cpp;md/test/synthetic_book_merge_tests.cpp;os/os.cpp;os/tests/os_tests.cpp;quickbus/core/LocalNode.cpp;quickbus/core/Quickbus.cpp;quickbus/core/SubscriptionID.cpp;quickbus/core/TableID.cpp;quickbus/message_model/Update.cpp;quickbus/message_model/merge_updates.cpp;quickbus/network/QBConnection.cpp;quickbus/network/QBConnectionManager.cpp;quickbus/network/endpoint_description.cpp;quickbus/network/quickbus_msgs.proto;quickbus/pubsub/TablePublisher.cpp;quickbus/pubsub/TableSubscriber.cpp;quickbus/pubsub/tests/qb_pubsub_tests.cpp;quickbus/routing/INode.cpp;quickbus/routing/NodeID.cpp;quickbus/routing/Router.cpp;quickbus/rpc/RPCClient.cpp;quickbus/rpc/RPCServer.cpp;quickbus/rpc/RPCSessionID.cpp;quickbus/rpc/rpc_utils.cpp;quickbus/rpc/tests/qb_rpc_tests.cpp;quickbus/tests/quickbus_tests.cpp;sparkproto/SparkProtos.proto;testing/catch_test_runner.cpp;utils/Dispatcher.cpp;utils/HTTPStream.cpp;utils/PBUtils.cpp;utils/Puid.cpp;utils/SecureLogon.cpp;utils/SharedMemory.cpp;utils/Sqlite_utils.cpp;utils/Uuid.cpp;utils/datetime.cpp;utils/download.cpp;utils/file_utils.cpp;utils/init_spark_lib.cpp;utils/is_unittest_environment.cpp)
+9 -1
View File
@@ -109,7 +109,15 @@ message TickOrderDefinition {
message LeanOrderDefinition {
spark.QuantityMeasure cross_threshold = 1;
uint32 max_chase_ticks = 2;
bool detach_on_toward = 4;
reserved 4; reserved "detach_on_toward";
enum OnToward
{
NO_CHANGE = 0; //continue to lean on initial inside market
CANCEL = 1; //cancel algo and order
DETACH = 2; //cancel algo but leave order working
REPRICE = 3; //lean on new inside market
}
OnToward trade_toward_behavior = 5;
CustomOrderDefinition child = 3;
}
message JoinOrderDefinition {
+1 -1
View File
@@ -234,7 +234,7 @@ bool ConfigPropertyEvaluator::get_value(const std::string& property, Value* out_
tokenizer<char_separator<char> >::iterator iter = tokens.begin (), end = tokens.end ();
// The first token is the key name
const proto::Message* key = _config.try_get_message(*iter);
const proto::Message* key = _config.try_get_message_or_default(*iter);
if (!key) return false;
// 2) Drill down using reflection to find the named property
+13
View File
@@ -616,6 +616,19 @@ const proto::Message* ConfigurationState::try_get_message(const std::string& pro
return nullptr;
}
const proto::Message* ConfigurationState::try_get_message_or_default(const std::string& property_name) {
const auto pmsg = try_get_message(property_name);
if (pmsg) {
return pmsg;
}
// If we can't find a value we should return a default instance
const auto* descriptor = get_descriptor_by_name(property_name);
if (descriptor) {
return proto::MessageFactory::generated_factory()->GetPrototype(descriptor);
}
return nullptr;
}
const proto::Message& ConfigurationState::get_message(const proto::Descriptor* property_desc)
{
if (!is_valid_key_descriptor(property_desc))
+1
View File
@@ -59,6 +59,7 @@ namespace internal {
const proto::Message& get_message(const proto::Descriptor* property_desc);
const proto::Message* try_get_message(const std::string& property_name);
const proto::Message* try_get_message_or_default(const std::string& property_name);
bool is_initialized() { return _is_initialized; }
+1 -10
View File
@@ -76,16 +76,7 @@ extern "C" BTS_EXPORT const char* get_buffer(const char* key_name, int& out_leng
extern "C" BTS_EXPORT const proto::Message* get_named(const char* key_name)
{
const auto* pmessage = config_state.try_get_message(key_name);
if (pmessage) {
return pmessage;
}
// If we can't find a value we should return a default instance
const auto* descriptor = config_state.get_descriptor_by_name(key_name);
if (descriptor) {
return proto::MessageFactory::generated_factory()->GetPrototype(descriptor);
}
return nullptr;
return config_state.try_get_message_or_default(key_name);
}
BTS_EXPORT std::string get_macro_string(const char* name) { return config_state.get_macro_string(name); }
+20
View File
@@ -26,6 +26,26 @@ SymbolList {
}
}
Symbols {
rule: "DeploymentType.type == 'DEMO' and System.platform == 'windows'"
value {
sim {
future: @SymbolList.symbol
spread: @SymbolList.symbol
}
}
}
Symbols {
rule: "DeploymentType.type == 'PROD' and System.platform == 'windows'"
value {
glbx {
future: @SymbolList.symbol
spread: @SymbolList.symbol
}
}
}
Symbols {
value {
glbx {
-8
View File
@@ -1,8 +0,0 @@
syntax='proto2';
package bts.config;
message Deployment {
// Acceptable values:
// DEV_CHAPEL_HILL, DEV_CHICAGO, DEMO_GT, QA, CUSTOMER
optional string type = 1 [default="DEV_CHAPEL_HILL"];
}
+3 -2
View File
@@ -24,8 +24,7 @@ struct OrderStore::PImpl {
PImpl()
: state(State::WAIT_SEC), known_orders(),
store(new persistence::SqliteStore("orders")), order_stream(),
soft_cleanup_enabled (config::get<config::toggles::OrdersSoftCleanup>().enabled()),
cutoff_time(SODPosition::get_orders_start_time())
soft_cleanup_enabled (config::get<config::toggles::OrdersSoftCleanup>().enabled())
{}
State state;
@@ -76,6 +75,8 @@ void OrderStore::init() {
auto all = me->store->retrieve_all()[orders_ns];
LOG(persist, Info, "Finished loading all {} orders", all.size());
me->cutoff_time=SODPosition::get_order_cutoff_time(all);
for (auto const &kvp : all)
if (utils::pb::from_string<api::orderman::OrderRecord>(
kvp.second, &rec)) {
+45 -6
View File
@@ -4,6 +4,7 @@
#include "lib/config/protos/toggles.pb.h"
#include "lib/config/protos/orders_fills_cleanup.pb.h"
#include "lib/config/config.h"
#include "lib/utils/PBUtils.h"
#include <sys/time.h>
#include <sstream>
@@ -18,12 +19,14 @@ _sod_time(_get_fills_sod_time()){
_enabled, _sod_time.tv_sec);
}
// returns the timeval for today's hh,mm,ss
// timeval is the microsecons from epoch)
timeval SODPosition::_to_timeval(uint16_t hh, uint16_t mm, uint16_t ss){
bts_assert(hh<24);
bts_assert(mm<60);
bts_assert(ss<60);
time_t secs;
time (&secs); // seconds since epoch
time (&secs); // seconds since epoch (utc)
struct tm* ptm = gmtime (&secs);
ptm->tm_hour=hh;
ptm->tm_min=mm;
@@ -37,9 +40,8 @@ timeval SODPosition::_to_timeval(uint16_t hh, uint16_t mm, uint16_t ss){
timeval SODPosition::_subtract_days(const timeval& tv, uint32_t n_days){
uint32_t secs_in_day=86400*n_days;
bts_assert(tv.tv_sec>secs_in_day);
timeval rv=tv;
rv.tv_sec=rv.tv_sec-secs_in_day;
rv.tv_sec=(rv.tv_sec > secs_in_day) ? rv.tv_sec-secs_in_day : 0;
return rv;
}
@@ -69,6 +71,42 @@ timeval SODPosition::get_orders_start_time(){
return sod;
}
timeval SODPosition::get_order_cutoff_time(
const std::map<std::string,std::string>& order_map){
//returns true is t1 >= t2
auto compare_ts = [&](google::protobuf::Timestamp t1, google::protobuf::Timestamp t2) -> bool
{
if (t1.seconds() > t2.seconds())
return true;
else if (t1.seconds() < t2.seconds())
return false;
else
return t1.nanos() >= t2.nanos();
};
google::protobuf::Timestamp max_ts;
max_ts.set_seconds(0);
max_ts.set_nanos(0);
for (auto const &kvp : order_map){
OrderRecord trec;
if (utils::pb::from_string<api::orderman::OrderRecord>(kvp.second, &trec)){
const auto& ts = trec.state().created();
if(compare_ts(ts,max_ts))
(&max_ts)->CopyFrom(ts);
}
else
LOG(OrderMan, Error,
"Could not recover order {} from storage. "
"This should be investigated",
kvp.first);
}
timeval rv;
rv.tv_sec=max_ts.seconds();
rv.tv_usec=static_cast<double>(max_ts.nanos())/1000;
const auto& orders_cleanup = config::get<config::OrdersSoftCleanupCutoff>();
return _subtract_days(rv,orders_cleanup.extra_days());
}
std::string SODPosition::_sod_fill_id(const Fill& fill,api::Side side){
//sod:acct:long/short:sec
std::ostringstream oss;
@@ -80,12 +118,12 @@ std::string SODPosition::_sod_fill_id(const Fill& fill,api::Side side){
void SODPosition::_merge_pos(Fill& pos, const Fill& fill){
bts_assert(pos.security_key()==fill.security_key());
bts_assert(pos.account()==fill.account());
bts_assert(pos.side()==fill.side());
pos.set_last_price(fill.last_price());
bts_assert(pos.side()==fill.side());
double total_qty=pos.last_shares()+fill.last_shares();
double avg_price=(pos.avg_price()*pos.last_shares()+
fill.avg_price()*fill.last_shares())/total_qty;
fill.last_price()*fill.last_shares())/total_qty;
pos.set_avg_price(avg_price);
pos.set_last_price(avg_price);
pos.set_last_shares(total_qty);
}
@@ -98,6 +136,7 @@ void SODPosition::_zero_pos(Fill& pos, const Fill& fill, api::Side side){
pos.set_fill_kind(Fill::FILL_KIND_SOD);
pos.set_order_key(0);
pos.set_fill_key(_sod_fill_id(fill,side));
pos.set_last_shares(0);
}
bool SODPosition::add_fill_to_sod_pos(const Fill& fill){
+2 -1
View File
@@ -31,9 +31,10 @@ public:
SODPosition();
// all inactive orders before this time are not published
static timeval get_orders_start_time();
static timeval get_order_cutoff_time(const std::map<std::string,std::string>& ordermap);
bool add_fill_to_sod_pos(const Fill& fill);
void add_sod_pos_as_fill_events(std::vector<StoredFillEvent>& fill_events,
std::map<SecurityKey, const api::Security*> sec_map);
std::map<SecurityKey, const api::Security*> sec_map);
};
}}
@@ -12,12 +12,12 @@ using namespace api::orderman;
struct LeanOrder::PImpl
{
PImpl() : cross_threshold(), max_chase_ticks(0), detach_on_toward(false), opposite_at_inception(), num_chases(0)
PImpl() : cross_threshold(), max_chase_ticks(0), trade_toward_behavior(LeanOrderDefinition_OnToward_NO_CHANGE), opposite_at_inception(), num_chases(0)
{}
spark::QuantityMeasure cross_threshold;
uint32_t max_chase_ticks;
bool detach_on_toward;
LeanOrderDefinition_OnToward trade_toward_behavior;
md::PriceSize opposite_at_inception;
uint32_t num_chases;
@@ -37,7 +37,7 @@ void LeanOrder::setup_child(const api::orderman::OrderDefinition& this_def, cons
me->cross_threshold = lean_def.cross_threshold();
me->max_chase_ticks = lean_def.max_chase_ticks();
me->detach_on_toward = lean_def.detach_on_toward();
me->trade_toward_behavior = lean_def.trade_toward_behavior();
}
void LeanOrder::payup(const md::PriceSize&, const bts::orderman::BookUpdateEvent& book, uint32_t cross_ticks /*= 0*/)
@@ -96,6 +96,33 @@ void LeanOrder::paydown(const md::PriceSize&, const bts::orderman::BookUpdateEve
report_state();
}
void LeanOrder::choose_trade_toward_behavior(const md::PriceSize& opposite)
{
switch (me->trade_toward_behavior)
{
case LeanOrderDefinition_OnToward_CANCEL:
{
cancel_child();
transition(ORDER_STATUS_CANCELED);
report_state();
}
break;
case LeanOrderDefinition_OnToward_DETACH:
{
detach();
}
break;
case LeanOrderDefinition_OnToward_REPRICE:
{
me->opposite_at_inception = opposite;
}
break;
case LeanOrderDefinition_OnToward_NO_CHANGE:
default:
break;
}
}
void LeanOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
{
switch (this_state().status())
@@ -122,12 +149,7 @@ void LeanOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
{
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; //we don't want to detach so look at next level
}
choose_trade_toward_behavior(opposite);
else if(opposite.price() > me->opposite_at_inception.price())
payup(opposite, book); //you missed, payup/join
else
@@ -140,12 +162,7 @@ void LeanOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
{
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;
}
choose_trade_toward_behavior(opposite);
else if(opposite.price() < me->opposite_at_inception.price())
paydown(opposite, book);
else
@@ -26,6 +26,7 @@ protected:
private:
void payup(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks = 0) override;
void paydown(const md::PriceSize& opposite, const bts::orderman::BookUpdateEvent&, uint32_t cross_ticks = 0) override;
void choose_trade_toward_behavior(const md::PriceSize& opposite);
private:
struct PImpl;
@@ -80,6 +80,33 @@ void TopOrder::on_book_update(const bts::orderman::BookUpdateEvent& book)
{
case ORDER_STATUS_INACTIVE:
{
Quantity thresh = SpreaderUtils::_quantity_threshold(me->top_threshold, Quantity(this_state().quantity()));
if(definition().side() == api::SIDE_BUY)
{
const auto& same = book.book.side(api::Side::SIDE_BUY)[0];
if(securities::test_price_equality(this_state().price(), same.price(), tick_size()))
{
if(same.size() <= thresh.value())
{
transition(ORDER_STATUS_CANCELED);
report_state();
return;
}
}
}
else
{
const auto& same = book.book.side(api::Side::SIDE_SELL)[0];
if(securities::test_price_equality(this_state().price(), same.price(), tick_size()))
{
if(same.size() <= thresh.value())
{
transition(ORDER_STATUS_CANCELED);
report_state();
return;
}
}
}
activate_child(Price(this_state().price()), Quantity(this_state().quantity()));
transition(ORDER_STATUS_WORKING);
report_state();
+3 -1
View File
@@ -151,10 +151,12 @@ std::string get_server_info(const api::ServiceContext& ctx) {
if (response.success()) {
ss << " \"users\": [" << endl;
bool first = true;
for (const auto& user : response.result()->users()) {
if (user.is_present()) {
ss << " ";
if (&user != &response.result()->users()[0]) ss << ",";
if (first) { first = false; }
else { ss << ","; }
ss << "{ ";
ss << "\"name\": \"" << user.name() << "\", ";
ss << "\"operator_id\": \"" << user.user_data().exchange_user_data().cme_data().operator_id() << "\"";