Just figured how to use IB API from spyder. With threads and queues. Let me know if anyone interested to know.
#%% from ibapi.client import EClient from ibapi.wrapper import EWrapper from ibapi.contract import Contract from threading import Thread from ibapi.common import BarData from queue import Queue import pandas as pd import matplotlib.pyplot as plt class MyIB(EWrapper, EClient): def __init__(self): EClient.__init__(self, self) def error(self, reqId, errorCode: int, errorString: str): global myErrorQ myErrorQ.put(errorString) def contractDetails(self, reqId: int, contractDetails): print(contractDetails) def nextValidId(self, orderId: int): print(f'next valid order id {orderId}') def historicalData(self, reqId: int, bar: BarData): global myHistDataQ myHistDataQ.put(bar) def historicalDataEnd(self, reqId: int, start: str, end: str): print('data end') myErrorQ = Queue(maxsize = 0) myHistDataQ = Queue(maxsize = 0) my_ib_app = MyIB() my_ib_app.connect('127.0.0.1', 7497, 0) thread = Thread(target=my_ib_app.run, daemon=True) thread.start() #%% my_ib_app.done = True my_ib_app.disconnect() #%% thread.isAlive() #%% contract = Contract() contract.symbol = 'AAPL' contract.secType = 'STK' contract.exchange = 'SMART' contract.currency = 'USD' #%% my_ib_app.reqContractDetails(1, contract) #%% my_ib_app.reqHistoricalData(411, contract, '20200801 00:00:00', '180 D', '1 day', 'TRADES', 1, 1, False, []) #%% while not myErrorQ.empty(): print(myErrorQ.get()) #%% hData = pd.DataFrame(columns=('Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Average', 'BarCount')) hData = hData.reindex(columns=['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Average', 'BarCount']) #%% while not myHistDataQ.empty(): bar = myHistDataQ.get() hData = hData.append({'Date': bar.date, 'Open': bar.open, 'High': bar.high, 'Low': bar.low, 'Close': bar.close,'Volume': bar.volume, 'Average': bar.average, 'BarCount': bar.barCount}, ignore_index=True) #%% bar = myHistDataQ.get() hData = hData.append({'Date': bar.date, 'Open': bar.open, 'High': bar.high, 'Low': bar.low, 'Close': bar.close,'Volume': bar.volume, 'Average': bar.average, 'BarCount': bar.barCount}, ignore_index=True)
Queue gets filled by the listener thread and the data can be pulled in the while loop. Let me know if any confusion. Be sure to disconnect before clearing the variables, as the listener thread will still be running.