def historicalTicks(self, reqId, ticks, done): self._results[reqId] += [ HistoricalTick( datetime.datetime.fromtimestamp(t.time, datetime.timezone.utc), t.price, t.size) for t in ticks if t.size ] if done: self._endReq(reqId)
def _decode(self, fields): """ Decode the fields of the single response and call the appropriate callback handler. """ msgId = int(fields[0]) # bypass the ibapi decoder for ticks for more efficiency if msgId == 1: if self._priceSizeTick: _, _, reqId, tickType, price, size, _ = fields self._priceSizeTick(int(reqId), int(tickType), float(price), int(size)) return elif msgId == 2: _, _, reqId, tickType, size = fields self.wrapper.tickSize(int(reqId), int(tickType), int(size)) return elif msgId == 12: _, _, reqId, position, operation, side, price, size = fields self.wrapper.updateMktDepth(int(reqId), int(position), int(operation), int(side), float(price), int(size)) return elif msgId == 46: _, _, reqId, tickType, value = fields self.wrapper.tickString(int(reqId), int(tickType), value.decode()) return elif msgId == 90: _, reqId, barCount, date, open_, close, high, low, \ average, volume = fields bar = BarData(date.decode(), float(open_), float(high), float(low), float(close), float(volume), int(barCount), float(average)) self.wrapper.historicalDataUpdate(int(reqId), bar) return # snoop for nextValidId and managedAccounts response, # when both are in then the client is ready elif msgId == 9: _, _, validId = fields self._reqIdSeq = int(validId) if self._accounts: self._readyEvent.set() elif msgId == 15: _, _, accts = fields self._accounts = accts.decode().split(',') if self._reqIdSeq: self._readyEvent.set() # new features not yet in ibapi # https://interactivebrokers.github.io/tws-api/historical_time_and_sales.html elif msgId == 96: _, reqId, nTicks, *fields = fields ticks = [] for _ in range(int(nTicks)): time, _, price, size, *fields = fields tick = HistoricalTick(int(time), float(price), int(size)) ticks.append(tick) done = fields[0] == b'1' self.wrapper.historicalTicks(int(reqId), ticks, done) return elif msgId == 97: _, reqId, nTicks, *fields = fields ticks = [] for _ in range(int(nTicks)): time, mask, priceBid, priceAsk, sizeBid, sizeAsk, \ *fields = fields tick = HistoricalTickBidAsk(int(time), int(mask), float(priceBid), float(priceAsk), int(sizeBid), int(sizeAsk)) ticks.append(tick) done = fields[0] == b'1' self.wrapper.historicalTicksBidAsk(int(reqId), ticks, done) return elif msgId == 98: _, reqId, nTicks, *fields = fields ticks = [] for _ in range(int(nTicks)): time, mask, price, size, exchange, \ specialConditions, *fields = fields tick = HistoricalTickLast(int(time), int(mask), float(price), int(size), exchange.decode(), specialConditions.decode()) ticks.append(tick) done = fields[0] == b'1' self.wrapper.historicalTicksLast(int(reqId), ticks, done) return elif msgId == 99: _, reqId, tickType, time, *fields = fields if tickType in (1, 2): price, size, mask, exchange, specialConditions = fields mask = int(mask) attribs = TickAttrib(pastLimit=bool(mask & 1), unreported=bool(mask & 2)) self.wrapper.tickByTickAllLast(int(reqId), int(tickType), int(time), float(price), int(size), attribs, exchange, specialConditions.decode()) elif tickType == 3: bidPrice, askPrice, bidSize, askSize, mask = fields mask = int(mask) attribs = TickAttrib(bidPastLow=bool(mask & 1), askPastHigh=bool(mask & 2)) self.wrapper.tickByTickBidAsk(int(reqId), int(time), float(bidPrice), float(askPrice), int(bidSize), int(askSize), attribs) elif tickType == 4: midPoint = fields[0] self.wrapper.tickByTickMidPoint(int(reqId), int(time), float(midPoint)) return self.decoder.interpret(fields)
def _decode(self, fields): """ Decode the fields of the single response and call the appropriate callback handler. """ msgId = int(fields[0]) # bypass the abapi decoder for ticks for more efficiency if msgId == 1: if self._priceSizeTick: _, _, reqId, tickType, price, size, _ = fields self._priceSizeTick(int(reqId), int(tickType), float(price), int(size)) return elif msgId == 2: _, _, reqId, tickType, size = fields self.wrapper.tickSize(int(reqId), int(tickType), int(size)) return elif msgId == 12: _, _, reqId, position, operation, side, price, size = fields self.wrapper.updateMktDepth(int(reqId), int(position), int(operation), int(side), float(price), int(size)) return elif msgId == 46: _, _, reqId, tickType, value = fields self.wrapper.tickString(int(reqId), int(tickType), value.decode()) return elif msgId == 90: _, reqId, barCount, date, open_, close, high, low, \ average, volume = fields bar = BarData(date.decode(), float(open_), float(high), float(low), float(close), float(volume), int(barCount), float(average)) self.wrapper.historicalDataUpdate(int(reqId), bar) return # snoop for nextValidId and managedAccounts response, # when both are in then the client is ready elif msgId == 9: _, _, validId = fields self._reqIdSeq = int(validId) if self._accounts: self._readyEvent.set() elif msgId == 15: _, _, accts = fields self._accounts = accts.decode().split(',') if self._reqIdSeq: self._readyEvent.set() # new features not yet in ibapi elif msgId == 96: reqId, nTicks, *fields = fields ticks = [] for _ in range(nTicks): time, _, price, size, *fields = fields tick = HistoricalTick(int(time), float(price), int(size)) ticks.append(tick) done = fields[0] == b'1' self.wrapper.historicalTicks(int(reqId), ticks, done) return elif msgId == 97: reqId, nTicks, *fields = fields ticks = [] for _ in range(nTicks): time, mask, priceBid, priceAsk, sizeBid, sizeAsk, \ *fields = fields tick = HistoricalTickBidAsk(int(time), int(mask), float(priceBid), float(priceAsk), int(sizeBid), int(sizeAsk)) ticks.append(tick) done = fields[0] == b'1' self.wrapper.historicalTicksBidAsk(int(reqId), ticks, done) return elif msgId == 98: reqId, nTicks, *fields = fields ticks = [] for _ in range(int(nTicks)): time, mask, price, size, exchange, \ specialConditions, *fields = fields tick = HistoricalTickLast(int(time), int(mask), float(price), int(size), exchange.decode(), specialConditions.decode()) ticks.append(tick) done = fields[0] == b'1' self.wrapper.historicalTicksLast(int(reqId), ticks, done) return self.decoder.interpret(fields)