def calculate_limit_prices_for_direct_child_orders(
    data: dataBlob,
    instrument_order: instrumentOrder,
    list_of_contract_orders: listOfOrders,
) -> listOfOrders:
    """
    A direct child order only contains one contract id i.e. not an intramarket spread

    :param data:
    :param instrument_order:
    :param list_of_contract_orders:
    :return: list of contract orders
    """
    list_of_contract_orders = [
        add_limit_price_to_a_direct_child_order(data, instrument_order, child_order)
        for child_order in list_of_contract_orders
    ]

    flag_missing_orders = [
        child_order is missing_order for child_order in list_of_contract_orders
    ]
    if any(flag_missing_orders):
        log = instrument_order.log_with_attributes(data.log)
        log.critical(
            "Couldn't adjust limit price for at least one child order %s: can't execute any child orders"
            % str(instrument_order)
        )
        return listOfOrders([])

    list_of_contract_orders = listOfOrders(list_of_contract_orders)

    return list_of_contract_orders
Example #2
0
    def apply_contract_fill_to_parent_order_multiple_children(
            self, list_of_contract_order_ids: list,
            instrument_order: instrumentOrder):
        ## Three cases for multiple children (as normally one to one)
        # - Inter market spread: we can't handle these yet and we'll break
        # - Leg by leg flat spread eg forced roll order: do nothing since doesn't change instrument positions
        # Distributed roll order eg if we are short -2 front, want to buy 3, will do +2 front +1 next

        log = instrument_order.log_with_attributes(self.log)

        distributed_order = self.check_to_see_if_distributed_instrument_order(
            list_of_contract_order_ids, instrument_order)

        flat_order = instrument_order.is_zero_trade()

        if flat_order:
            # An inter-market flat spread
            # Meaningless to do this
            return None

        elif distributed_order:
            # a distributed order, all orders have the same sign as the
            # instrument order
            self.apply_contract_fill_to_parent_order_distributed_children(
                list_of_contract_order_ids, instrument_order)

        else:
            # A proper spread trade across markets can't do this
            log.critical(
                "Can't handle inter-market spread orders! Instrument order %s %s"
                % (str(instrument_order), str(instrument_order.order_id)))
Example #3
0
def create_contract_roll_orders(data: dataBlob,
                                roll_spread_info: rollSpreadInformation,
                                instrument_order: instrumentOrder) -> listOfOrders:
    diag_positions = diagPositions(data)
    instrument_code = instrument_order.instrument_code

    if roll_spread_info.position_in_priced == 0:
        return missing_order

    if diag_positions.is_roll_state_force(instrument_code):
        contract_orders = create_contract_orders_spread(roll_spread_info)

    elif diag_positions.is_roll_state_force_outright(instrument_code):
        contract_orders = create_contract_orders_outright(roll_spread_info)

    else:
        log = instrument_order.log_with_attributes(data.log)
        roll_state = diag_positions.get_roll_state(instrument_code)
        log.warn("Roll state %s is unexpected, might have changed" % str(roll_state))
        return missing_order

    contract_orders = allocate_algo_to_list_of_contract_orders(
        data, contract_orders, instrument_order
    )

    return contract_orders
    def _put_adjusting_order_on_stack(self,
                                      new_order: instrumentOrder,
                                      existing_order_id_list: list,
                                      allow_zero_orders: bool = False) -> int:
        """
        Considering the unfilled orders already on the stack place an additional adjusting order

        :param new_order:
        :return:
        """
        log = new_order.log_with_attributes(self.log)

        existing_orders = listOfOrders([
            self.get_order_with_id_from_stack(order_id)
            for order_id in existing_order_id_list
        ])

        adjusted_order = calculate_adjusted_order_given_existing_orders(
            new_order, existing_orders, log)

        if adjusted_order.is_zero_trade() and not allow_zero_orders:
            # Trade we want is already in the system
            error_msg = "Adjusted order %s is zero, zero orders not allowed" % str(
                adjusted_order)
            log.warn(error_msg)
            raise zeroOrderException(error_msg)

        order_id = self._put_order_on_stack_and_get_order_id(adjusted_order)

        return order_id
    def apply_overrides_for_instrument_and_strategy(self, proposed_order: instrumentOrder)\
            -> instrumentOrder:
        """
        Apply an override to a trade

        :param strategy_name: str
        :param instrument_code: str
        :return: int, updated position
        """

        diag_overrides = diagOverrides(self.data)
        diag_positions = diagPositions(self.data)

        instrument_strategy = proposed_order.instrument_strategy

        original_position = diag_positions.get_current_position_for_instrument_strategy(
            instrument_strategy)

        override = diag_overrides.get_cumulative_override_for_instrument_strategy(
            instrument_strategy)

        revised_order = override.apply_override(original_position,
                                                proposed_order)

        if revised_order.trade != proposed_order.trade:
            log = proposed_order.log_with_attributes(self.log)
            log.msg("%s trade change from %s to %s because of override %s" % (
                instrument_strategy.key,
                str(revised_order.trade),
                str(proposed_order.trade),
                str(override),
            ))

        return revised_order
