def send_to_algo( self, contract_order_to_trade: contractOrder ) -> (Algo, orderWithControls): log = contract_order_to_trade.log_with_attributes(self.log) instrument_order = self.get_parent_of_contract_order( contract_order_to_trade) contract_order_to_trade_with_algo_set = check_and_if_required_allocate_algo_to_single_contract_order( data=self.data, contract_order=contract_order_to_trade, instrument_order=instrument_order) log.msg("Sending order %s to algo %s" % (str(contract_order_to_trade_with_algo_set), contract_order_to_trade_with_algo_set.algo_to_use)) algo_class_to_call = self.add_controlling_algo_to_order( contract_order_to_trade_with_algo_set) algo_instance = algo_class_to_call( self.data, contract_order_to_trade_with_algo_set) # THIS LINE ACTUALLY SENDS THE ORDER TO THE ALGO placed_broker_order_with_controls = algo_instance.submit_trade() if placed_broker_order_with_controls is missing_order: # important we do this or order will never execute # if no issue here will be released once order filled self.contract_stack.release_order_from_algo_control( contract_order_to_trade_with_algo_set.order_id) return missing_order return algo_instance, placed_broker_order_with_controls
def create_broker_order_for_contract_order(self, contract_order_id, check_if_open=True): original_contract_order = self.contract_stack.get_order_with_id_from_stack( contract_order_id) contract_order = self.preprocess_contract_order( original_contract_order, check_if_open=check_if_open) if contract_order is missing_order: return None contract_order = check_and_if_required_allocate_algo_to_single_contract_order( self.data, contract_order) algo_class_to_call = self.resolve_algo(contract_order) algo_instance = algo_class_to_call(self.data, contract_order) ## THIS LINE ACTUALLY SENDS THE ORDER TO THE ALGO broker_order_with_controls = algo_instance.submit_trade() if broker_order_with_controls is missing_order: self.contract_stack.release_order_from_algo_control( contract_order_id) return None broker_order_with_controls = self.add_trade_to_database( broker_order_with_controls) broker_order_with_controls = algo_instance.manage_trade( broker_order_with_controls) result = self.post_trade_processing(broker_order_with_controls) return result
def create_broker_order_for_contract_order(self, contract_order_id): ## This next line prevents another process or algo having a go TEMPORARY_ALGO_REFERENCE = 'Locked-for-writing' self.contract_stack.add_controlling_algo_ref(contract_order_id, TEMPORARY_ALGO_REFERENCE) contract_order = self.contract_stack.get_order_with_id_from_stack( contract_order_id) log = log_attributes_from_contract_order(self.log, contract_order) contract_order = check_and_if_required_allocate_algo_to_single_contract_order( self.data, contract_order) algo_to_use_str = contract_order.algo_to_use algo_method = resolve_function(algo_to_use_str) ## The algo method submits an order to the broker, and returns a broker order object ## We then save the brokerorder in the broker stack, and add it as a child to a contract order ## Algos may be 'fire and forget' (a simple market order, as implemented initially) or 'active' ## Active algos need to keep running on another thread (need to work out how to do this) ## They will set the property 'reference_of_controlling_algo' in contract order ## Fills are picked up by another process (or if the algo is an active thing, potentially by itself) broker_order, reference_of_controlling_algo = algo_method( self.data, contract_order) if broker_order is missing_order: # something bad has happened and we can't submit an order to the broker # Nae bother, maybe try again later # Unlock the contract order in case we want to do this later self.contract_stack.release_order_from_algo_control( contract_order_id) return None broker_order_id = self.broker_stack.put_order_on_stack(broker_order) if type(broker_order_id) is not int: # We've created a broker order but can't add it to the broker order database # Probably safest to leave the contract order locked otherwise there could be multiple # broker orders issued and nobody wants that! log.critical( "Created a broker order %s but can't add it to the order stack!! (condition %s)" % (str(broker_order), str(e))) return failure ## Release the temporary algo lock self.contract_stack.release_order_from_algo_control(contract_order_id) # Create new algo lock # This means nobody else can try and execute this order until it is released self.contract_stack.add_controlling_algo_ref( contract_order_id, reference_of_controlling_algo) self.contract_stack.add_another_child_to_order(contract_order_id, broker_order_id) return success
def create_broker_order_for_contract_order(self, contract_order_id): original_contract_order = self.contract_stack.get_order_with_id_from_stack(contract_order_id) log = original_contract_order.log_with_attributes(self.log) ## Check the order doesn't breach trade limits contract_order = self.what_contract_trade_is_possible(original_contract_order) contract_order = check_and_if_required_allocate_algo_to_single_contract_order(self.data, contract_order) algo_to_use_str = contract_order.algo_to_use algo_method = resolve_function(algo_to_use_str) ## The algo method submits an order to the broker, and returns a broker order object ## We then save the brokerorder in the broker stack, and add it as a child to a contract order ## Algos may be 'fire and forget' (a simple market order, as implemented initially) or 'active' ## Active algos need to keep running on another thread (need to work out how to do this) ## They will set the property 'reference_of_controlling_algo' in contract order ## Fills are picked up by another process (or if the algo is an active thing, potentially by itself) broker_order, reference_of_controlling_algo = algo_method(self.data, contract_order) if broker_order is missing_order: # something bad has happened and we can't submit an order to the broker # Nae bother, maybe try again later # Unlock the contract order in case we want to do this later self.contract_stack.release_order_from_algo_control(contract_order_id) return None ## update trade limits self.add_trade_to_trade_limits(broker_order) broker_order_id = self.broker_stack.put_order_on_stack(broker_order) if type(broker_order_id) is not int: # We've created a broker order but can't add it to the broker order database # Probably safest to leave the contract order locked otherwise there could be multiple # broker orders issued and nobody wants that! log.critical("Created a broker order %s but can't add it to the order stack!! (condition %s)" % (str(broker_order), str(broker_order_id))) return failure # ....create new algo lock # This means nobody else can try and execute this order until it is released # Only the algo itself can release! self.contract_stack.add_controlling_algo_ref(contract_order_id, reference_of_controlling_algo) # This broker order is a child of the parent contract order # We add 'another' child since it's valid to have multiple broker orders self.contract_stack.add_another_child_to_order(contract_order_id, broker_order_id) return success
def create_broker_order_for_contract_order(self, contract_order_id, check_if_open=True): original_contract_order = self.contract_stack.get_order_with_id_from_stack( contract_order_id) if original_contract_order is missing_order: # weird race condition return failure contract_order = self.preprocess_contract_order( original_contract_order, check_if_open=check_if_open) if contract_order is missing_order: #print("Empty order not submitting to algo") return None contract_order = check_and_if_required_allocate_algo_to_single_contract_order( self.data, contract_order) log = contract_order.log_with_attributes(self.log) log.msg("Sending order %s to algo %s" % (str(contract_order), contract_order.algo_to_use)) algo_class_to_call = self.resolve_algo(contract_order) algo_instance = algo_class_to_call(self.data, contract_order) # THIS LINE ACTUALLY SENDS THE ORDER TO THE ALGO broker_order_with_controls = algo_instance.submit_trade() if broker_order_with_controls is missing_order: self.contract_stack.release_order_from_algo_control( contract_order_id) return None broker_order_with_controls = self.add_trade_to_database( broker_order_with_controls) broker_order_with_controls = algo_instance.manage_trade( broker_order_with_controls) result = self.post_trade_processing(broker_order_with_controls) return result
def create_broker_order_for_contract_order(self, contract_order_id, check_if_open=True): original_contract_order = self.contract_stack.get_order_with_id_from_stack(contract_order_id) log = original_contract_order.log_with_attributes(self.log) data_locks = dataLocks(self.data) instrument_locked = data_locks.is_instrument_locked(original_contract_order.instrument_code) if instrument_locked: log.msg("Instrument is locked, not spawning order") return None if check_if_open: data_broker = dataBroker(self.data) market_open = data_broker.is_instrument_code_and_contract_date_okay_to_trade(original_contract_order.instrument_code, original_contract_order.contract_id) if not market_open: return None # We can deal with partially filled contract orders: that's how hard we are! remaining_contract_order = original_contract_order.order_with_remaining() ## Check the order doesn't breach trade limits contract_order = self.what_contract_trade_is_possible(remaining_contract_order) ## Note we don't save the algo method, but reallocate each time ## This is useful if trading is about to finish, because we switch to market orders ## (assuming a bunch of limit orders haven't worked out so well) contract_order = check_and_if_required_allocate_algo_to_single_contract_order(self.data, contract_order) algo_to_use_str = contract_order.algo_to_use algo_method = resolve_function(algo_to_use_str) ## The algo method submits an order to the broker, and returns a broker order object ## We then save the brokerorder in the broker stack, and add it as a child to a contract order ## Algos may be 'fire and forget' (a simple market order, as implemented initially) or 'active' ## Active algos need to keep running on another thread (need to work out how to do this) ## They will set the property 'reference_of_controlling_algo' in contract order ## Fills are picked up by another process (or if the algo is an active thing, potentially by itself) broker_order, reference_of_controlling_algo = algo_method(self.data, contract_order) if broker_order is missing_order: # something bad has happened and we can't submit an order to the broker # Nae bother, maybe try again later # Unlock the contract order in case we want to do this later self.contract_stack.release_order_from_algo_control(contract_order_id) return None ## update trade limits self.add_trade_to_trade_limits(broker_order) broker_order_id = self.broker_stack.put_order_on_stack(broker_order) if type(broker_order_id) is not int: # We've created a broker order but can't add it to the broker order database # Probably safest to leave the contract order locked otherwise there could be multiple # broker orders issued and nobody wants that! log.critical("Created a broker order %s but can't add it to the order stack!! (condition %s)" % (str(broker_order), str(broker_order_id))) return failure # ....create new algo lock # This means nobody else can try and execute this order until it is released # Only the algo itself can release! # This only applies to 'fire and forget' orders that aren't controlled by an algo self.contract_stack.add_controlling_algo_ref(contract_order_id, reference_of_controlling_algo) # This broker order is a child of the parent contract order # We add 'another' child since it's valid to have multiple broker orders self.contract_stack.add_another_child_to_order(contract_order_id, broker_order_id) return success