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