def passive_roll_child_order(
    data: dataBlob,
    trade: int,
    instrument_order: instrumentOrder,
) -> list:

    log = instrument_order.log_with_attributes(data.log)
    diag_positions = diagPositions(data)
    instrument_code = instrument_order.instrument_code

    diag_contracts = diagContracts(data)
    current_contract = diag_contracts.get_priced_contract_id(instrument_code)
    next_contract = diag_contracts.get_forward_contract_id(instrument_code)

    position_current_contract = (
        diag_positions.get_position_for_instrument_and_contract_date(
            instrument_code, current_contract))

    # Break out because so darn complicated
    if position_current_contract == 0:
        # Passive roll and no position in the current contract, start trading
        # the next contract
        log.msg(
            "Passive roll handling order %s, no position in current contract, entire trade in next contract %s"
            % (str(instrument_order), next_contract))
        return [contractIdAndTrade(next_contract, trade)]

    # ok still have a position in the current contract
    increasing_trade = sign(trade) == sign(position_current_contract)
    if increasing_trade:
        # Passive roll and increasing trade
        # Do it all in next contract
        log.msg(
            "Passive roll handling order %s, increasing trade, entire trade in next contract %s"
            % (str(instrument_order), next_contract))
        return [contractIdAndTrade(next_contract, trade)]

    # ok a reducing trade
    new_position = position_current_contract + trade
    sign_of_position_is_unchanged = sign(position_current_contract) == sign(
        new_position)
    if new_position == 0 or sign_of_position_is_unchanged:
        # A reducing trade that we can do entirely in the current contract
        log.msg(
            "Passive roll handling order %s, reducing trade, entire trade in next contract %s"
            % (str(instrument_order), next_contract))
        return [contractIdAndTrade(current_contract, trade)]

    # OKAY to recap: it's a passive roll, but the trade will be split between
    # current and next
    list_of_child_contract_dates_and_trades = \
        passive_trade_split_over_two_contracts(trade=trade,
                                               current_contract=current_contract,
                                               next_contract=next_contract,
                                               position_current_contract=position_current_contract)
    log.msg(
        "Passive roll handling order %s, reducing trade, split trade between contract %s and %s"
        % (str(instrument_order), current_contract, next_contract))

    return list_of_child_contract_dates_and_trades
    def put_balance_trades_on_stack(
        self,
        instrument_order: instrumentOrder,
        contract_order: contractOrder,
        broker_order: brokerOrder,
    ):
        log = instrument_order.log_with_attributes(self.log)
        log.msg("Putting balancing trades on stacks")

        try:
            instrument_order_id = (
                self.instrument_stack.
                put_manual_order_on_stack_and_return_order_id(instrument_order)
            )
        except Exception as e:
            log.error(
                "Couldn't add balancing instrument trade error condition %s" %
                str(e))
            return failure, missing_order, missing_order, missing_order

        try:
            contract_order.parent = instrument_order_id
            contract_order_id = self.contract_stack.put_order_on_stack(
                contract_order)
        except Exception as e:
            log.error(
                "Couldn't add balancing contract trade error condition %s " %
                str(e))
            return failure, instrument_order_id, missing_order, missing_order

        try:
            self.instrument_stack.add_children_to_order_without_existing_children(
                instrument_order_id, [contract_order_id])
        except Exception as e:

            log.error("Couldn't add children to instrument order error %s" %
                      str(e))
            return failure, instrument_order_id, contract_order_id, missing_order

        broker_order.parent = contract_order_id
        try:
            broker_order_id = self.broker_stack.put_order_on_stack(
                broker_order)
        except Exception as e:
            log.error(
                "Couldn't add balancing broker trade error condition %s" %
                str(e))
            return failure, instrument_order_id, contract_order_id, missing_order

        try:
            self.contract_stack.add_children_to_order_without_existing_children(
                contract_order_id, [broker_order_id])
        except Exception as e:
            log.error("Couldn't add children to contract order exception %s" %
                      str(e))
            return failure, instrument_order_id, contract_order_id, broker_order_id

        log.msg("All balancing trades added to stacks")

        return success, instrument_order_id, contract_order_id, broker_order_id
