def _fromTDChildOrdertoIBOpenOrder(tdOrder, idConverter): originalTdOrderId = str(tdOrder['orderId']) int_orderId = idConverter.fromBrokerToIB(originalTdOrderId) security = _fromTDInstrumentToIBridgePySecurity(tdOrder['orderLegCollection'][0]['instrument']) contract = from_security_to_contract(security) orderStatus = OrderStatusConverter().fromTDtoIB(str(tdOrder['status'])) quantity = int(float(tdOrder['quantity'])) orderState = IBCpp.OrderState() orderState.status = orderStatus ibOrder = IBCpp.Order() ibOrder.orderId = int_orderId ibOrder.account = str(tdOrder['accountId']) ibOrder.action = str(tdOrder['orderLegCollection'][0]['instruction']) ibOrder.totalQuantity = quantity ibOrder.orderType = OrderTypeConverter().fromTDtoIB(str(tdOrder['orderType'])) ibOrder.tif = OrderTifConverter().fromTDtoIB(str(tdOrder['duration'])) if ibOrder.orderType == OrderType.LMT: ibOrder.lmtPrice = float(str(tdOrder['price'])) elif ibOrder.orderType == OrderType.STP: ibOrder.auxPrice = float(str(tdOrder['stopPrice'])) elif ibOrder.orderType == OrderType.STP_LMT: ibOrder.lmtPrice = float(str(tdOrder['price'])) ibOrder.auxPrice = float(str(tdOrder['stopPrice'])) elif ibOrder.orderType == OrderType.MKT: pass else: raise RuntimeError(__name__ + '::reqOneOrderWrapper: EXIT, cannot handle orderType=%s' % (ibOrder.orderType,)) ibOrder.orderRef = originalTdOrderId orderStatus, filledQuantity, remaining, price, whyHeld = OrderConverter().fromTDtoIBOrderStatus(tdOrder) return int_orderId, contract, ibOrder, orderState, security, orderStatus, filledQuantity, remaining, price, whyHeld
def reqPositionsWrapper(self): ans = self._tdClient.accounts(positions=True, orders=False) for accountCode in ans.keys(): # If there is no any position, just return if 'positions' not in ans[accountCode]['securitiesAccount']: self.simulatePositionEnd() return # If there are positions in the account positions = ans[accountCode]['securitiesAccount']['positions'] for position in positions: security = _fromTDInstrumentToIBridgePySecurity( position['instrument'], self._log) if security is None: continue contract = from_security_to_contract(security) longQuantity = int(float(position['longQuantity'])) shortQuantity = int(float(position['shortQuantity'])) if shortQuantity == 0: self.position(accountCode, contract, longQuantity, float(position['averagePrice'])) else: self.position(accountCode, contract, (-1) * abs(shortQuantity), float(position['averagePrice'])) self.simulatePositionEnd()
def reqPositions(self): self.log.debug(__name__ + '::reqPositions') for ct in self.aTrader.PORTFOLIO.positions: self.aTrader.position(self.aTrader.accountCode, from_security_to_contract(ct), self.aTrader.PORTFOLIO.positions.amount, self.aTrader.PORTFOLIO.positions.cost_basis) self.aTrader.positionEnd()
def reqPositionsWrapper(self): ans = self._robinhoodClient.get_all_positions() # ans = [{'symbol':'SPY', 'quantity':100, 'average_buy_price':99.9}] for position in ans: security = symbol(str(position['symbol'])) contract = from_security_to_contract(security) self.position(self._accountCode, contract, int(float(position['quantity'])), float(position['average_buy_price'])) self.simulatePositionEnd()
def fromRBtoIBOpenOrder(rbOrder, idConverter, accountCode): # IBCpp.Order().orderId must be an integer so that an integer orderId has to be created originalTdOrderId = str(rbOrder['id']) int_orderId = idConverter.fromBrokerToIB(originalTdOrderId) security = symbol(str(rbOrder['symbol'])) contract = from_security_to_contract(security) orderStatus = OrderStatusConverter().fromRBtoIB(str(rbOrder['state'])) quantity = int(float(rbOrder['quantity'])) orderState = IBCpp.OrderState() orderState.status = orderStatus ibOrder = IBCpp.Order() ibOrder.orderId = int_orderId ibOrder.account = accountCode ibOrder.action = OrderActionConverter().fromRBtoIB( str(rbOrder['side'])) # _robinhoodClient side : buy, sell ibOrder.totalQuantity = quantity ibOrder.orderType = OrderTypeConverter().fromRBtoIB( str(rbOrder['type']).lower(), str(rbOrder['trigger']).lower()) ibOrder.tif = OrderTifConverter().fromRBtoIB( str(rbOrder['time_in_force'])) if ibOrder.orderType == OrderType.LMT: ibOrder.lmtPrice = float(str(rbOrder['price'])) elif ibOrder.orderType == OrderType.STP: ibOrder.auxPrice = float(str(rbOrder['stop_price'])) elif ibOrder.orderType == OrderType.STP_LMT: ibOrder.lmtPrice = float(str(rbOrder['price'])) ibOrder.auxPrice = float(str(rbOrder['stop_price'])) elif ibOrder.orderType == OrderType.MKT: pass else: print(__name__ + '::reqOneOrderWrapper: EXIT, cannot handle orderType=%s' % (ibOrder.orderType, )) exit() return int_orderId, contract, ibOrder, orderState, security
def _send_req_to_server(self, activeRequests): """ pandas dataFrame: reqData All requests are defined in broker_client_factory::BrokerClientDefs """ self._log.debug(__name__ + '::_send_req_to_server: brokerClient=%s' % (self, )) for reqId in activeRequests.get_request_ids(): aRequest = activeRequests.get_by_reqId_otherwise_exit(reqId) self._allRequests[ reqId] = aRequest # move to allRequest which stores all requests aRequest.status = ReqAttr.Status.SUBMITTED reqType = aRequest.reqType param = aRequest.param self._log.debug('%s' % (aRequest, )) if reqType == 'reqPositions': self.reqPositionsWrapper() elif reqType == 'reqConnect': ans = self.isConnectedWrapper() if ans: aRequest.status = ReqAttr.Status.COMPLETED else: ans = self.connectWrapper() if ans: aRequest.status = ReqAttr.Status.COMPLETED elif reqType == 'reqCurrentTime': self.reqCurrentTimeWrapper() elif reqType == 'reqAllOpenOrders': self.reqAllOpenOrdersWrapper() elif reqType == 'reqOneOrder': ibpyOrderId = param['orderId'] self.reqOneOrderWrapper(ibpyOrderId) elif reqType == 'reqAccountUpdates': accountCode = param['accountCode'] subscribe = param['subscribe'] self.reqAccountUpdatesWrapper( subscribe, accountCode) # Request to update account info elif reqType == 'reqAccountSummary': group = param['group'] tag = param['tag'] self.reqAccountSummaryWrapper(reqId, group, tag) elif reqType == 'reqIds': self.reqIdsWrapper() elif reqType == 'reqHeartBeats': self.reqHeartBeatsWrapper() elif reqType == 'reqHistoricalData': security = param['security'] endTime = param['endTime'] goBack = param['goBack'] barSize = param['barSize'] whatToShow = param['whatToShow'] useRTH = param['useRTH'] formatDate = 2 # param['formatDate'] Send epoch to IB server all the time. It is easier to handle self.reqHistoricalDataWrapper( reqId, from_security_to_contract(security), endTime, goBack, barSize, whatToShow, useRTH, formatDate) elif reqType == 'reqMktData': security = param['security'] genericTickList = param['genericTickList'] snapshot = param['snapshot'] # put security and reqID in dictionary for fast access # it is keyed by both security and reqId self._realTimePriceRequestedList.addReqIdAndStrSecurity( reqId, security.full_print()) self.reqMktDataWrapper( reqId, from_security_to_contract(security), genericTickList, snapshot) # Send market data request to IB server elif reqType == 'cancelMktData': security = param['security'] reqId = self._realTimePriceRequestedList.findByStrSecurity( security.full_print()) self.cancelMktDataWrapper(reqId) self._realTimePriceRequestedList.deleteReqIdAndStrSecurity( reqId, security.full_print()) elif reqType == 'reqRealTimeBars': security = param['security'] barSize = param['barSize'] whatToShow = param['whatToShow'] useRTH = param['useRTH'] self._realTimePriceRequestedList.addReqIdAndStrSecurity( reqId, security.full_print()) self.reqRealTimeBarsWrapper( reqId, from_security_to_contract(security), barSize, whatToShow, useRTH) # Send market dataFromServer request to IB server elif reqType == 'placeOrder': """ Ending label is IBCpp::callBacks::orderStatus """ contract = param['contract'] order = param['order'] self.placeOrderWrapper(contract, order, aRequest) # When the order is placed, IB will callback orderStatus # In broker_client_factory::CallBack::orderStatus, IBridgePy, set ending flag for this request and assign ibpyOrderId # self.activeRequests.get_by_reqId_otherwise_exit(reqId).returnedResult = str_ibpyOrderId # self.activeRequests.get_by_reqId_otherwise_exit(reqId).status = ReqAttr.Status.COMPLETED elif reqType == 'modifyOrder': """ Ending label is IBCpp::callBacks::orderStatus """ ibpyOrderId = param['ibpyOrderId'] contract = param['contract'] order = param['order'] int_orderId = order.orderId self._idConverter.verifyRelationship(int_orderId, ibpyOrderId) self._log.info( 'ModifyOrder ibpyOrderId=%s security=%s order=%s' % (ibpyOrderId, print_IBCpp_contract(contract), print_IBCpp_order(order))) self.modifyOrderWrapper(contract, order, aRequest) elif reqType == 'reqContractDetails': security = param['security'] self.reqContractDetailsWrapper( reqId, from_security_to_contract(security)) elif reqType == 'calculateImpliedVolatility': security = param['security'] optionPrice = float(param['optionPrice']) underPrice = float(param['underPrice']) # put security and reqID in dictionary for fast access # it is keyed by both security and reqId self._realTimePriceRequestedList.addReqIdAndStrSecurity( reqId, security.full_print()) self.calculateImpliedVolatilityWrapper( reqId, from_security_to_contract(security), optionPrice, underPrice) elif reqType == 'reqScannerSubscription': subscription = param['subscription'] self.reqScannerSubscriptionWrapper(reqId, subscription) # Need to upgrade IBCpp # tagValueList = self.end_check_list.loc[idx, 'reqData'].param['tagValueList'] # self.reqScannerSubscription(reqId, subscription, tagValueList) # self._log.debug(__name__ + '::_send_req_to_server:reqScannerSubscription:' # + ' subscription=' + subscription.full_print() + ' tagValueList=' + str(tagValueList)) elif reqType == 'cancelScannerSubscription': tickerId = param['tickerId'] self.cancelScannerSubscriptionWrapper(tickerId) elif reqType == 'cancelOrder': """ Ending label is IBCpp::callBacks::error: errorCode = 10148 Do not use orderStatus callback to follow up on cancelOrder request because the status can be either Canceled Or PendingCancel """ ibpyOrderId = param['ibpyOrderId'] int_orderId = self._idConverter.fromBrokerToIB(ibpyOrderId) param['int_orderId'] = int_orderId self.cancelOrderWrapper(ibpyOrderId) elif reqType == 'reqScannerParameters': self.reqScannerParametersWrapper() else: self._log.error( __name__ + '::_send_req_to_server: EXIT, cannot handle reqType=%s' % (reqType, )) self.end()
def create_order(orderId, accountCode, security, amount, orderDetails, createdTime, ocaGroup=None, ocaType=None, transmit=None, parentId=None, orderRef='', outsideRth=False, hidden=False): contract = from_security_to_contract(security) order = IBCpp.Order() if hidden: if contract.exchange == ExchangeName.ISLAND: order.hidden = True else: print(__name__ + '::create_order: EXIT, only ISLAND accept hidden orders') exit() if amount > 0: order.action = 'BUY' elif amount < 0: order.action = 'SELL' order.orderId = orderId order.account = accountCode order.totalQuantity = int(abs(amount)) # int only order.orderType = orderDetails.orderType # LMT, MKT, STP order.tif = orderDetails.tif order.orderRef = str(orderRef) order.outsideRth = outsideRth if ocaGroup is not None: order.ocaGroup = ocaGroup if ocaType is not None: order.ocaType = ocaType if transmit is not None: order.transmit = transmit if parentId is not None: order.parentId = parentId if orderDetails.orderType in ['MKT', 'MOC']: pass elif orderDetails.orderType == 'LMT': order.lmtPrice = orderDetails.limit_price elif orderDetails.orderType == 'STP': order.auxPrice = orderDetails.stop_price elif orderDetails.orderType == 'STP LMT': order.lmtPrice = orderDetails.limit_price order.auxPrice = orderDetails.stop_price elif orderDetails.orderType == 'TRAIL LIMIT': if orderDetails.trailing_amount is not None: order.auxPrice = orderDetails.trailing_amount # trailing amount if orderDetails.trailing_percent is not None: order.trailingPercent = orderDetails.trailing_percent order.trailStopPrice = orderDetails.stop_price if order.action == 'SELL': order.lmtPrice = orderDetails.stop_price - orderDetails.limit_offset elif order.action == 'BUY': order.lmtPrice = orderDetails.stop_price + orderDetails.limit_offset elif orderDetails.orderType == 'TRAIL': if orderDetails.trailing_amount is not None: order.auxPrice = orderDetails.trailing_amount # trailing amount if orderDetails.trailing_percent is not None: order.trailingPercent = orderDetails.trailing_percent if orderDetails.stop_price is not None: order.trailStopPrice = orderDetails.stop_price else: print(__name__ + '::create_order: EXIT,Cannot handle orderType=%s' % (orderDetails.orderType, )) an_order = IbridgePyOrder(requestedContract=contract, requestedOrder=order, createdTime=createdTime) return an_order