Пример #1
0
    def commit_order_execution(self, order, date_time, fill_info):
        price = fill_info.price
        quantity = fill_info.quantity

        if order.is_a_buy_order:
            cost = price * quantity * -1
            assert (cost < 0)
            shares_delta = quantity
        elif order.is_a_sell_order:
            cost = price * quantity
            assert (cost > 0)
            shares_delta = quantity * -1
        else:  # Unknown action
            assert False

        commission = self.commission.calculate(order, price, quantity)
        cost -= commission
        resulting_cash = self.cash + cost

        # Check that we're ok on cash after the commission.
        if resulting_cash >= 0 or self.__allow_negative_cash:

            # Update the order before updating internal state since add_execution_info may raise.
            # add_execution_info should switch the order state.
            order_execution_info = broker.OrderExecutionInfo(
                price, quantity, commission, date_time)
            order.add_execution_info(order_execution_info)

            # Commit the order execution.
            self.__cash = resulting_cash
            updated_shares = order.instrument_traits.round_quantity(
                self.shares(order.instrument) + shares_delta)
            if updated_shares == 0:
                del self.__shares[order.instrument]
            else:
                self.__shares[order.instrument] = updated_shares

            # Let the strategy know that the order was filled.
            self.__fill_strategy.onOrderFilled(self, order)

            # Notify the order update
            if order.is_filled:
                self._unregister_order(order)
                self.notify_order_event(
                    broker.OrderEvent(order, broker.OrderEvent.Type.FILLED,
                                      order_execution_info))
            elif order.is_partially_filled:
                self.notify_order_event(
                    broker.OrderEvent(order,
                                      broker.OrderEvent.Type.PARTIALLY_FILLED,
                                      order_execution_info))
            else:
                assert False
        else:
            self.__logger.debug(
                "Not enough cash to fill %s order [%s] for %d share/s" %
                (order.instrument, order.id, order.remaining))
Пример #2
0
    def cancel_order(self, order):
        active_order = self.__active_orders.get(order.id)
        if active_order is None:
            raise Exception("The order is not active anymore")
        if active_order.is_filled:
            raise Exception("Can't cancel order that has already been filled")

        self._unregister_order(active_order)
        active_order.switch_state(broker.BaseOrder.State.CANCELED)
        self.notify_order_event(
            broker.OrderEvent(active_order, broker.OrderEvent.Type.CANCELED,
                              "User requested cancellation"))
Пример #3
0
    def __post_process_order(self, order, bar_):
        # For non-GTC orders and daily (or greater) bars we need to check if orders should expire right now
        # before waiting for the next bar.
        if not order.good_till_canceled:
            expired = False
            if self.__barfeed.frequency >= const.Frequency.DAY:
                expired = bar_.date_time.date(
                ) >= order.accepted_date_time.date()

            # Cancel the order if it will expire in the next bar.
            if expired:
                self._unregister_order(order)
                order.switch_state(broker.BaseOrder.State.CANCELED)
                self.notify_order_event(
                    broker.OrderEvent(order, broker.OrderEvent.Type.CANCELED,
                                      "Expired"))
Пример #4
0
    def __pre_process_order(self, order, bar_):
        ret = True

        # For non-GTC orders we need to check if the order has expired.
        if not order.good_till_canceled:
            expired = bar_.date_time.date() > order.accepted_date_time.date()

            # Cancel the order if it is expired.
            if expired:
                ret = False
                self._unregister_order(order)
                order.switch_state(broker.BaseOrder.State.CANCELED)
                self.notify_order_event(
                    broker.OrderEvent(order, broker.OrderEvent.Type.CANCELED,
                                      "Expired"))

        return ret
Пример #5
0
    def __on_bars_Impl(self, order, bars):
        # IF WE'RE DEALING WITH MULTIPLE INSTRUMENTS WE SKIP ORDER PROCESSING IF THERE IS NO BAR FOR THE ORDER'S
        # INSTRUMENT TO GET THE SAME BEHAVIOUR AS IF WERE BE PROCESSING ONLY ONE INSTRUMENT.
        bar_ = bars.bar(order.instrument)
        if bar_ is not None:
            # Switch from SUBMITTED -> ACCEPTED
            if order.is_submitted:
                order.setAcceptedDateTime(bar_.date_time)
                order.switch_state(broker.BaseOrder.State.ACCEPTED)
                self.notify_order_event(
                    broker.OrderEvent(order, broker.OrderEvent.Type.ACCEPTED,
                                      None))

            if order.is_active:
                # This may trigger orders to be added/removed from __active_orders.
                self.__process_order(order, bar_)
            else:
                # If an order is not active it should be because it was canceled in this same loop and it should
                # have been removed.
                assert order.is_canceled
                assert (order not in self.__active_orders)