Search code examples
pythonib-api

Python IBAPI reqContractDetails won't return result when run second time


I want to request contract details and it worked the first time I run the code, but when I press run again, it won't return anything. It will work if I quit TWS and pycharm and try again I am new to python and don't understand how it works overall, pls help.

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import *
from ibapi.contract import *
from ContractSamples import ContractSamples


class TestApp(EClient, EWrapper):
    def __init__(self):
        EClient.__init__(self, self)

    def error(self, reqId:TickerId, errorCode:int, errorString:str):
        print("Error: ", reqId, "", errorCode, "", errorString)

    def contractDetails(self, reqId:int, contractDetails:ContractDetails):
        print("contractDetail: ", reqId, " ", contractDetails)


def main():
    app = TestApp()

    app.connect("127.0.0.1", 7496, 0)

    contract = Contract()
    contract.symbol = "AAPL"
    contract.secType = "STK"
    contract.exchange = "SMART"
    contract.currency = "USD"
    contract.primaryExchange = "NASDAQ"

    app.reqContractDetails(10, contract)

    app.run()


if __name__ == "__main__":
    main()

No error msg, just no result: "Process finished with exit code 0".


Solution

  • app.run() starts a thread to read from the socket. Your program never stops running so is always connected to TWS. Try clicking on the data menu button in TWS. It shows all your connections. You will see client 0 stays connected. Obviously closing pyCharm kills the program.

    You also request the contract details before the program is ready. You should wait for nextValidId and then send the request. When the data has been recieved, then you can stop your program and it will free up the clientId for future connections. Here is how I would change your program.

    from ibapi.client import EClient
    from ibapi.wrapper import EWrapper
    from ibapi.common import *
    from ibapi.contract import *
    from ContractSamples import ContractSamples
    
    
    class TestApp(EClient, EWrapper):
        def __init__(self):
            EClient.__init__(self, self)
    
        def nextValidId(self, orderId:int):
            print("id", orderId)
            contract = Contract()
            contract.symbol = "IBKR"
            contract.secType = "STK"
            contract.exchange = "SMART"
            contract.currency = "USD"
            contract.primaryExchange = "NASDAQ"
    
            self.reqContractDetails(10, contract)
    
        def error(self, reqId:TickerId, errorCode:int, errorString:str):
            print("Error: ", reqId, "", errorCode, "", errorString)
    
        def contractDetails(self, reqId:int, contractDetails:ContractDetails):
            print("contractDetail: ", reqId, " ", contractDetails)
    
        def contractDetailsEnd(self, reqId:int):
            print("end, disconnecting")
            self.disconnect()
    
    def main():
        app = TestApp()
    
        app.connect("127.0.0.1", 7496, 0)
        app.run()
    
    if __name__ == "__main__":
        main()