Example #8
0
    def update_strategy_position_table_with_instrument_order(
            self, original_instrument_order: instrumentOrder,
            new_fill: tradeQuantity):
        """
        Alter the strategy position table according to new_fill value

        :param original_instrument_order:
        :return:
        """

        instrument_strategy = original_instrument_order.instrument_strategy

        current_position_as_int = self.diag_positions.get_current_position_for_instrument_strategy(
            instrument_strategy)
        trade_done_as_int = new_fill.as_single_trade_qty_or_error()
        if trade_done_as_int is missing_order:
            self.log.critical("Instrument orders can't be spread orders!")
            return failure

        new_position_as_int = current_position_as_int + trade_done_as_int

        self.db_strategy_position_data.update_position_for_instrument_strategy_object(
            instrument_strategy, new_position_as_int)

        log = original_instrument_order.log_with_attributes(self.log)
        log.msg(
            "Updated position of %s from %d to %d because of trade %s %d fill %s"
            % (str(instrument_strategy), current_position_as_int,
               new_position_as_int, str(original_instrument_order),
               original_instrument_order.order_id, str(new_fill)))

        return success
def get_required_contract_trade_for_instrument(data: dataBlob,
                                               instrument_order: instrumentOrder) -> list:
    """
    Return the contract to trade for a given instrument

    Depends on roll status and trade vs position:
     - roll_states = ['No_Roll', 'Passive', 'Force', 'Force_Outright', 'Roll_Adjusted']

    If 'No Roll' then trade current contract
    If 'Passive', and no position in current contract: trade next contract
    If 'Passive', and reducing trade which leaves zero or something in current contract: trade current contract
    If 'Passive', and reducing trade which is larger than current contract position: trade current and next contract
    If 'Passive', and increasing trade: trade next contract
    If 'Force' or 'Force Outright' or 'Roll_Adjusted': don't trade

    :param instrument_order:
    :param data: dataBlog
    :return: tuple: list of child orders: each is a tuple: contract str or missing_contract, trade int
    """
    instrument_code = instrument_order.instrument_code
    log = instrument_order.log_with_attributes(data.log)
    trade = instrument_order.as_single_trade_qty_or_error()
    if trade is missing_order:
        log.critical("Instrument order can't be a spread order")
        return []

    diag_positions = diagPositions(data)

    if diag_positions.is_roll_state_no_roll(instrument_code):
        diag_contracts = dataContracts(data)
        current_contract = diag_contracts.get_priced_contract_id(instrument_code)

        log.msg(
            "No roll, allocating entire order %s to current contract %s"
            % (str(instrument_order), current_contract)
        )
        return [contractIdAndTrade(current_contract, trade)]

    elif diag_positions.is_roll_state_passive(instrument_code):
        # no log as function does it
        list_of_child_contract_dates_and_trades = passive_roll_child_order(data=data,
                                                                  instrument_order = instrument_order,
                                                                  trade = trade
                                                                    )

        return list_of_child_contract_dates_and_trades

    elif diag_positions.is_type_of_active_rolling_roll_state(instrument_code):
        log.msg(
            "Roll state is active rolling, not going to generate trade for order %s" %
            (str(instrument_order)))
        return []

    else:
        log.critical(
            "Roll state %s not understood: can't generate trade for %s"
            % (diag_positions.get_name_of_roll_state(instrument_code), str(instrument_order))
        )
        return []
