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)
def execDetails(self, reqId, contract, execution): """ This wrapper handles both live fills and responses to reqExecutions. """ if execution.orderId == UNSET_INTEGER: # bug in TWS: executions of manual orders have unset value execution.orderId = 0 key = self.orderKey(execution.clientId, execution.orderId, execution.permId) trade = self.trades.get(key) or self.permId2Trade.get(execution.permId) if trade and contract == trade.contract: contract = trade.contract else: contract = Contract.create(**contract.dict()) execId = execution.execId execution.time = util.parseIBDatetime(execution.time). \ astimezone(datetime.timezone.utc) 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)
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
def _getContract(self, ibContract): """ Create contract that corresponds to the given ibapi contract. """ contract = Contract.create(**ibContract.__dict__) if ibContract.comboLegs: contract.comboLegs = [ ComboLeg(**leg.__dict__) for leg in ibContract.comboLegs ] return contract
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
def position(self, account, contract, posSize, avgCost): contract = Contract.create(**contract.dict()) 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)
def updatePortfolio(self, contract, posSize, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, account): contract = Contract.create(**contract.dict()) 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)
def _getContract(self, ibContract): """ Return existing shared contract or newly created contract that corresponds to the given ibapi contract. """ conId = ibContract.conId contract = self.conId2Contract.get(conId) if not contract: contract = Contract.create(**ibContract.__dict__) if ibContract.comboLegs: contract.comboLegs = [ComboLeg(**leg.__dict__) for leg in ibContract.comboLegs] if contract.isHashable(): self.conId2Contract[conId] = contract return contract
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)