Ejemplo n.º 1
0
 def placeOrder(self, contract: Contract, order: Order) -> Trade:
     """
     Place a new order or modify an existing order.
     Returns an Trade that is kept live updated with
     status changes, fills, etc.
     """
     orderId = order.orderId or self.client.getReqId()
     self.client.placeOrder(orderId, contract, order)
     now = datetime.datetime.now(datetime.timezone.utc)
     if not isinstance(order, Order):
         order = Order(**order.__dict__)
     key = (self.wrapper.clientId, orderId)
     trade = self.wrapper.trades.get(key)
     if trade:
         # this is a modification of an existing order
         assert trade.orderStatus.status not in OrderStatus.DoneStates
         logEntry = TradeLogEntry(now,
                 trade.orderStatus.status, 'Modify')
         trade.log.append(logEntry)
         _logger.info(f'placeOrder: Modify order {trade}')
     else:
         # this is a new order
         order.orderId = orderId
         orderStatus = OrderStatus(status=OrderStatus.PendingSubmit)
         logEntry = TradeLogEntry(now, orderStatus.status, '')
         trade = Trade(
                 contract, order, orderStatus, [], [logEntry])
         self.wrapper.trades[key] = trade
         _logger.info(f'placeOrder: New order {trade}')
     return trade
Ejemplo n.º 2
0
    def openOrder(self, orderId, contract, order, orderState):
        """
        This wrapper is called to:

        * feed in open orders at startup;
        * feed in open orders or order updates from other clients and TWS
          if clientId=master id;
        * feed in manual orders and order updates from TWS if clientId=0.
        """
        if order.whatIf:
            # response to whatIfOrder
            orderState = OrderState(**orderState.__dict__)
            self._endReq(order.orderId, orderState)
        else:
            if order.softDollarTier:
                order.softDollarTier = SoftDollarTier(
                    **order.softDollarTier.__dict__)
            key = self.orderKey(order.clientId, order.orderId, order.permId)
            trade = self.trades.get(key)
            if trade:
                trade.order.update(**order.__dict__)
            else:
                contract = self._getContract(contract)
                order = Order(**order.__dict__)
                orderStatus = OrderStatus(status=orderState.status)
                trade = Trade(contract, order, orderStatus, [], [])
                self.trades[key] = trade
                self._logger.info(f'openOrder: {trade}')
            results = self._results.get('openOrders')
            if results is None:
                self._ib.openOrderEvent.emit(trade)
            else:
                # response to reqOpenOrders
                results.append(order)
Ejemplo n.º 3
0
    def openOrder(self, orderId, contract, order, orderState):
        """
        This wrapper is called to:

        * feed in open orders at startup;
        * feed in open orders or order updates from other clients and TWS
          if clientId=master id;
        * feed in manual orders and order updates from TWS if clientId=0;
        * handle openOrders and allOpenOrders responses.
        """
        if order.whatIf:
            # response to whatIfOrder
            self._endReq(order.orderId, orderState)
        else:
            key = self.orderKey(order.clientId, order.orderId, order.permId)
            trade = self.trades.get(key)
            # ignore '?' values in the order
            d = {k: v for k, v in order.dict().items() if v != '?'}
            if trade:
                trade.order.update(**d)
            else:
                contract = Contract.create(**contract.dict())
                order = Order(**d)
                orderStatus = OrderStatus(status=orderState.status)
                trade = Trade(contract, order, orderStatus, [], [])
                self.trades[key] = trade
                self._logger.info(f'openOrder: {trade}')
            self.permId2Trade.setdefault(order.permId, trade)
            results = self._results.get('openOrders')
            if results is None:
                self.ib.openOrderEvent.emit(trade)
            else:
                # response to reqOpenOrders or reqAllOpenOrders
                results.append(order)
Ejemplo n.º 4
0
    def fill_trade(trade: Trade, exec_id: int, date: pd.datetime,
                   price: float) -> Trade:
        quantity = trade.order.totalQuantity
        execution = Execution(execId=exec_id,
                              time=date,
                              acctNumber='',
                              exchange=trade.contract.exchange,
                              side=trade.order.action,
                              shares=quantity,
                              price=price,
                              permId=trade.order.permId,
                              orderId=trade.order.orderId,
                              cumQty=quantity,
                              avgPrice=price,
                              lastLiquidity=quantity)
        commission = CommissionReport()
        fill = Fill(time=date,
                    contract=trade.contract,
                    execution=execution,
                    commissionReport=commission)
        trade.fills.append(fill)
        trade.orderStatus = OrderStatus(status='Filled',
                                        filled=quantity,
                                        remaining=0,
                                        avgFillPrice=price,
                                        lastFillPrice=price)
        trade.log.append(
            TradeLogEntry(time=date,
                          status=trade.orderStatus,
                          message=f'Fill @{price}'))

        return trade
Ejemplo n.º 5
0
 def completedOrder(self, contract, order, orderState):
     contract = Contract.create(**contract.dict())
     orderStatus = OrderStatus(status=orderState.status)
     trade = Trade(contract, order, orderStatus, [], [])
     self._results['completedOrders'].append(trade)
     if order.permId not in self.permId2Trade:
         self.trades[order.permId] = trade
         self.permId2Trade[order.permId] = trade
