0

I have a python script that connects to an Interactive Brokers API and retrieves security contract information as below:

from ibapi.client import *
from ibapi.wrapper import *
import time


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

    def contractDetails(self, reqId: int, contractDetails: ContractDetails):
        print(f"contract details: {contractDetails}")

    def contractDetailsEnd(self, reqId: int):
        print("End of contractDetails")
        self.disconnect()
        

def main():
    try:            
        app = TestApp()

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

        myContract = Contract()
        # myContract.conId = "503837634"
        myContract.symbol = "/ES"
        myContract.exchange = "CME"
        myContract.secType = "FUT"
        myContract.currency = "USD"
        myContract.localSymbol = 'ESZ3'
        #myContract.primaryExchange = "ISLAND"        

        time.sleep(3)

        app.reqContractDetails(1, myContract)
        app.run()

    except KeyboardInterrupt:
        print('Session completed')
        app.disconnect()
        
if __name__ == "__main__":
    main()

In cases where I need to break the process (e.g., the program doesn't end naturally because a contract with specified details isn't found), I've set it up using a try/catch and KeyboardInterrupt exception. This doesn't seem to get picked up so killing the process also kills the established connection and I'm forced to log in again manually.

I've considered using the signal module but there doesn't seem to be a natural way to apply code snippets I've found to allow me to close the connection (app.disconnect()) before exiting.

For example, I can implement a version of the linked to answer, as below, but there's no way to pass my app instance to be disconnected by the handler before exiting.

def handler(sig, frame):
    print('Exception detected...session completed')
    sys.exit(0)

def main():    
    app = TestApp()

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

    myContract = Contract()
    # myContract.conId = "503837634"
    myContract.symbol = '/ES'
    myContract.exchange = 'CME'
    myContract.secType = "FUT"
    myContract.currency = "USD"
    myContract.localSymbol = 'ESZ3'
    #myContract.primaryExchange = "ISLAND"        

    time.sleep(3)

    app.reqContractDetails(1, myContract)
    app.run()   

    signal.signal(signal.SIGINT, handler)
    signal.pause()

    app.disconnect()
    
if __name__ == "__main__":
    main()

Can anyone shed some light on how to accomplish this?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Chris
  • 1,401
  • 4
  • 17
  • 28

1 Answers1

2

According to the docs, the EWrapper::error is an error handler that can receive error code of -1 meaning that there's no error, and a positive error code in case of an actual error. I think the idea is that you don't actually terminate your connection with disconnect. Instead, you should:

  • create a thread as it's suggested by the docs
  • periodically check this error code to see how the request is doing. If it indicates an error (contract not found?) then terminate the thread, but not the whole connection.

I can't really do more without writing up something myself too - which might be a good idea actually.

Ant tell me, what happens if you don't terminate the thing? Does it wait for ever, or timeouts?

  • thanks, will take a look. yeah, it waits forever...haven't waited long enough to see it timeout. – Chris Jun 26 '23 at 19:48