Reputation: 331
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()
Upvotes: 1
Views: 959
Reputation: 10969
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()
Upvotes: 0
Reputation: 5936
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!
Upvotes: 2