From 51ed07a730372d498dfd8df1d3589bba760ef5ca Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Thu, 2 Nov 2023 13:06:09 +0000 Subject: [PATCH 1/6] reduce excessive log messages when no contract order spawned --- .../spawn_children_from_instrument_orders.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sysexecution/stack_handler/spawn_children_from_instrument_orders.py b/sysexecution/stack_handler/spawn_children_from_instrument_orders.py index 54db138d70..968ef1a0c3 100644 --- a/sysexecution/stack_handler/spawn_children_from_instrument_orders.py +++ b/sysexecution/stack_handler/spawn_children_from_instrument_orders.py @@ -64,15 +64,18 @@ def spawn_children_from_instrument_order_id(self, instrument_order_id: int): self.data, instrument_order ) - log = instrument_order.log_with_attributes(self.log) - log.debug("List of contract orders spawned %s" % str(list_of_contract_orders)) + if len(list_of_contract_orders) > 0: + log = instrument_order.log_with_attributes(self.log) + log.debug( + "List of contract orders spawned %s" % str(list_of_contract_orders) + ) - self.add_children_to_stack_and_child_id_to_parent( - self.instrument_stack, - self.contract_stack, - instrument_order, - list_of_contract_orders, - ) + self.add_children_to_stack_and_child_id_to_parent( + self.instrument_stack, + self.contract_stack, + instrument_order, + list_of_contract_orders, + ) def add_children_to_stack_and_child_id_to_parent( self, From abb1fb40fdda6937e2572dd4cd2e15620ab3b1d2 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Thu, 2 Nov 2023 14:44:13 +0000 Subject: [PATCH 2/6] reduce excessive logging on dataBroker() creation --- sysexecution/algos/algo_original_best.py | 27 ++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/sysexecution/algos/algo_original_best.py b/sysexecution/algos/algo_original_best.py index 1b8a02646c..b2ef12f456 100644 --- a/sysexecution/algos/algo_original_best.py +++ b/sysexecution/algos/algo_original_best.py @@ -111,7 +111,7 @@ def prepare_and_submit_trade(self) -> orderWithControls: try: okay_to_do_limit_trade = limit_trade_viable( ticker_object=ticker_object, - data=data, + data_broker=self.data_broker, order=cut_down_contract_order, log=log, ) @@ -151,7 +151,6 @@ def manage_live_trade( log = broker_order_with_controls_and_order_id.order.log_with_attributes( data.log ) - data_broker = dataBroker(data) trade_open = True is_aggressive = False @@ -181,7 +180,7 @@ def manage_live_trade( else: # passive limit trade reason_to_switch = reason_to_switch_to_aggressive( - data=data, + data_broker=self.data_broker, broker_order_with_controls=broker_order_with_controls_and_order_id, log=log, ) @@ -210,8 +209,10 @@ def manage_live_trade( ) break - order_cancelled = data_broker.check_order_is_cancelled_given_control_object( - broker_order_with_controls_and_order_id + order_cancelled = ( + self.data_broker.check_order_is_cancelled_given_control_object( + broker_order_with_controls_and_order_id + ) ) if order_cancelled: log.warning("Order has been cancelled: not by algo") @@ -221,7 +222,10 @@ def manage_live_trade( def limit_trade_viable( - data: dataBlob, order: contractOrder, ticker_object: tickerObject, log: pst_logger + data_broker: dataBroker, + order: contractOrder, + ticker_object: tickerObject, + log: pst_logger, ) -> bool: # no point doing limit order if we've got imbalanced size issues, as we'd @@ -235,7 +239,7 @@ def limit_trade_viable( return False # or if not enough time left - if is_market_about_to_close(data, order=order, log=log): + if is_market_about_to_close(data_broker=data_broker, order=order, log=log): log.debug( "Market about to close or stack handler nearly close - doing market order" @@ -284,7 +288,9 @@ def file_log_report_limit_order( def reason_to_switch_to_aggressive( - data: dataBlob, broker_order_with_controls: orderWithControls, log: pst_logger + data_broker: dataBroker, + broker_order_with_controls: orderWithControls, + log: pst_logger, ) -> str: ticker_object = broker_order_with_controls.ticker @@ -298,7 +304,7 @@ def reason_to_switch_to_aggressive( ) market_about_to_close = is_market_about_to_close( - data=data, order=broker_order_with_controls, log=log + data_broker=data_broker, order=broker_order_with_controls, log=log ) if market_about_to_close: return "Market is closing soon or stack handler will end soon" @@ -325,11 +331,10 @@ def reason_to_switch_to_aggressive( def is_market_about_to_close( - data: dataBlob, + data_broker: dataBroker, order: Union[brokerOrder, contractOrder, orderWithControls], log: pst_logger, ) -> bool: - data_broker = dataBroker(data) try: short_of_time = data_broker.less_than_N_hours_of_trading_left_for_contract( From 7a95cce9c2f546166fcab7789c1750b6c22e6a22 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Thu, 2 Nov 2023 14:45:00 +0000 Subject: [PATCH 3/6] add minimal sleep() to wait loops, giving the GIL some breathing space --- sysexecution/algos/algo_market.py | 2 ++ sysexecution/algos/algo_original_best.py | 3 ++- sysexecution/algos/common_functions.py | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sysexecution/algos/algo_market.py b/sysexecution/algos/algo_market.py index 6197b6ac5c..41894019d8 100644 --- a/sysexecution/algos/algo_market.py +++ b/sysexecution/algos/algo_market.py @@ -2,6 +2,7 @@ Simplest possible execution method, one market order """ from copy import copy +import time from sysexecution.orders.named_order_objects import missing_order from sysexecution.algos.algo import Algo @@ -86,6 +87,7 @@ def manage_live_trade( % str(broker_order_with_controls.order) ) while trade_open: + time.sleep(0.001) log_message_required = broker_order_with_controls.message_required( messaging_frequency_seconds=MESSAGING_FREQUENCY ) diff --git a/sysexecution/algos/algo_original_best.py b/sysexecution/algos/algo_original_best.py index b2ef12f456..79fd985f29 100644 --- a/sysexecution/algos/algo_original_best.py +++ b/sysexecution/algos/algo_original_best.py @@ -2,7 +2,7 @@ This is the original 'best execution' algo I used in my legacy system """ from typing import Union - +import time from syscore.exceptions import missingData, marketClosed from sysexecution.orders.named_order_objects import missing_order @@ -164,6 +164,7 @@ def manage_live_trade( ) while trade_open: + time.sleep(0.001) if broker_order_with_controls_and_order_id.message_required( messaging_frequency_seconds=MESSAGING_FREQUENCY ): diff --git a/sysexecution/algos/common_functions.py b/sysexecution/algos/common_functions.py index 513a1987af..39edaf8315 100644 --- a/sysexecution/algos/common_functions.py +++ b/sysexecution/algos/common_functions.py @@ -1,5 +1,5 @@ # functions used by multiple algos - +import time from syscore.exceptions import orderCannotBeModified from sysdata.data_blob import dataBlob from sysproduction.data.broker import dataBroker @@ -43,6 +43,7 @@ def cancel_order( timer = quickTimer(seconds=CANCEL_WAIT_TIME) not_cancelled = True while not_cancelled: + time.sleep(0.001) is_cancelled = data_broker.check_order_is_cancelled_given_control_object( broker_order_with_controls ) From f8cbad7a6adffccd73930be11fb16784f8b1f3ca Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Fri, 3 Nov 2023 13:58:33 +0000 Subject: [PATCH 4/6] reduce excessive logging in 'trade_open' loop --- sysexecution/algos/algo_original_best.py | 7 ++++--- sysexecution/algos/common_functions.py | 5 ++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sysexecution/algos/algo_original_best.py b/sysexecution/algos/algo_original_best.py index 79fd985f29..1256f098f8 100644 --- a/sysexecution/algos/algo_original_best.py +++ b/sysexecution/algos/algo_original_best.py @@ -176,7 +176,8 @@ def manage_live_trade( if is_aggressive: ## aggressive keep limit price in line set_aggressive_limit_price( - data, broker_order_with_controls_and_order_id + data_broker=self.data_broker, + broker_order_with_controls=broker_order_with_controls_and_order_id, ) else: # passive limit trade @@ -423,7 +424,7 @@ def _is_insufficient_size_on_our_preferred_side( def set_aggressive_limit_price( - data: dataBlob, broker_order_with_controls: orderWithControls + data_broker: dataBroker, broker_order_with_controls: orderWithControls ) -> orderWithControls: limit_trade = broker_order_with_controls.order.order_type == limit_order_type if not limit_trade: @@ -437,7 +438,7 @@ def set_aggressive_limit_price( pass else: broker_order_with_controls = set_limit_price( - data, broker_order_with_controls, new_limit_price + data_broker, broker_order_with_controls, new_limit_price ) return broker_order_with_controls diff --git a/sysexecution/algos/common_functions.py b/sysexecution/algos/common_functions.py index 39edaf8315..a8411952d4 100644 --- a/sysexecution/algos/common_functions.py +++ b/sysexecution/algos/common_functions.py @@ -58,13 +58,12 @@ def cancel_order( def set_limit_price( - data: dataBlob, + data_broker: dataBroker, broker_order_with_controls: orderWithControls, new_limit_price: float, ): - log = broker_order_with_controls.order.log_with_attributes(data.log) - data_broker = dataBroker(data) + log = broker_order_with_controls.order.log_with_attributes(data_broker.data.log) try: broker_order_with_controls = ( From 7dfea17294e0ad8228aa52a58e7c41e2ab9ce5cb Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Mon, 6 Nov 2023 13:01:52 +0000 Subject: [PATCH 5/6] reduce excessive logging in 'trade_open' loop --- sysproduction/data/broker.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sysproduction/data/broker.py b/sysproduction/data/broker.py index a1c553d0f8..b4a49af3f3 100644 --- a/sysproduction/data/broker.py +++ b/sysproduction/data/broker.py @@ -45,6 +45,10 @@ class dataBroker(productionDataLayerGeneric): + def __init__(self, data: dataBlob = arg_not_supplied): + super().__init__(data) + self._diag_controls = diagControlProcess() + def _add_required_classes_to_data(self, data) -> dataBlob: # Add a list of broker specific classes that will be aliased as self.data.broker_fx_prices, @@ -90,6 +94,10 @@ def broker_fx_handling_data(self) -> brokerFxHandlingData: def broker_static_data(self) -> brokerStaticData: return self.data.broker_static + @property + def diag_controls(self) -> diagControlProcess: + return self._diag_controls + ## Methods def get_list_of_contract_dates_for_instrument_code( @@ -191,9 +199,8 @@ def less_than_N_hours_of_trading_left_for_contract( self, contract: futuresContract, N_hours: float = 1.0 ) -> bool: - diag_controls = diagControlProcess() hours_left_before_process_finishes = ( - diag_controls.how_long_in_hours_before_trading_process_finishes() + self.diag_controls.how_long_in_hours_before_trading_process_finishes() ) if hours_left_before_process_finishes < N_hours: From 2b2f84a8fc1a6132b851ec12f7a58ded7876f822 Mon Sep 17 00:00:00 2001 From: Andy Geach Date: Tue, 7 Nov 2023 10:41:34 +0000 Subject: [PATCH 6/6] merge latest, black --- .../optimised_positions_stage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/systems/provided/dynamic_small_system_optimise/optimised_positions_stage.py b/systems/provided/dynamic_small_system_optimise/optimised_positions_stage.py index c98000c3ee..0b4d4a3c40 100644 --- a/systems/provided/dynamic_small_system_optimise/optimised_positions_stage.py +++ b/systems/provided/dynamic_small_system_optimise/optimised_positions_stage.py @@ -149,9 +149,9 @@ def get_reduce_only_instruments(self) -> list: return reduce_only_keys def get_long_only_instruments(self) -> list: - long_only_keys =\ + long_only_keys = ( self.config.get_element_or_default("long_only_instruments_DO_ONLY", []), - + ) return long_only_keys