Ejemplo n.º 6
0
 def completedOrder(self, contract: Contract, order: Order,
                    orderState: OrderState):
     contract = Contract.create(**dataclassAsDict(contract))
     orderStatus = OrderStatus(orderId=order.orderId,
                               status=orderState.status)
     trade = Trade(contract, order, orderStatus, [], [])
     self._results['completedOrders'].append(trade)
     if order.permId not in self.permId2Trade:
         self.trades[order.permId] = trade
         self.permId2Trade[order.permId] = trade
Ejemplo n.º 7
0
 def log_commission(self, trade: Trade, fill: Fill,
                    comm_report: CommissionReport, reason: str):
     """
     Get trades that have all CommissionReport filled and log them.
     """
     # bug in ib_insync sometimes causes trade to have fills for
     # unrelated transactions, permId uniquely identifies order
     comms = [fill.commissionReport for fill in trade.fills
              if fill.commissionReport.execId != ''
              and fill.execution.permId == trade.order.permId]
     fills = [fill for fill in trade.fills
              if fill.execution.permId == trade.order.permId]
     if trade.isDone() and (len(comms) == len(fills)):
         self.log_trade(trade, comms, reason)
Ejemplo n.º 8
0
    def openOrder(
            self, orderId: int, contract: Contract, order: Order,
            orderState: OrderState):
        """
        This wrapper is called to:

        * feed in open orders at startup;
        * feed in open orders or order updates from other clients and TWS
          if clientId=master id;
        * feed in manual orders and order updates from TWS if clientId=0;
        * handle openOrders and allOpenOrders responses.
        """
        if order.whatIf:
            # response to whatIfOrder
            if orderState.commissionCurrency:
                self._endReq(order.orderId, orderState)
        else:
            key = self.orderKey(order.clientId, order.orderId, order.permId)
            trade = self.trades.get(key)
            if trade:
                trade.order.permId = order.permId
                trade.order.totalQuantity = order.totalQuantity
                trade.order.lmtPrice = order.lmtPrice
                trade.order.auxPrice = order.auxPrice
                trade.order.orderType = order.orderType
            else:
                # ignore '?' values in the order
                order = Order(**{
                    k: v for k, v in dataclassAsDict(order).items()
                    if v != '?'})
                contract = Contract.create(**dataclassAsDict(contract))
                orderStatus = OrderStatus(
                    orderId=orderId, status=orderState.status)
                trade = Trade(contract, order, orderStatus, [], [])
                self.trades[key] = trade
                self._logger.info(f'openOrder: {trade}')
            self.permId2Trade.setdefault(order.permId, trade)
            results = self._results.get('openOrders')
            if results is None:
                self.ib.openOrderEvent.emit(trade)
            else:
                # response to reqOpenOrders or reqAllOpenOrders
                results.append(order)

        # make sure that the client issues order ids larger then any
        # order id encountered (even from other clients) to avoid
        # "Duplicate order id" error
        self.ib.client.updateReqId(orderId + 1)
Ejemplo n.º 9
0
    def log_commission(self, trade: Trade, fill: Fill,
                       comm_report: CommissionReport, reason: str):
        """
        Get trades that have all CommissionReport filled and log them.
        """
        log.debug(f'logging commission for trade: {trade}')
        log.debug(f'trade isDone: {trade.isDone()}')
        # bug in ib_insync sometimes causes trade to have fills for
        # unrelated transactions
        comms = [
            fill.commissionReport for fill in trade.fills
            if fill.commissionReport.execId != ''
            and fill.contract == trade.contract
        ]
        log.debug(f'comms: {comms}')
        log.debug(
            f'len(comms): {len(comms)}, len(trade.fills): {len(trade.fills)}')

        if trade.isDone() and (len(comms) == len(trade.fills)):
            self.log_trade(trade, comms, reason)
Ejemplo n.º 10
0
 def openOrder(self, orderId, contract, order, orderState):
     if order.whatIf:
         # response to whatIfOrder
         orderState = OrderState(**orderState.__dict__)
         self._endReq(orderId, orderState)
     else:
         contract = Contract(**contract.__dict__)
         order = Order(**order.__dict__)
         orderStatus = OrderStatus(status=orderState.status)
         if order.softDollarTier:
             order.softDollarTier = SoftDollarTier(
                     **order.softDollarTier.__dict__)
         trade = Trade(contract, order, orderStatus, [], [])
         key = (order.clientId, orderId)
         if key not in self.trades:
             self.trades[key] = trade
             _logger.info(f'openOrder: {trade}')
         results = self._results.get('openOrders')
         if results is not None:
             # response to reqOpenOrders
             results.append(order)
Ejemplo n.º 11
0
 def placeOrder(self, contract, order):
     orderId = order.orderId or next(self.id)
     now = self.market.date
     trade = self.market.get_trade(order)
     if trade:
         # this is a modification of an existing order
         assert trade.orderStatus.status not in OrderStatus.DoneStates
         logEntry = TradeLogEntry(now, trade.orderStatus.status, 'Modify')
         trade.log.append(logEntry)
         trade.modifyEvent.emit(trade)
         self.orderModifyEvent.emit(trade)
     else:
         # this is a new order
         assert order.totalQuantity != 0, 'Order quantity cannot be zero'
         order.orderId = orderId
         order.permId = orderId
         orderStatus = OrderStatus(status=OrderStatus.PendingSubmit,
                                   remaining=order.totalQuantity)
         logEntry = TradeLogEntry(now, orderStatus, '')
         trade = Trade(contract, order, orderStatus, [], [logEntry])
         self.newOrderEvent.emit(trade)
         self.market.append_trade(trade)
     return trade