Search code examples
pythonapiinteractive-brokers

How to get historical stock price data from interactive brokers API?


I want to use IBAPI to get historical stock data. My code does not work and returns nothings. Can anybody help me edit the code? Thanks

from ibapi import client
from ibapi import wrapper
import datetime
from ibapi.contract import Contract
from ibapi.common import BarData

# ! [socket_init]
class App(wrapper.EWrapper,client.EClient):
    def __init__(self):
        wrapper.EWrapper.__init__(self)
        client.EClient.__init__(self, wrapper=self)


 #Build a sample contract
contract = Contract();
contract.symbol = "9005.T";
contract.secType = "STK";
contract.currency = "JPY";
contract.exchange = "SMART";


app = App()
app.connect(host='localhost',port=7497, clientId=3)
print(app.isConnected())
queryTime = (datetime.datetime.today() - datetime.timedelta(days=180)).strftime("%Y%m%d %H:%M:%S")
print(app.reqHistoricalData(4102, contract, queryTime,"1 M", "1 day", "MIDPOINT", 1, 1, False, []))
queryTime = (datetime.datetime.today() - datetime.timedelta(days=180)).strftime("%Y%m%d %H:%M:%S")
print(app.historicalData(4102,BarData))


OUTPUT:
True
None
None

I tried to read the source code. But I found it is quite difficult to understand for me. Other posts showed the answer that appears not relevant to the newest api version.


Solution

  • Here's what I would do.

    class App(wrapper.EWrapper,client.EClient): I would only subclass EClient if I wanted to override any of it's methods. I don't use python very much but it's like that in other languages.

    Inside the class App you need to override the methods you are interested in like historicalData

    After app.connect you must call app.run() to start it's message reader thread. Once that thread takes control it will block in your program so you must do program flow asynchronously.

    I will put numbers in comments so you see the flow.

    from ibapi.client import EClient
    from ibapi.wrapper import EWrapper
    from ibapi.contract import Contract
    from ibapi.common import BarData
    
    import datetime
    
    class MyWrapper(EWrapper):
    
        def nextValidId(self, orderId:int):
            #4 first message received is this one
            print("setting nextValidOrderId: %d", orderId)
            self.nextValidOrderId = orderId
            #5 start requests here
            self.start()
    
        def historicalData(self, reqId:int, bar: BarData):
            #7 data is received for every bar
            print("HistoricalData. ReqId:", reqId, "BarData.", bar)
    
        def historicalDataEnd(self, reqId: int, start: str, end: str):
            #8 data is finished
            print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to", end)
            #9 this is the logical end of your program
            app.disconnect()
            print("finished")
    
        def error(self, reqId, errorCode, errorString):
            # these messages can come anytime.
            print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
    
        def start(self):
            queryTime = (datetime.datetime.today() - datetime.timedelta(days=180)).strftime("%Y%m%d %H:%M:%S")
    
            fx = Contract()
            fx.secType = "CASH" 
            fx.symbol = "USD"
            fx.currency = "JPY"
            fx.exchange = "IDEALPRO"
    
            #6 request data, using fx since I don't have Japanese data
            app.reqHistoricalData(4102, fx, queryTime,"1 M", "1 day", "MIDPOINT", 1, 1, False, [])
    
    app = EClient(MyWrapper()) #1 create wrapper subclass and pass it to EClient
    app.connect("127.0.0.1", 7497, clientId=123) #2 connect to TWS/IBG
    app.run() #3 start message thread