Example #10
0
    def create_balance_instrument_trade(self,
                                        instrument_order: instrumentOrder):
        log = instrument_order.log_with_attributes(self.log)
        log.msg("Putting balancing order on instrument stack")
        instrument_order_id = self.instrument_stack.put_manual_order_on_stack_and_return_order_id(
            instrument_order)

        instrument_order.order_id = instrument_order_id

        log.msg(
            "Marking balancing trades as completed and updating positions and historic order data"
        )
        self.apply_position_change_to_instrument(instrument_order,
                                                 instrument_order.fill,
                                                 apply_entire_trade=True)
        self.handle_completed_instrument_order(instrument_order_id)
    def adjust_order_for_position_limits(self, order: instrumentOrder) -> instrumentOrder:

        log = order.log_with_attributes(self.log)

        data_position_limits = dataPositionLimits(self.data)
        cut_down_order = data_position_limits.cut_down_proposed_instrument_trade_for_position_limits(order)

        if cut_down_order.trade != order.trade:
            if cut_down_order.is_zero_trade():
                ## at position limit, can't do anything
                log.warn("Can't trade at all because of position limits %s" % str(order))
            else:
                log.warn("Can't do full trade of %s because of position limits, can only do %s" %
                         (str(order), str(cut_down_order.trade)))

        return cut_down_order
    def submit_order(self, order: instrumentOrder):
        log = order.log_with_attributes(self.log)
        cut_down_order = self.adjust_order_for_position_limits(order)

        try:
            order_id = self.order_stack.put_order_on_stack(cut_down_order)
        except zeroOrderException:
            # we checked for zero already, which means that there is an existing order on the stack
            # An existing order of the same size
            log.warn("Ignoring new order as either zero size or it replicates an existing order on the stack")

        else:
            log.msg(
                    "Added order %s to instrument order stack with order id %d"
                    % (str(order), order_id),
                    instrument_order_id=order_id,
                )
    def _put_new_order_on_stack_when_no_existing_order(
        self, new_order: instrumentOrder, allow_zero_orders: bool = False
    ) -> int:
        # no current order for this instrument/strategy

        log = new_order.log_with_attributes(self.log)

        if new_order.is_zero_trade() and not allow_zero_orders:
            log_msg = "Zero orders not allowed"
            log.msg(log_msg)
            raise zeroOrderException(log_msg)

        log.msg("New order %s putting on %s" % (str(new_order), str(self)))

        order_id = self._put_order_on_stack_and_get_order_id(new_order)

        return order_id
def add_limit_price_to_a_direct_child_order(
    data: dataBlob, instrument_order: instrumentOrder, child_order: contractOrder
) -> contractOrder:
    """

    :param data: dataBlob
    :param instrument_order:
    :param child_order: will be modified
    :return: float
    """

    contract_to_match = instrument_order.limit_contract
    price_to_adjust = instrument_order.limit_price

    if contract_to_match is None or price_to_adjust is None:
        # No limit price so don't bother
        return child_order

    new_limit_price = calculate_adjusted_price_for_a_direct_child_order(
        data, child_order, contract_to_match, price_to_adjust
    )
    if new_limit_price is missing_data:
        # This is a serious problem
        # We can't possibly execute any part of the parent order
        log = instrument_order.log_with_attributes(data.log)
        log.critical(
            "Couldn't adjust limit price for order %s child %s going from %s to %s"
            % (
                str(instrument_order),
                str(child_order),
                contract_to_match,
                child_order.contract_date,
            )
        )
        return missing_order

    child_order.limit_price = new_limit_price

    return child_order
