Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to eliminate (or suppress from console) Interactive Brokers error when downloading data with Python API

I wrote the code below to read information from my accounts at Interactive Brokers:

# Interactive Brokers functions to import data

def read_positions(): #read all accounts positions and return DataFrame with information

    from ibapi.client import EClient 
    from ibapi.wrapper import EWrapper
    from ibapi.common import TickerId
    import pandas as pd

    class ib_class(EWrapper, EClient): 
        def __init__(self): 
            EClient.__init__(self, self)
            self.all_positions = pd.DataFrame([], columns = ['Account','Symbol', 'Quantity', 'Average Cost'])

        def position(self, account, contract, pos, avgCost):
            index = str(account)+str(contract.symbol)
            self.all_positions.loc[index]=account,contract.symbol,pos,avgCost

        def error(self, reqId:TickerId, errorCode:int, errorString:str):
            if reqId > -1:
                print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)

        def positionEnd(self):
            super().positionEnd()
            self.disconnect()

    ib_api = ib_class() 
    ib_api.connect("127.0.0.1", 7496, 0) 
    ib_api.reqPositions()
    current_positions = ib_api.all_positions
    ib_api.run()

    return(current_positions)


def read_navs(): #read all accounts NAVs

    from ibapi.client import EClient 
    from ibapi.wrapper import EWrapper
    from ibapi.common import TickerId
    import pandas as pd

    class ib_class(EWrapper, EClient): 
        def __init__(self): 
            EClient.__init__(self, self)
            self.all_accounts = pd.DataFrame([], columns = ['reqId','Account', 'Tag', 'Value' , 'Currency'])

        def accountSummary(self, reqId, account, tag, value, currency):
            if tag == 'NetLiquidationByCurrency':
                index = str(account)
                self.all_accounts.loc[index]=reqId, account, tag, value, currency

        def error(self, reqId:TickerId, errorCode:int, errorString:str):
            if reqId > -1:
                print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)

        def accountSummaryEnd(self, reqId:int):
                super().accountSummaryEnd(reqId)
                self.disconnect()

    ib_api = ib_class() 
    ib_api.connect("127.0.0.1", 7496, 0) 
    ib_api.reqAccountSummary(9001,"All","$LEDGER")
    current_nav = ib_api.all_accounts
    ib_api.run()

    return(current_nav)

If I call the two functions read_positions() or read_navs() I get the results I want, on DataFrame variables. However, I get an error message (on the console) that reads:

"OSError: [WinError 10038] An operation was attempted on something that is not a socket".

Before the error message itself, I get a lot of error-related messages:

unhandled exception in EReader thread Traceback (most recent call last): File "C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\reader.py", line 34, in run data = self.conn.recvMsg() File "C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py", line 99, in recvMsg buf = self._recvAllMsg() File "C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py", line 119, in _recvAllMsg buf = self.socket.recv(4096)

The helpdesk from IB refuses to answer my question: how do I either avoid this error message or suppress it? I don't know if it is something I'm doing wrong or if this is a bug on their API. As long as I can avoid this junk printed on my console, I will be OK. Any guidance is much appreciated.

like image 761
Rational-IM Avatar asked Feb 03 '26 09:02

Rational-IM


2 Answers

Matt's answer above is correct: it was an API bug! I'm only adding this answer to provide more clear steps on how to downgrade to the older version:

1) Download the older version from here: http://interactivebrokers.github.io/downloads/TWS%20API%20Install%20974.01.msi

IB doesn't show the links for older versions but they keep the file on the Github (note the version name at the end of the link address)

2) Uninstall the current version. From IB's own website, do the following:

  • Uninstall the API from the "Add/Remove Tool" in the Windows
    Control Panel as usual
  • Delete the C:\TWS API\ folder if any files are still remaining to prevent a version mismatch.
  • Locate the file "C:\Windows\SysWOW64\TwsSocketClient.dll". Delete this file. [didn't find this file]
  • Restart the computer before installing a different API version.

3) Install the API using the .msi file

4) Run the Anaconda prompt and navigate to the dir C:\TWS API\source\pythonclient

5) Run: "python setup.py install"

6) After python setup.py install, restart Spyder (if it was opened; I closed mine before step #5 above)

After I installed this older version, the error disappeared!

like image 186
Rational-IM Avatar answered Feb 05 '26 23:02

Rational-IM


So instead of downgrading, I found a quick fix to suppressing the error message. Go to the script where its messing up at, it should be connection.py and at line 119 at the very bottom. This is what I did to catch the error and it worked.

while cont and self.socket is not None:
            try:
                buf = self.socket.recv(4096)
                allbuf += buf
                logger.debug("len %d raw:%s|", len(buf), buf)

                if len(buf) < 4096:
                    cont = False
            except OSError:
                pass
like image 29
shnog Avatar answered Feb 05 '26 21:02

shnog