# Simple contract for DELL dell = Contract() dell.exchange = "SMART" dell.symbol = "DELL" dell.secType = "STK" dell.currency = "USD" today = datetime.today() print "Requesting historical data for %s" % dell.symbol # Request some historical data. tws.reqHistoricalData( 1, #tickerId, dell, #contract, today.strftime("%Y%m%d %H:%M:%S %Z"), #endDateTime, "1 W", #durationStr, "1 day", #barSizeSetting, "TRADES", #whatToShow, 0, #useRTH, 1 #formatDate ) print "\n=====================================================================" print " History requested, waiting for TWS responses" print "=====================================================================\n" print "******************* Press ENTER to quit when done *******************\n" raw_input() print "\nDisconnecting..."
# Simple contract for DELL dell = Contract() dell.exchange = "SMART" dell.symbol = "DELL" dell.secType = "STK" dell.currency = "USD" today = datetime.today() print "Requesting historical data for %s" % dell.symbol # Request some historical data. tws.reqHistoricalData( 1, #tickerId, dell, #contract, today.strftime("%Y%m%d %H:%M:%S %Z"), #endDateTime, "1 W", #durationStr, "1 day", #barSizeSetting, "TRADES", #whatToShow, 0, #useRTH, 1 #formatDate ) print "\n=====================================================================" print " History requested, waiting for TWS responses" print "=====================================================================\n" print "******************* Press ENTER to quit when done *******************\n" raw_input() print "\nDisconnecting..." tws.eDisconnect() time.sleep(1)
# Connect to tws running on localhost if not tws.eConnect("", 7496, 42): raise RuntimeError('Failed to connect to TWS') today = datetime.today() for index, row in contractlist.iterrows(): print 'Index:', index, ', Sym:', row['sym'] #self.reqMktData(index, create_contract(row['sym']), '233', False) # Request some historical data. tws.reqHistoricalData( index, # tickerId, create_contract(row['sym']), # contract, today.strftime("%Y%m%d %H:%M:%S %Z"), # endDateTime, "1 W", # durationStr, "1 day", # barSizeSetting, "TRADES", # whatToShow, useRTH, # useRTH, 1, # formatDate None # chartOptions ) print("\n====================================================================") print(" History requested, waiting %ds for TWS responses" % WAIT_TIME) print("====================================================================\n") try: callback.got_history.wait(timeout=WAIT_TIME) print symbols except KeyboardInterrupt:
else: filename = "{}_{}_{}.csv".format(contract_to_string(contract), barsize.replace(" ", ""), datatype) output_file = open(filename, 'w') s = "Receiving {} batches of historical data...".format(num_requests) if num_requests > 1 and pacing: s += " {} seconds remaining".format( (num_requests - num_batches_received) * pacing) logging.info(s) prev_last_time = endtime if tws.exited: sys.exit(2) tws.reqHistoricalData(0, contract, endtime.strftime("%Y%m%d %H:%M:%S"), duration, barsize, datatype, rth_only, 1) historical_data_received.wait() if output_file.tell() > 0: # file not empty logging.info("Reversing the output file...") output_file.close() with open(filename, 'r') as input_file: lines = input_file.readlines() lines.reverse() with open(filename, 'w') as output_file: for line in lines: output_file.write(line) else:
def error(self, id, errCode, errString): global clientid global tws global connection_state global pacing global last_time global cooldowntime s = "IB[{}]: {}".format(errCode, errString) if id > -1: s += " (ID: {})".format(id) logging.debug(s) if errCode == ErrorCode.clientid_in_use: logging.info( "Client ID {} in use, reconnecting ...".format(clientid)) clientid += 1 tws = EPosixClientSocket(self) tws.eConnect("", 7496, clientid) elif errCode == ErrorCode.md_connection_ok: logging.info("IB[{}]: {}".format(errCode, errString)) api_started.set() # TODO: use a better string here! elif errCode == ErrorCode.historical_data_error and "Historical data request pacing violation" in errString: logging.info( "Historical data pacing violation: retrying last batch and start using pacing between data requests..." ) logging.info(errString) if not pacing: pacing = 10 dt = prev_last_time.strftime("%Y%m%d %H:%M:%S") logging.info("Cooling down for {} seconds...".format(cooldowntime)) sleep(cooldowntime) cooldowntime += 15 # sometimes we just need to cool down for a longer time tws.reqHistoricalData(0, contract, dt, duration, barsize, datatype, rth_only, 1) elif errCode == ErrorCode.historical_data_error and "invalid step" in errString: logging.info("IB[{}]: {}".format(errCode, errString)) historical_data_received.set() elif errCode == ErrorCode.historical_data_error and "HMDS query returned no data" in errString: logging.info("IB[{}]: {}".format(errCode, errString)) historical_data_received.set() elif (errCode == ErrorCode.historical_data_error and "Trader Workstation exited" in errString) or \ errCode == ErrorCode.cannot_connect_to_tws: logging.info("IB[{}]: {}".format(errCode, errString)) tws.exited = True historical_data_received.set() # requesting historical data from period too long time ago elif errCode == ErrorCode.error_validating_request and "Historical data queries on this contract requesting any data earlier than" in errString: dt = prev_last_time.strftime(dt_format) logging.info( "IB cannot provide data from period ending {}, it's too far back in the history." .format(dt)) historical_data_received.set() elif errCode == ErrorCode.error_validating_request: s = "IB[{}]: {}".format(errCode, errString) if id > -1: s += " (ID: {})".format(id) logging.fatal(s) historical_data_received.set() elif errCode == ErrorCode.connection_lost: # TODO: some logic to retry after connection has been momentarily lost, and eventually give up... logging.info("Connection lost, saving data end aborting...") if not output_file: sys.exit(ExitCode.error_can_continue) historical_data_received.set() elif errCode == ErrorCode.no_security_def_found: logging.info("IB[{}]: {}".format(errCode, errString)) if not output_file: sys.exit(ExitCode.error_can_continue) historical_data_received.set() else: s = "IB[{}]: {}".format(errCode, errString) if id > -1: s += " (ID: {})".format(id) logging.info(s)
def error(self, id, errCode, errString): global clientid global tws global connection_state global pacing global last_time global cooldowntime s = "IB[{}]: {}".format(errCode, errString) if id > -1: s += " (ID: {})".format(id) logging.debug(s) if errCode == ErrorCode.clientid_in_use: logging.info("Client ID {} in use, reconnecting ...".format(clientid)) clientid += 1 tws = EPosixClientSocket(self) tws.eConnect("", 7496, clientid) elif errCode == ErrorCode.md_connection_ok: logging.info("IB[{}]: {}".format(errCode, errString)) api_started.set() # TODO: use a better string here! elif errCode == ErrorCode.historical_data_error and "Historical data request pacing violation" in errString: logging.info("Historical data pacing violation: retrying last batch and start using pacing between data requests...") logging.info(errString) if not pacing: pacing = 10 dt = prev_last_time.strftime("%Y%m%d %H:%M:%S") logging.info("Cooling down for {} seconds...".format(cooldowntime)) sleep(cooldowntime) cooldowntime += 15 # sometimes we just need to cool down for a longer time tws.reqHistoricalData(0, contract, dt, duration, barsize, datatype, rth_only, 1) elif errCode == ErrorCode.historical_data_error and "invalid step" in errString: logging.info("IB[{}]: {}".format(errCode, errString)) historical_data_received.set() elif errCode == ErrorCode.historical_data_error and "HMDS query returned no data" in errString: logging.info("IB[{}]: {}".format(errCode, errString)) historical_data_received.set() elif (errCode == ErrorCode.historical_data_error and "Trader Workstation exited" in errString) or \ errCode == ErrorCode.cannot_connect_to_tws: logging.info("IB[{}]: {}".format(errCode, errString)) tws.exited = True historical_data_received.set() # requesting historical data from period too long time ago elif errCode == ErrorCode.error_validating_request and "Historical data queries on this contract requesting any data earlier than" in errString: dt = prev_last_time.strftime(dt_format) logging.info("IB cannot provide data from period ending {}, it's too far back in the history.".format(dt)) historical_data_received.set() elif errCode == ErrorCode.error_validating_request: s = "IB[{}]: {}".format(errCode, errString) if id > -1: s += " (ID: {})".format(id) logging.fatal(s) historical_data_received.set() elif errCode == ErrorCode.connection_lost: # TODO: some logic to retry after connection has been momentarily lost, and eventually give up... logging.info("Connection lost, saving data end aborting...") if not output_file: sys.exit(ExitCode.error_can_continue) historical_data_received.set() elif errCode == ErrorCode.no_security_def_found: logging.info("IB[{}]: {}".format(errCode, errString)) if not output_file: sys.exit(ExitCode.error_can_continue) historical_data_received.set() else: s = "IB[{}]: {}".format(errCode, errString) if id > -1: s += " (ID: {})".format(id) logging.info(s)
filename = args.o else: filename = "{}_{}_{}.csv".format(contract_to_string(contract), barsize.replace(" ", ""), datatype) output_file = open(filename, 'w') s = "Receiving {} batches of historical data...".format(num_requests) if num_requests > 1 and pacing: s += " {} seconds remaining".format((num_requests - num_batches_received) * pacing) logging.info(s) prev_last_time = endtime if tws.exited: sys.exit(2) tws.reqHistoricalData(0, contract, endtime.strftime("%Y%m%d %H:%M:%S"), duration, barsize, datatype, rth_only, 1) historical_data_received.wait() if output_file.tell() > 0: # file not empty logging.info("Reversing the output file...") output_file.close() with open(filename, 'r') as input_file: lines = input_file.readlines() lines.reverse() with open(filename, 'w') as output_file: for line in lines: output_file.write(line)
# Connect to tws running on localhost tws.eConnect("", 7496, 46, poll_interval=1) accountNumber = '' contract = Contract() contract.exchange = "SMART" contract.symbol = "TOT" contract.secType = "STK" #contract.right = "PUT" contract.currency = "USD" #contract.secType = 'OPT' #contract.strike = 24 #contract.expiry = '20121116' today = datetime.today() #tws.reqAccountUpdates(1, accountNumber) #tws.reqAccountUpdates(0, accountNumber) callback.histTickerID = contract.symbol tws.reqHistoricalData( 1, #tickerId, contract, #contract, datetime(2012, 11, 2, 23, 59, 59).strftime("%Y%m%d %H:%M:%S"), #endDateTime, "2 D", #durationStr, "1 min", #barSizeSetting, "TRADES", #whatToShow, 0, #useRTH, 1 #formatDate )
class SwigIBClient(EWrapper): '''Callback object passed to TWS, these functions will be called directly by TWS. ''' def __init__(self, port=4001, client_id=12): super(SwigIBClient, self).__init__() self.tws = EPosixClientSocket(self) self.port = port self.client_id = client_id self.got_history = Event() self.got_contract = Event() self.got_err = Event() self.order_filled = Event() self.order_ids = Queue() def execDetails(self, id, contract, execution): pass def managedAccounts(self, openOrderEnd): pass ### Order def nextValidId(self, validOrderId): '''Capture the next order id''' self.order_ids.put(validOrderId) def orderStatus(self, id, status, filled, remaining, avgFillPrice, permId, parentId, lastFilledPrice, clientId, whyHeld): print(("Order #%s - %s (filled %d, remaining %d, avgFillPrice %f," "last fill price %f)") % (id, status, filled, remaining, avgFillPrice, lastFilledPrice)) if remaining <= 0: self.order_filled.set() def openOrder(self, orderID, contract, order, orderState): print("Order opened for %s" % contract.symbol) def openOrderEnd(self): pass def commissionReport(self, commissionReport): print 'Commission %s %s P&L: %s' % (commissionReport.currency, commissionReport.commission, commissionReport.realizedPNL) ### Historical data def historicalData(self, reqId, date, open, high, low, close, volume, barCount, WAP, hasGaps): if date[:8] == 'finished': print("History request complete") self.got_history.set() else: date = datetime.strptime(date, "%Y%m%d").strftime("%d %b %Y") print(("History %s - Open: %s, High: %s, Low: %s, Close: " "%s, Volume: %d") % (date, open, high, low, close, volume)) ### Contract details def contractDetailsEnd(self, reqId): print("Contract details request complete, (request id %i)" % reqId) def contractDetails(self, reqId, contractDetails): print("Contract details received (request id %i):" % reqId) print("callable: %s" % contractDetails.callable) print("category: %s" % contractDetails.category) print("contractMonth: %s" % contractDetails.contractMonth) print("convertible: %s" % contractDetails.convertible) print("coupon: %s" % contractDetails.coupon) print("industry: %s" % contractDetails.industry) print("liquidHours: %s" % contractDetails.liquidHours) print("longName: %s" % contractDetails.longName) print("marketName: %s" % contractDetails.marketName) print("minTick: %s" % contractDetails.minTick) print("nextOptionPartial: %s" % contractDetails.nextOptionPartial) print("orderTypes: %s" % contractDetails.orderTypes) print("priceMagnifier: %s" % contractDetails.priceMagnifier) print("putable: %s" % contractDetails.putable) if contractDetails.secIdList is not None: for secId in contractDetails.secIdList: print("secIdList: %s" % secId) else: print("secIdList: None") print("subcategory: %s" % contractDetails.subcategory) print("tradingHours: %s" % contractDetails.tradingHours) print("timeZoneId: %s" % contractDetails.timeZoneId) print("underConId: %s" % contractDetails.underConId) print("evRule: %s" % contractDetails.evRule) print("evMultiplier: %s" % contractDetails.evMultiplier) contract = contractDetails.summary print("\nContract Summary:") print("exchange: %s" % contract.exchange) print("symbol: %s" % contract.symbol) print("secType: %s" % contract.secType) print("currency: %s" % contract.currency) print("tradingClass: %s" % contract.tradingClass) if contract.comboLegs is not None: for comboLeg in contract.comboLegs: print("comboLegs: %s - %s" % (comboLeg.action, comboLeg.exchange)) else: print("comboLegs: None") print("\nBond Values:") print("bondType: %s" % contractDetails.bondType) print("couponType: %s" % contractDetails.couponType) print("cusip: %s" % contractDetails.cusip) print("descAppend: %s" % contractDetails.descAppend) print("issueDate: %s" % contractDetails.issueDate) print("maturity: %s" % contractDetails.maturity) print("nextOptionDate: %s" % contractDetails.nextOptionDate) print("nextOptionType: %s" % contractDetails.nextOptionType) print("notes: %s" % contractDetails.notes) print("ratings: %s" % contractDetails.ratings) print("validExchanges: %s" % contractDetails.validExchanges) self.got_contract.set() ### Error def error(self, id, errCode, errString): if errCode == 165 or (errCode >= 2100 and errCode <= 2110): print("TWS warns %s" % errString) elif errCode == 502: print('Looks like TWS is not running, ' 'start it up and try again') sys.exit() elif errCode == 501: print("TWS reports error in client: %s" % errString) elif errCode >= 1100 and errCode < 2100: print("TWS reports system error: %s" % errString) elif errCode == 321: print("TWS complaining about bad request: %s" % errString) else: super(SwigIBClient, self).error(id, errCode, errString) self.got_err.set() def winError(self, msg, lastError): print("TWS reports API error: %s" % msg) self.got_err.set() def pyError(self, type, val, tb): sys.print_exception(type, val, tb) ### def connect(self): if not self.tws.eConnect("", self.port, self.client_id): raise RuntimeError('Failed to connect to TWS') def disconnect(self): print("\nDisconnecting...") self.tws.eDisconnect() def create_contract(self): # Simple contract for GOOG contract = Contract() contract.exchange = "SMART" contract.symbol = "GOOG" contract.secType = "STK" contract.currency = "USD" return contract def request_contract_details(self, contract): today = datetime.today() print("Requesting contract details...") # Perform the request self.tws.reqContractDetails( 42, # reqId, contract, # contract, ) print("\n====================================================================") print(" Contract details requested, waiting %ds for TWS responses" % WAIT_TIME) print("====================================================================\n") try: self.got_contract.wait(timeout=WAIT_TIME) except KeyboardInterrupt: pass finally: if not self.got_contract.is_set(): print('Failed to get contract within %d seconds' % WAIT_TIME) def request_hist_data(self, contract): today = datetime.today() print("Requesting historical data for %s" % contract.symbol) # Request some historical data. self.tws.reqHistoricalData( 2, # tickerId, contract, # contract, today.strftime("%Y%m%d %H:%M:%S %Z"), # endDateTime, "1 W", # durationStr, "1 day", # barSizeSetting, "TRADES", # whatToShow, 0, # useRTH, 1 # formatDate ) print("\n====================================================================") print(" History requested, waiting %ds for TWS responses" % WAIT_TIME) print(" History requested, waiting %ds for TWS responses" % WAIT_TIME) print("====================================================================\n") try: self.got_history.wait(timeout=WAIT_TIME) except KeyboardInterrupt: pass finally: if not self.got_history.is_set(): print('Failed to get history within %d seconds' % WAIT_TIME) def subscribe_market_data(self, contract): pass def unsubscribe_market_data(self, contract): pass def place_order(self, contract): print('Waiting for valid order id') order_id = self.order_ids.get(timeout=WAIT_TIME) if not order_id: raise RuntimeError('Failed to receive order id after %ds' % WAIT_TIME) # Order details algoParams = TagValueList() algoParams.append(TagValue("componentSize", "3")) algoParams.append(TagValue("timeBetweenOrders", "60")) algoParams.append(TagValue("randomizeTime20", "1")) algoParams.append(TagValue("randomizeSize55", "1")) algoParams.append(TagValue("giveUp", "1")) algoParams.append(TagValue("catchUp", "1")) algoParams.append(TagValue("waitForFill", "1")) algoParams.append(TagValue("startTime", "20110302-14:30:00 GMT")) algoParams.append(TagValue("endTime", "20110302-21:00:00 GMT")) order = Order() order.action = 'BUY' order.lmtPrice = 140 order.orderType = 'LMT' order.totalQuantity = 10 order.algoStrategy = "AD" order.tif = 'DAT' order.algoParams = algoParams # order.transmit = False print("Placing order for %d %s's (id: %d)" % (order.totalQuantity, contract.symbol, order_id)) # Place the order self.tws.placeOrder( order_id, # orderId, contract, # contract, order # order ) print("\n====================================================================") print(" Order placed, waiting %ds for TWS responses" % WAIT_TIME) print("====================================================================\n") print("Waiting for order to be filled..") try: self.order_filled.wait(WAIT_TIME) except KeyboardInterrupt: pass finally: if not self.order_filled.is_set(): print('Failed to fill order')
class TwsClient(object): logger = logging.getLogger(__name__) """Represents Interactive Broker's TWS.""" _next_request_id = 0 def __init__(self, client_id: int): """Initialises an instance for the specified client id.""" self._client_id = client_id self._requests_lock = threading.Lock() self._requests = {} self._wrapper = _MulticastWrapper(self._requests, self._requests_lock) self._socket = EPosixClientSocket(self._wrapper) @property def client_id(self): return self._client_id def connect(self, host: str = "", port: int = 7496) -> Disconnecting: """Connects to TWS.""" if not self._socket.eConnect(host, port, self.client_id): raise RuntimeError("Client[%d] Failed to connect at Host: %s, Port: %d" % \ (self._client_id, host, port)) TwsClient.logger.info("Client[%d] connected at Host: %s, Port: %d" % (self._client_id, host, port)) return Disconnecting(self._socket) def reqHistoricalData(self, handler, contract: Contract, end_datetime: str, duration: str = "1 D", bar_size: BarSize = BarSize.Min1, what_to_show: WhatToShow = WhatToShow.Trades, use_rth: UseRth = UseRth.WithinTradingHour, format_date: FormatDate = FormatDate.InString): """""" request = self._createRequest(RequestType.HistoricalData, handler) self._socket.reqHistoricalData(request.request_id, contract, end_datetime, duration, bar_size.value, what_to_show.value, use_rth.value, format_date.value) return request def reqMarketData(self, handler, contract: Contract, generic_tick: str, snapshot: bool = False): """""" request = self._createRequest(RequestType.MarketData, handler) self._socket.reqMktData(request.request_id, contract, generic_tick, snapshot) return request def reqOpenOrders(self): return self._socket.reqOpenOrders() def cancelRequest(self, request: Request): """""" req_id = request.request_id with self._requests_lock: if self._requests.get(req_id) != request: return False del self._requests[req_id] try: { RequestType.HistoricalData: lambda: self._socket.cancelHistoricalData(req_id), RequestType.MarketData: lambda: self.cancelMktData(req_id) }[request.request_type]() except KeyError: raise LookupError( "Client[%d] Reqest: %d - Unable to cancel unknown request type [%s]." % (self._client_id, req_id, request.request_type.value)) def cancelMktData(self, req_id): TwsClient.logger.info('MarketData request[%d] is cancelled.' % req_id) self._socket.cancelMktData(req_id) def _createRequest(self, req_type: RequestType, handler) -> Request: TwsClient._next_request_id += 1 req_id = TwsClient._next_request_id request = Request(self, req_type, req_id, handler) with self._requests_lock: self._requests[req_id] = request return request