def add_reference_price_to_a_direct_child_order(
    data: dataBlob, instrument_order: instrumentOrder, child_order: contractOrder
):
    """

    :param data: dataBlob
    :param instrument_order:
    :param child_order: will be modified
    :return: child order
    """

    contract_to_match = instrument_order.reference_contract
    price_to_adjust = instrument_order.reference_price

    if contract_to_match is None or price_to_adjust is None:
        # No reference price so don't bother
        return child_order

    new_reference_price = calculate_adjusted_price_for_a_direct_child_order(
        data, child_order, contract_to_match, price_to_adjust
    )

    if new_reference_price is missing_data:
        log = instrument_order.log_with_attributes(data.log)
        log.warn(
            "Couldn't adjust reference price for order %s child %s going from %s to %s, can't do TCA"
            % (
                str(instrument_order),
                str(child_order),
                contract_to_match,
                child_order.contract_date,
            )
        )
        return child_order

    child_order.reference_price = new_reference_price

    return child_order
Example #16
0
    def add_instrument_and_list_of_contract_orders_to_stack(
        self,
            instrument_order: instrumentOrder,
            list_of_contract_orders: listOfOrders
    ):

        instrument_stack = self.instrument_stack
        contract_stack = self.contract_stack
        parent_log = instrument_order.log_with_attributes(self.log)

        # Do as a transaction: if everything doesn't go to plan can roll back
        # We lock now, and
        instrument_order.lock_order()
        try:
            parent_order_id = instrument_stack.put_order_on_stack(
                instrument_order, allow_zero_orders = True)

        except Exception as parent_order_error:
            parent_log.warn(
                    "Couldn't put parent order %s on instrument order stack error %s" %
                    (str(instrument_order), str(parent_order_error)))
            instrument_order.unlock_order()
            return None

        ## Parent order is now on stack in locked state
        ## We will unlock at the end, or during a rollback

        # 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
        list_of_child_order_ids =[]

        try:
            # Add parent order to children
            # This will only throw an error if the orders already have parents, which they shouldn't
            for child_order in list_of_contract_orders:
                child_order.parent = parent_order_id

            # this will return eithier -
            #     - a list of order IDS if all went well
            #     - an empty list if error and rolled back,
            #      - or an error something went wrong and couldn't rollback (the outer catch will try and rollback)
            list_of_child_order_ids = put_children_on_stack(child_stack = contract_stack,
                                                            parent_log=parent_log,
                                                            list_of_child_orders=list_of_contract_orders,
                                                            parent_order = instrument_order)

            if len(list_of_child_order_ids)==0:
                ## We had an error, but manged to roll back the children. Still need to throw an error so the parent
                ##   will be rolledback. But because the list_of_child_order_ids is probably zero
                ##   we won't try and rollback children in the catch statement
                raise Exception("Couldn't put child orders on stack, children were rolled back okay")

            ## All seems to have worked

            # still locked remember
            instrument_stack.unlock_order_on_stack(parent_order_id)
            instrument_stack.add_children_to_order_without_existing_children(
                parent_order_id, list_of_child_order_ids
            )


        except Exception as error_from_adding_child_orders:
            # okay it's gone wrong
            # Roll back parent order and possibly children
            # At this point list_of_child_order_ids will eithier be empty (if succesful rollback) or contain child ids

            rollback_parents_and_children_and_handle_exceptions(child_stack=contract_stack,
                                          parent_stack=instrument_stack,
                                          list_of_child_order_ids=list_of_child_order_ids,
                                          parent_order_id=parent_order_id,
                                        error_from_adding_child_orders=error_from_adding_child_orders,
                                                                parent_log=parent_log)

        # phew got there
        parent_log.msg("Added parent order with ID %d %s to stack" % (parent_order_id, str(instrument_order)))
        log_successful_adding(list_of_child_orders=list_of_contract_orders,
                              list_of_child_ids=list_of_child_order_ids,
                              parent_order=instrument_order,
                              parent_log=parent_log)