1

Running a simple data download request through IBKR TWS Python API Following one of the tutorials: https://www.youtube.com/watch?time_continue=1065&v=GmTPDzcko6k

Debugging yields that app.reqContractDetails(1, contract) returns None

Info on this issue seems limited

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract


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


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


def contractDetails(self, reqId, contractDetails):
    print("contractDetails: ", reqId, " ", contractDetails)


def main():
    app = TestApp()

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

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

    print (app.reqContractDetails(1, contract))

    app.run()
    app.reqContractDetails(2, contract)


if __name__ == "__main__":
    main()

Actual:

"C:\Users\Erix Liechtenstein\AppData\Local\Programs\Python\Python37-32\python.exe" "C:/TWS API/source/pythonclient/HelloWorld.py"
None
ERROR -1 2104 Market data farm connection is OK:eufarm
ERROR -1 2104 Market data farm connection is OK:cashfarm
ERROR -1 2104 Market data farm connection is OK:usopt
ERROR -1 2104 Market data farm connection is OK:usfarm
ERROR -1 2106 HMDS data farm connection is OK:ushmds

Update:

tried the following per brian's advice - still does nothing :(:

class TestApp(EWrapper, EClient):

    def __init__(self, addr, port, client_id):
       EWrapper.__init__(self)
       EClient.__init__(self, self)

       self.connect(addr, port, client_id)
       thread = Thread(target=self.run)
       thread.start()


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


def contractDetails(self, reqId, contractDetails):
    print("contractDetails: ", reqId, " ", contractDetails)


def main():
    app = TestApp("127.0.0.1", 4002, 0)
    app.run()

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

    app.reqContractDetails(1, contract)
    time.sleep(3)
    app.disconnect()

if __name__ == "__main__":
    main()

2 Answers2

2

The problem is that your client thread isn't waiting for the server's response. That is, the thread calling reqContractDetails needs to wait until the thread that runs contractDetails can finish.

A simple way to delay the main thread is to call time.sleep. The following code creates a contract and sets the thread to sleep for three seconds.

contract = Contract()
...
client.reqContractDetails(1, contract)
time.sleep(3)
client.disconnect()

If that doesn't fix your problem, you might want to try launching the thread from the constructor:

class TestApp(EWrapper, EClient):

    def __init__(self, addr, port, client_id):
       EWrapper.__init__(self)
       EClient.__init__(self, self)

       # Connect and launch thread
       self.connect(addr, port, client_id)
       thread = Thread(target=self.run)
       thread.start()

Good luck!

MatthewScarpino
  • 5,672
  • 5
  • 33
  • 47
  • thanks a lot for the advice - but didn't work for me unfortunately. I was able to get code from your other link to work though for some reason (I'm also very novice with python, usually code in C++) – erixliechtenstein Jul 28 '19 at 19:58
  • thanks - this saved me! does it vary network to network? – thomas.mac Feb 28 '20 at 02:05
0

I don't think that was my advice. Here is the exact code from the linked question with some comments.

Note that print (app.reqContractDetails(1, contract)) in your first code is printing a method call that doesn't return anything. The program is asynchronous meaning you ask for something and it will be returned later to a callback method, in this case reqContractDetails returns data later to contractDetails.

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)

        # this is where IB suggest starting your interaction with the API 
        # since the connection is established

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

        # now you can request data and wait for it in the other method
        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):
        # when IB's servers have time they will send the details.
        print("contractDetail: ", reqId, " ", contractDetails)

    def contractDetailsEnd(self, reqId:int):
        # when all details have been sent you will get this callback
        print("end, disconnecting")

        # so may as well disconnect so the socket doesn't hang
        self.disconnect()

def main():
    app = TestApp()

    app.connect("127.0.0.1", 4002, 0) #7496, 0)
    app.run()

if __name__ == "__main__":
    main()
brian
  • 10,619
  • 4
  • 21
  • 79
  • thank you so much! this worked - now am able to access historical data on top of this as well. your explanation was really helpful - really appreciate it! – erixliechtenstein Jul 29 '19 at 21:02