示例#1
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)
示例#2
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
示例#3
0
    def orderStatus(self,
                    orderId: int,
                    status: str,
                    filled: float,
                    remaining: float,
                    avgFillPrice: float,
                    permId: int,
                    parentId: int,
                    lastFillPrice: float,
                    clientId: int,
                    whyHeld: str,
                    mktCapPrice: float = 0.0):
        key = self.orderKey(clientId, orderId, permId)
        trade = self.trades.get(key)
        if trade:
            msg: Optional[str]
            oldStatus = trade.orderStatus.status
            new = dict(status=status,
                       filled=filled,
                       remaining=remaining,
                       avgFillPrice=avgFillPrice,
                       permId=permId,
                       parentId=parentId,
                       lastFillPrice=lastFillPrice,
                       clientId=clientId,
                       whyHeld=whyHeld,
                       mktCapPrice=mktCapPrice)
            curr = dataclassAsDict(trade.orderStatus)
            isChanged = curr != {**curr, **new}
            if isChanged:
                dataclassUpdate(trade.orderStatus, **new)
                msg = ''
            elif (status == 'Submitted' and trade.log
                  and trade.log[-1].message == 'Modify'):
                # order modifications are acknowledged
                msg = 'Modified'
            else:
                msg = None

            if msg is not None:
                logEntry = TradeLogEntry(self.lastTime, status, msg)
                trade.log.append(logEntry)
                self._logger.info(f'orderStatus: {trade}')
                self.ib.orderStatusEvent.emit(trade)
                trade.statusEvent.emit(trade)
                if status != oldStatus:
                    if status == OrderStatus.Filled:
                        trade.filledEvent.emit(trade)
                    elif status == OrderStatus.Cancelled:
                        trade.cancelledEvent.emit(trade)
        else:
            self._logger.error(
                'orderStatus: No order found for '
                'orderId %s and clientId %s', orderId, clientId)
示例#4
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
            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
            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)
示例#5
0
 def position(self, account: str, contract: Contract, posSize: float,
              avgCost: float):
     contract = Contract.create(**dataclassAsDict(contract))
     position = Position(account, contract, posSize, avgCost)
     positions = self.positions[account]
     if posSize == 0:
         positions.pop(contract.conId, None)
     else:
         positions[contract.conId] = position
     self._logger.info(f'position: {position}')
     results = self._results.get('positions')
     if results is not None:
         results.append(position)
     self.ib.positionEvent.emit(position)
示例#6
0
 def updatePortfolio(self, contract: Contract, posSize: float,
                     marketPrice: float, marketValue: float,
                     averageCost: float, unrealizedPNL: float,
                     realizedPNL: float, account: str):
     contract = Contract.create(**dataclassAsDict(contract))
     portfItem = PortfolioItem(contract, posSize, marketPrice, marketValue,
                               averageCost, unrealizedPNL, realizedPNL,
                               account)
     portfolioItems = self.portfolio[account]
     if posSize == 0:
         portfolioItems.pop(contract.conId, None)
     else:
         portfolioItems[contract.conId] = portfItem
     self._logger.info(f'updatePortfolio: {portfItem}')
     self.ib.updatePortfolioEvent.emit(portfItem)
示例#7
0
    async def startAsync(self):
        if self._proc:
            return
        self._logger.info('Starting')

        # expand paths
        d = util.dataclassAsDict(self)
        for k, v in d.items():
            if k.endswith('_PATH') or k.endswith('_INI'):
                d[k] = os.path.expanduser(v)
        if not d['TWS_CONFIG_PATH']:
            d['TWS_CONFIG_PATH'] = d['TWS_PATH']
        self.__dict__.update(**d)

        # run shell command
        ext = 'bat' if os.sys.platform == 'win32' else 'sh'
        cmd = f'{d["IBC_PATH"]}/Scripts/DisplayBannerAndLaunch.{ext}'
        env = {**os.environ, **d}
        self._proc = await asyncio.create_subprocess_exec(
            cmd, env=env, stdout=asyncio.subprocess.PIPE)
        self._monitor = asyncio.ensure_future(self.monitorAsync())
示例#8
0
 def execDetails(
         self, reqId: int, contract: Contract, execution: Execution):
     """
     This wrapper handles both live fills and responses to
     reqExecutions.
     """
     self._logger.info(f'execDetails {execution}')
     if execution.orderId == UNSET_INTEGER:
         # bug in TWS: executions of manual orders have unset value
         execution.orderId = 0
     trade = self.permId2Trade.get(execution.permId)
     if not trade:
         key = self.orderKey(
             execution.clientId, execution.orderId, execution.permId)
         trade = self.trades.get(key)
     if trade and contract == trade.contract:
         contract = trade.contract
     else:
         contract = Contract.create(**dataclassAsDict(contract))
     execId = execution.execId
     isLive = reqId not in self._futures
     time = self.lastTime if isLive else execution.time
     fill = Fill(contract, execution, CommissionReport(), time)
     if execId not in self.fills:
         # first time we see this execution so add it
         self.fills[execId] = fill
         if trade:
             trade.fills.append(fill)
             logEntry = TradeLogEntry(
                 time,
                 trade.orderStatus.status,
                 f'Fill {execution.shares}@{execution.price}')
             trade.log.append(logEntry)
             if isLive:
                 self._logger.info(f'execDetails: {fill}')
                 self.ib.execDetailsEvent.emit(trade, fill)
                 trade.fillEvent(trade, fill)
     if not isLive:
         self._results[reqId].append(fill)
示例#9
0
    async def startAsync(self):
        if self._proc:
            return
        self._logger.info('Starting')

        # map from field names to cmd arguments; key=(UnixArg, WindowsArg)
        args = dict(twsVersion=('', ''),
                    gateway=('--gateway', '/Gateway'),
                    tradingMode=('--mode=', '/Mode:'),
                    twsPath=('--tws-path=', '/TwsPath:'),
                    twsSettingsPath=('--tws-settings-path=', ''),
                    ibcPath=('--ibc-path=', '/IbcPath:'),
                    ibcIni=('--ibc-ini=', '/Config:'),
                    javaPath=('--java-path=', '/JavaPath:'),
                    userid=('--user='******'/User:'******'--pw=', '/PW:'),
                    fixuserid=('--fix-user='******'/FIXUser:'******'--fix-pw=', '/FIXPW:'))

        # create shell command
        cmd = [
            f'{self.ibcPath}\\scripts\\StartIBC.bat'
            if self._isWindows else f'{self.ibcPath}/scripts/ibcstart.sh'
        ]
        for k, v in util.dataclassAsDict(self).items():
            arg = args[k][self._isWindows]
            if v:
                if arg.endswith('=') or arg.endswith(':'):
                    cmd.append(f'{arg}{v}')
                elif arg:
                    cmd.append(arg)
                else:
                    cmd.append(str(v))

        # run shell command
        self._proc = await asyncio.create_subprocess_exec(
            *cmd, stdout=asyncio.subprocess.PIPE)
        self._monitor = asyncio.ensure_future(self.monitorAsync())
示例#10
0
 def __eq__(self, other):
     return (
         isinstance(other, Contract)
         and (
             self.conId and self.conId == other.conId
             or util.dataclassAsDict(self) == util.dataclassAsDict(other)))
示例#11
0
 def __eq__(self, other):
     if not isinstance(other, Contract):
         return False
     return (self.isHashable() and isinstance(other, Contract) and
             (self.conId == other.conId
              or util.dataclassAsDict(self) == util.dataclassAsDict(other)))