IBpy Ewrapper methods don't work only EClientSocket

1.1k Views Asked by At

Hi I'm trying to use IBPy as per here: https://github.com/blampe/IbPy and it is reacting very weirdly. Methods calling upon the EClientSocket class returns data but any EClientSocket method calling to EWrapper or EWrapper methods returns None and/or has issues. I realize IB's API is asynchronous at its source in Java but I can't figure out where it's breaking. I have DDE/Socket connections enabled in TWS, and even a clientId(100) specified.

I am using the IB TWS demo from this link: https://www.interactivebrokers.com/en/index.php?f=553&twsdemo=1 and Python 3.4. My version of IBpy is installed using pip install ib-api.

Here is my code:

from ib.opt import ibConnection, Connection, message
from ib.ext.Contract import Contract
from ib.ext.EWrapper import EWrapper
from ib.ext.EClientSocket import EClientSocket
from ib.ext.ExecutionFilter import ExecutionFilter
from ib.ext.Order import Order
import time
from time import sleep

def reply_handler(msg):
print("Reply:", msg)

def create_contract(symbol, sec_type, exch, prim_exch, curr):
contract = Contract()
contract.m_symbol = symbol
contract.m_sec_type = sec_type
contract.m_exch = exch
contract.m_prim_exch = prim_exch
contract.m_curr = curr
return contract

if __name__ == "__main__":
tws_conn = ibConnection(host='localhost', port=7496, clientId=100)
tws_conn.connect()

tws_conn.registerAll(reply_handler)

contract = Contract()
contract.m_symbol = 'GE'
contract.m_exchange = 'SMART'
contract.m_localSymbol = 'GE'
contract.m_primaryExch = 'SMART'
contract.m_currency = 'USD'
contract.m_secType = 'STK'

#EClientSocket only methods
reply_handler(tws_conn.isConnected())
reply_handler(tws_conn.serverVersion())
reply_handler(tws_conn.TwsConnectionTime())

#EWrapper methods or calls to EWrapper methods
reply_handler(tws_conn.reqCurrentTime())
reply_handler(tws_conn.reqAccountUpdates(1, ''))
reply_handler(tws_conn.currentTime())
reply_handler(tws_conn.reqMktData(1, contract, '', False))
reply_handler(tws_conn.contractDetails(1, contract))

Here is the console output when the script is ran:

Server Version: 76

TWS Time at connection:20150529 23:29:54 PST

Reply: True

Reply: 76

Reply: 20150529 23:29:54 PST

Reply: None

Reply: None

Reply: currentTime time=None

Reply: None

Reply: None

Reply: contractDetails reqId=1, contractDetails=ib.ext.Contract.Contract object at 0x000000000287FB70

Reply: None

You can see that after the 3rd method the last EClientSocket call it stops working. I've looked into IB's and IBpy's documentation and this particular issue is not mentioned anywhere as well on Stackoverflow. Thanks for any help!

2

There are 2 best solutions below

0
On BEST ANSWER

It's a bit confusing for you to wrap your calls in reply_handler(). It's registered with the tws_conn object to get all replies, that's all you need to do. Anything that's not a socket request like tws_conn.isConnected() just needs to be in a print(), which is all reply_handler does, but it makes it look like a reply from EReader - it's not.

Also in tws_conn.contractDetails... you forgot req.

from ib.opt import ibConnection, Connection, message
from ib.ext.Contract import Contract
from ib.ext.EWrapper import EWrapper
from ib.ext.EClientSocket import EClientSocket

def reply_handler(msg):
    print("Reply:", msg)

tws_conn = ibConnection(host='localhost', port=7496, clientId=1)
tws_conn.registerAll(reply_handler)
tws_conn.connect()


contract = Contract()
contract.m_symbol = 'GE'
contract.m_exchange = 'SMART'
contract.m_currency = 'USD'
contract.m_secType = 'STK'

#EClientSocket only methods
reply_handler(tws_conn.isConnected())
reply_handler(tws_conn.serverVersion())
reply_handler(tws_conn.TwsConnectionTime())

#EWrapper methods or calls to EWrapper methods
tws_conn.reqCurrentTime()
tws_conn.reqContractDetails(1, contract)
#tws_conn.disconnect()#don't forget at some point
2
On

Ok so I figured it out. It was ridiculously simple and obtuse beyond belief.

Apparently if you make a call to IBs API and don't put a pause after each call, nothing returns from the handler. This isn't anywhere I could find in the API docs.

So time.sleep(1) as the last line in a method or the next line after calling a method works perfectly.