title: How do I get my accounts' positions at Interactive Brokers using Python API?
body: <p>EDITED: I found a solution regarding the error messages - it was a bug on IB's API. The code I show as an answer below should be useful for those looking for a clean solution to read positions, and also NAVs, from their accounts at IB.</p>
  
  <p>The original question [SEE SOLUTION BELOW; LEAVING ORIGINAL QUESTION HERE FOR CONTEXT]: I'm trying to get all my accounts positions at Interactive Brokers [IB] using the firm's API. Their documentation, although extensive, is extremely confusing. Sample codes are full of unnecessary commands - I want something very streamlined.</p>
  
  <p>I need help with:</p>
  
  <ol>
  <li>How to get the information "per account" [SOLVED] </li>
  <li>How to bring the variables to a DataFrame [SOLVED]</li>
  <li>How to avoid IB's API from printing a series of error messages [SOLVED]</li>
  </ol>
  
  <p>The code so far: </p>
  
  <pre><code>from ibapi.client import EClient 
  from ibapi.wrapper import EWrapper
  from ibapi.common import * #for TickerId type
  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 &gt; -1:
              print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
  
      def positionEnd(self):
          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()
  </code></pre>
  
  <p>When I run the code above I get a series of (i) account numbers, (ii) the contract symbol, (iii) position and (iv) average cost. This, therefore, answers question #1. You might want to "print" these values to see how IB's API send you the information.</p>
  
  <p>I was also able to define a DataFrame variable <code>all_positions</code> that receives the information I was looking for. See the result below. Note that I had to create an "index" variable that is a unique identifier for each row of the DataFrame (as a combination of the account number and symbol). I didn't find a way to 'append' information to the DataFrame without this 'index' (any idea on how to do it would be welcome):</p>
  
  <p><a href="https://i.stack.imgur.com/9e6Lr.png" rel="noreferrer"><img src="https://i.stack.imgur.com/9e6Lr.png" alt="enter image description here"></a></p>
  
  <p>As for the last issue (the error messages):</p>
  
  <p>Brian's suggestion of the "error" function (see below) got rid of the "-1" errors. But I still get the following:</p>
  
  <blockquote>
    <p>unhandled exception in EReader thread Traceback (most recent call
    last):   File
    "C:\Users\danil\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\danil\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py",
    line 99, in recvMsg
        buf = self._recvAllMsg()   File "C:\Users\danil\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py",
    line 119, in _recvAllMsg
        buf = self.socket.recv(4096) OSError: [WinError 10038] An operation was attempted on something that is not a socket</p>
  </blockquote>