def get_and_submit_broker_order_for_contract_order_as_market_order_with_quantity( self, contract_order, qty): log = log_attributes_from_contract_order(self.data.log, contract_order) broker = self.get_broker_name() broker_account = self.get_broker_account() broker_clientid = self.get_broker_clientid() # Check market closed? side_price, mid_price = self.check_market_conditions_for_contract_order( contract_order) broker_order = create_new_broker_order_from_contract_order( contract_order, qty, order_type="market", side_price=side_price, mid_price=mid_price, algo_comment="market order", broker=broker, broker_account=broker_account, broker_clientid=broker_clientid) submitted_broker_order = self.\ submit_broker_order(broker_order) if submitted_broker_order is missing_order: return missing_order return submitted_broker_order
def clear_parents_and_children_if_all_modification_rejected(self, instrument_order_id): parent_order = self.instrument_stack.get_order_with_id_from_stack(instrument_order_id) log = log_attributes_from_instrument_order(self.log, parent_order) list_of_child_order_ids = parent_order.children list_of_child_orders = [self.contract_stack.get_order_with_id_from_stack(child_order_id) \ for child_order_id in list_of_child_order_ids] # Check all child orders are in 'rejected' state # If any aren't we can't do this # This shouldn't happen since we only mark parent orders as rejected once all the kids are for child_order in list_of_child_orders: if not child_order.is_order_modification_rejected(): child_log = log_attributes_from_contract_order(self.log, child_order) child_log.warn("Instrument order %s has rejected modifying but child contract order %s has not! Can't clear modifications" % \ (str(parent_order), str(child_order))) return failure for child_order_id in list_of_child_order_ids: result = self.contract_stack.clear_modification_of_order_on_stack(child_order_id) if result is failure: log.warn("Can't clear modifications for contract order %d child of %s" % (child_order_id, str(parent_order))) return failure # Children are completed, we can do parent result = self.instrument_stack.clear_modification_of_order_on_stack(instrument_order_id) if result is failure: log = log_attributes_from_instrument_order(self.log, parent_order) log.warn("Cleared modifications for contract order children, but can't clear parent instrument order %s!" % parent_order) return failure return success
def pass_modification_complete_from_child_to_parent_orders(self, contract_order_id): # ... if and only if *all* children are in modification complete state child_order = self.contract_stack.get_order_with_id_from_stack(contract_order_id) log = log_attributes_from_contract_order(self.log, child_order) parent_order_id = child_order.parent if parent_order_id is no_parent: log.warn("No parent order for child order %s when trying to mark modification as complete" % (str(child_order))) return failure instrument_order = self.instrument_stack.get_order_with_id_from_stack(parent_order_id) # Check that all children have completed modifying child_id_list = instrument_order.children if child_id_list is no_children: log.warn("Reckless parenting! Instrument order %s has no children but child order %s thinks it is the parent when trying to mark modification as complete" % (str(instrument_order), str(child_order))) return failure flag_completed = [self.contract_stack.is_finished_modified(other_child_order_id) for other_child_order_id in child_id_list] if not all(flag_completed): # Can't mark parent order as complete until all children are complete return failure result = self.instrument_stack.completed_modifying_order_on_stack(parent_order_id) if result is failure: log.warn("Couldn't pass modification from child order %s up to parent order %d" % (str(child_order), parent_order_id)) return failure return success
def pass_modification_rejection_from_child_to_parent_order(self, contract_order_id): # if any child order is rejected, then we also reject the parent and all other child orders child_order = self.contract_stack.get_order_with_id_from_stack(contract_order_id) log = log_attributes_from_contract_order(self.log, child_order) parent_order_id = child_order.parent if parent_order_id is no_parent: log.warn("No parent order for child order %s when trying to mark modification as rejected" % (str(child_order))) return failure instrument_order = self.instrument_stack.get_order_with_id_from_stack(parent_order_id) # All children should also be rejected child_id_list = instrument_order.children if child_id_list is no_children: log.warn("Reckless parenting! Instrument order %s has no children but child order %s thinks it is the parent when trying to mark modification as complete" % (str(instrument_order), str(child_order))) return failure for other_child_id in child_id_list: result = self.contract_stack.reject_order_on_stack(other_child_id) if result is not success: log.warn("Couldn't mark child order %d as rejected when another child %s was rejected" % (other_child_id, str(child_order))) return failure result = self.instrument_stack.reject_order_on_stack(parent_order_id) if result is not success: log.warn("Couldn't pass reject modification from child order %s up to parent order %d" % (str(child_order), parent_order_id)) return failure return success
def spawn_children_from_instrument_order_id(self, instrument_order_id): instrument_order = self.instrument_stack.get_order_with_id_from_stack(instrument_order_id) if instrument_order is missing_order: return failure log = log_attributes_from_instrument_order(self.log, instrument_order) list_of_contract_orders = spawn_children_from_instrument_order(self.data, instrument_order) log.msg("List of contract orders spawned %s" % str(list_of_contract_orders)) list_of_child_ids = self.contract_stack.put_list_of_orders_on_stack(list_of_contract_orders) if list_of_child_ids is failure: log.msg("Failed to create child orders %s from parent order %s" % (str(list_of_contract_orders), str(instrument_order))) return failure for contract_order, child_id in zip(list_of_contract_orders, list_of_child_ids): child_log = log_attributes_from_contract_order(log, contract_order) child_log.msg("Put child order %s on contract_stack with ID %d from parent order %s" % (str(contract_order), child_id, str(instrument_order))) result = self.instrument_stack.add_children_to_order(instrument_order.order_id, list_of_child_ids) if result is not success: log.msg("Error %s when adding children to instrument order %s" % (str(result), str(instrument_order))) return failure return success
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 _modify_multiple_child_orders(self, instrument_order): """ OK, it's got multiple child orders. This is more complicated... We now have a series of possibilites: - equal and opposite positions in each (eg roll order on outright legs, spread instrument) - opposite but not equal positions in each (spread instrument) - same sign positions in each (passive roll order) It's far too complicated to try and deal with all these cases. So instead we allow a cancellation order to go ahead (where there is zero unfilled quantity left), but all other types of modifications are rejected """ log = log_attributes_from_instrument_order(self.log, instrument_order) parent_order_can_be_cancelled = instrument_order.fill_equals_modification_quantity( ) if not parent_order_can_be_cancelled: log.warn( "Instrument order %s has multiple children and isn't a full cancellation: can't be modified" % str(instrument_order)) return failure child_order_ids = instrument_order.children for child_id in child_order_ids: child_order = self.contract_stack.get_order_with_id_from_stack( child_id) if child_order is missing_order: log.warn( "Child order orderid % is missing for instrument order %s, can't pass on modification" % (child_id, str(instrument_order))) return failure child_log = log_attributes_from_contract_order( self.log, child_order) result = self.contract_stack.cancel_order(child_id) if type(result) is int: # successful cancellation modification continue elif result is order_is_in_status_modified: # Modification is already happening, probably from a previous run of this code continue else: child_log.warn( "Couldn't pass modification from parent instrument order %s to child %s error %s" % (str(instrument_order), str(child_order), str(result))) continue return success
def _modify_single_child_order_where_child_is_single_contract(self, child_id, instrument_order): child_order = self.contract_stack.get_order_with_id_from_stack(child_id) child_log = log_attributes_from_contract_order(self.log, child_order) modification_quantity = instrument_order.modification_quantity result = self.contract_stack.modify_order_on_stack(child_id, [modification_quantity]) if result is success: # fine return success elif result is order_is_in_status_modified: # Modification is already happening, probably from a previous run of this code return success else: child_log.warn("Couldn't pass modification from parent instrument order %s to child %s error %s" % (str(instrument_order), str(child_order), str(result))) return failure
def clear_parents_and_children_if_all_modification_complete( self, instrument_order_id): parent_order = self.instrument_stack.get_order_with_id_from_stack( instrument_order_id) log = log_attributes_from_instrument_order(self.log, parent_order) list_of_child_order_ids = parent_order.children list_of_child_orders = [self.contract_stack.get_order_with_id_from_stack(child_order_id) \ for child_order_id in list_of_child_order_ids] # Check all child orders are in 'completed modifying' state # if any are not, we can't do this # (this shouldn't happen, since we only set parent order to completed modifying when all children are set) for child_order in list_of_child_orders: child_log = log_attributes_from_contract_order( self.log, child_order) if not child_order.is_order_finished_modifying(): child_log.warn("Instrument order %s has finished modifying but child contract order %s has not! Can't clear modifications" % \ (str(parent_order), str(child_order))) return failure # clear the modifications for the children for child_order_id in list_of_child_order_ids: result = self.contract_stack.clear_modification_of_order_on_stack( child_order_id) if result is failure: log.warn( "Can't clear modifications for contract order %d, child of parent %s" % (child_order_id, str(parent_order))) return failure # Children are completed, we can do parent result = self.instrument_stack.clear_modification_of_order_on_stack( instrument_order_id) if result is failure: instrument_log = log_attributes_from_instrument_order( self.log, parent_order) instrument_log.warn( "Cleared modifications for contract order children, but can't clear parent instrument order %s!" % parent_order) return failure return success
def algo_market(data, contract_order): """ Simplest possible execution algo Submits a single market order for the entire quantity :param data: dataBlob :param contract_order: contractOrder :returns: tuple, (broker_order, reference of controlling algo) """ log = log_attributes_from_contract_order(data.log, contract_order) if not contract_order.fill_equals_zero(): log.warn("Simple market algo can only deal with orders that have no existing fill, not %s!" % str(contract_order)) return missing_order, "" qty = contract_order.trade if len(qty)>1: log.warn("Simple market algo can't yet deal with spread order' %s!" % str( contract_order)) return missing_order, "" ## do full order qty_for_broker = qty data_broker = dataBroker(data) broker_order = data_broker.get_and_submit_broker_order_for_contract_order_as_market_order_with_quantity(contract_order, qty_for_broker) ## Need some kind of keystore for controlling Algos ## However as this is a 'fire and forget' algo that just runs once without any permanent thread ## this doesn't matter, except perhaps for some complex case that we don't want to worry about right now ## When we introduce hooks for picking up fills, we're probably going to want to do this properly reference_of_controlling_algo = "algo_market" return broker_order, reference_of_controlling_algo
def generate_force_roll_orders_for_instrument(self, instrument_code): log = self.data.log.setup(instrument_code=instrument_code, strategy_name=ROLL_PSEUDO_STRATEGY) instrument_order, contract_orders = create_force_roll_orders( self.data, instrument_code) # Create a pseudo instrument order and a set of contract orders # This will also prevent trying to generate more than one set of roll orders if len(contract_orders) == 0 or instrument_order is missing_order: # No orders return None # Do as a transaction: if everything doesn't go to plan can roll back instrument_order.lock_order() instrument_order_id = self.instrument_stack.put_order_on_stack( instrument_order, allow_zero_orders=True) if type(instrument_order_id) is not int: if instrument_order_id is duplicate_order: # Probably already done this return success else: log.msg( "Couldn't put roll order %s on instrument order stack error %s" % (str(instrument_order), str(instrument_order_id))) return failure for child_order in contract_orders: child_order.parent = instrument_order_id # Do as a transaction: if everything doesn't go to plan can roll back # if this try fails we will roll back the instrument commit try: log = log.setup(instrument_order_id=instrument_order_id) log.msg("List of roll contract orders spawned %s" % str(contract_orders)) list_of_child_order_ids = self.contract_stack.put_list_of_orders_on_stack( contract_orders, unlock_when_finished=False) if list_of_child_order_ids is failure: log.msg("Failed to add roll contract orders to stack %s" % (str(contract_orders))) list_of_child_order_ids = [] raise Exception for roll_order, order_id in zip(contract_orders, list_of_child_order_ids): child_log = log_attributes_from_contract_order(log, roll_order) child_log.msg( "Put roll order %s on contract_stack with ID %d from parent order %s" % (str(roll_order), order_id, str(instrument_order))) self.instrument_stack._unlock_order_on_stack(instrument_order_id) result = self.instrument_stack.add_children_to_order( instrument_order_id, list_of_child_order_ids) if result is not success: log.msg( "Error %s when adding children to instrument roll order %s" % (str(result), str(instrument_order))) raise Exception except: ## Roll back instrument order self.instrument_stack._unlock_order_on_stack(instrument_order_id) self.instrument_stack.deactivate_order(instrument_order_id) self.instrument_stack.remove_order_with_id_from_stack( instrument_order_id) # If any children, roll them back also if len(list_of_child_order_ids) > 0: self.contract_stack.rollback_list_of_orders_on_stack( list_of_child_order_ids) return failure return success