ibpy Getting portfolio information: Interactive Broker, Python

interactive brokers python api
interactive brokers api tutorial
ibpy documentation
interactive brokers java api
interactive brokers automated trading
interactive brokers historical data - python
interactive brokers api cost
interactive brokers maven

I have successfully written the code to extract the information from demo version of TWS regarding my positions using the code:

    tws_conn = conn.Connection.create(port=7497, clientId=100)    
    tws_conn.register( acct_update, msg.updateAccountValue,  
    msg.updateAccountTime, msg.updatePortfolio)
    tws_conn.connect()
    tws_conn.reqPositions()
    tws_conn.reqAccountUpdates(True,'DU15181')

However, it dumps the information as:

<updatePortfolio contract=<Packages.IbPy.ib.ext.Contract.Contract object at 0x06B0FE30>, position=-10, marketPrice=3.4000001, marketValue=-3400.0, averageCost=334.345, unrealizedPNL=-56.55, realizedPNL=0.0, accountName=DU15181>

I was wondering how the above information can be stored instead into an array with columns for contract or stock ticker, quantity in portfolio and purchase price in different columns

Adding another answer given the length and major changes. Given I was working on some piece of code I answered another question with it and with a small adaptation can be used for the portfolio too.

Code:

from __future__ import (absolute_import, division, print_function,)
#                        unicode_literals)

import collections
import sys

if sys.version_info.major == 2:
    import Queue as queue
    import itertools
    map = itertools.imap

else:  # >= 3
    import queue


import ib.opt
import ib.ext.Contract


class IbManager(object):
    def __init__(self, timeout=20, **kwargs):
        self.q = queue.Queue()
        self.timeout = 20

        self.con = ib.opt.ibConnection(**kwargs)
        self.con.registerAll(self.watcher)

        self.msgs = {
            ib.opt.message.error: self.errors,
            ib.opt.message.updatePortfolio: self.acct_update,
            ib.opt.message.accountDownloadEnd: self.acct_update,
        }

        # Skip the registered ones plus noisy ones from acctUpdate
        self.skipmsgs = tuple(self.msgs.keys()) + (
            ib.opt.message.updateAccountValue,
            ib.opt.message.updateAccountTime)

        for msgtype, handler in self.msgs.items():
            self.con.register(handler, msgtype)

        self.con.connect()

    def watcher(self, msg):
        if isinstance(msg, ib.opt.message.error):
            if msg.errorCode > 2000:  # informative message
                print('-' * 10, msg)

        elif not isinstance(msg, self.skipmsgs):
            print('-' * 10, msg)

    def errors(self, msg):
        if msg.id is None:  # something is very wrong in the connection to tws
            self.q.put((True, -1, 'Lost Connection to TWS'))
        elif msg.errorCode < 1000:
            self.q.put((True, msg.errorCode, msg.errorMsg))

    def acct_update(self, msg):
        self.q.put((False, -1, msg))

    def get_account_update(self):
        self.con.reqAccountUpdates(True, 'D999999')

        portfolio = list()
        while True:
            try:
                err, mid, msg = self.q.get(block=True, timeout=self.timeout)
            except queue.Empty:
                err, mid, msg = True, -1, "Timeout receiving information"
                break

            if isinstance(msg, ib.opt.message.accountDownloadEnd):
                break

            if isinstance(msg, ib.opt.message.updatePortfolio):
                c = msg.contract
                ticker = '%s-%s-%s' % (c.m_symbol, c.m_secType, c.m_exchange)

                entry = collections.OrderedDict(msg.items())

                # Don't do this if contract object needs to be referenced later
                entry['contract'] = ticker  # replace object with the ticker

                portfolio.append(entry)

        # return list of contract details, followed by:
        #   last return code (False means no error / True Error)
        #   last error code or None if no error
        #   last error message or None if no error
        # last error message

        return portfolio, err, mid, msg


ibm = IbManager(clientId=5001)

portfolio, err, errid, errmsg = ibm.get_account_update()

if portfolio:
    print(','.join(portfolio[0].keys()))

for p in portfolio:
    print(','.join(map(str, p.values())))

sys.exit(0)  # Ensure ib thread is terminated

Result

Server Version: 76
TWS Time at connection:20160113 00:15:29 CET
---------- <managedAccounts accountsList=D999999>
---------- <nextValidId orderId=1>
---------- <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfuture>
---------- <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:eufarm>
---------- <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:cashfarm>
---------- <error id=-1, errorCode=2104, errorMsg=Market data farm connection is OK:usfarm.us>
---------- <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ushmds.us>
---------- <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ilhmds>
---------- <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:cashhmds>
---------- <error id=-1, errorCode=2106, errorMsg=HMDS data farm connection is OK:ethmds>

contract,position,marketPrice,marketValue,averageCost,unrealizedPNL,realizedPNL,accountName
IBM-STK-,10,25.0,250.0,210.0,40.0,0.0,D999999

The last 2 lines can be imported directly to (for example) Excel. Or given it's a list of dictionaries (what's getting printed out) it can be further manipulated in an script.

How to get positions of your portfolio from Interactive Brokers with , You probably need to look through the ibPy code to confirm 'updatePortfolio' is Interactive Brokers posted a recorded webinar at youtube on Dec 13 2016. The topic is to use IBridgePy, a flexiable and easy-to-use python tool to trade at IB. Stack Overflow Public ibpy Getting portfolio information: Interactive Broker, Python (and hence retrieve the portfolio) for my python based platform github

The "columns" requirement is somehow vague, given a list already fulfills the requirement if each entry in the list is a list itself (and each index position in the sublists always contains the same field)

The message you receive is sent to the callback you have registered with tws. Each of the "dumped" fields can be accessed with "dot" notation or through dict-like methods like "keys", "values" and "items"

The major challenge is the contract: IB gives access to a large amount of exchanges and different trading assets. The "contract" object (and information in the IB Backend) seems to reflect an effort to provide a uniform/unified access to everything and at the same time shows they had to build upon existing infrastructure.

You mention "stock ticker" so I guess you'll probably be happy with something like: IBM-STK-SMART with the "ib" industry standard notation (the 2nd field indicates it is a stock and the 3rd that IB will use SMART routing for orders and price updated)

Let's go for a list of lists:

def acct_update(self, msg):
    # Assume the function is a method in a class with access to a member
    # 'portfolio' which is a list

    if isinstance(msg, ib.opt.message.updatePortfolio):
        c = msg.contract
        ticker = '%s-%s-%s' % (contract.m_symbol, c.m_secType, c.m_exchange)
        entry = [ticker]
        entry.extend(msg.values)
        self.portfolio.append(entry)

Unfortunately the "keys" method in the ibpy messages is not a classmethod, but the names are actually __slots__. In the class holding the acct_update method you coud do the following:

class MyClass(object):
    portfields = ['ticker'] + ib.opt.message.updatePortfolio.__slots__

If rather than accessing the fields in a list by index you prefer the names of the fields already provided by ibpy, you can also make a dict of dicts

def __init__(self, ...)
    self.portfolio = collections.OrderedDict()

def acct_update(self, msg):
    # Assume the function is a method in a class with access to a member
    # 'portfolio' which is a list

    if isinstance(msg, ib.opt.message.updatePortfolio):
        c = msg.contract
        ticker = '%s-%s-%s' % (contract.m_symbol, c.m_secType, c.m_exchange)
        self.portfolio[ticker] = collections.OrderedDict(msg.items())

Which would allow you to get the latest ticker information by name and access the fields by name.

If you need to keep a per ticker history

def __init__(self, ...)
    self.portfolio = collections.defaultdict(list)

def acct_update(self, msg):
    # Assume the function is a method in a class with access to a member
    # 'portfolio' which is a list

    if isinstance(msg, ib.opt.message.updatePortfolio):
        c = msg.contract
        ticker = '%s-%s-%s' % (contract.m_symbol, c.m_secType, c.m_exchange)
        self.portfolio[ticker].extend(msg.values())

You could store the "items" rather than the values and later access the tuples if needed.

Trading with Interactive Brokers using Python: An IBPy Tutorial, Tutorial to use IBPy for implementing Python in Interactive Brokers API. After this, you will have to get your Trader Workstation (TWS) in operation. the same, i.e. to relay info between your system and the Interactive Brokers server. Options Trading · Portfolio & Risk Management · Python For Trading  IBPy is a Python wrapper written around the Java-based Interactive Brokers API. It makes development of algorithmic trading systems in Python somewhat less problematic. It will be used as the basis for all subsequent communication with Interactive Brokers until we consider the FIX protocol at a later date.

Besides using ibpy, I will also import IBWrapper which can be downloaded from Github: https://github.com/anthonyng2/ib

import pandas as pd
import numpy as np
import time
from IBWrapper import IBWrapper, contract
from ib.ext.EClientSocket import EClientSocket

accountName = "Your Account ID" 
callback = IBWrapper()             # Instantiate IBWrapper. callback
tws = EClientSocket(callback)      # Instantiate EClientSocket and return data to callback
host = ""
port = 4002   # It is for default port no. in demo account
clientId = 25

tws.eConnect(host, port, clientId) # connect to TWS

create = contract()                # Instantiate contract class
callback.initiate_variables()

tws.reqAccountUpdates(1, accountName)
time.sleep(2)

They are your updated account value and portfolio summary:

accvalue = pd.DataFrame(callback.update_AccountValue, columns = ['key', 'value', 'currency', 'accountName']) #[:199]

portfolio = pd.DataFrame(callback.update_Portfolio, columns=['Contract ID','Currency', 'Expiry','Include Expired','Local Symbol','Multiplier','Primary Exchange','Right',
                                'Security Type','Strike','Symbol','Trading         Class','Position','Market Price','Market Value',
                                'Average Cost', 'Unrealised PnL', 'Realised PnL', 'Account Name'])

callback.update_AccountTime
print("AccountValue: \n" + str(accvalue))
print("portfolio: \n" + str(portfolio))

It is your updated Position Summary:

# Position Summary
tws.reqPositions()
time.sleep(2)
dat = pd.DataFrame(callback.update_Position, 
               columns=['Account','Contract ID','Currency','Exchange','Expiry',
                        'Include Expired','Local Symbol','Multiplier','Right',
                        'Security Type','Strike','Symbol','Trading Class',
                        'Position','Average Cost'])

dat[dat["Account"] == accountName]
print("Position Summary: \n" + str(dat))

Using Python, IBPy and the Interactive Brokers API to Automate , Using Python, IBPy and the Interactive Brokers API to Automate Trades. sudo apt-get install git-core TWS Portfolio View (Prior to Google Trade) (due to the identical login information) or IB places arbitrary orders into the account to make​  IBPy is a third-party implementation of the API used for accessing the Interactive Brokers on-line trading system. IBPy implements functionality that the Python programmer can use to connect to IB, request stock ticker data, submit orders for stocks and futures, and more.

I wrote the following code to allow me to read my positions and NAVs directly from Interactive Brokers API.

# 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)

To test the code I saved it on a .py file named IB_API and run the following:

import IB_API

print("Testing IB's API as an imported library:")

all_positions = IB_API.read_positions()
all_navs = IB_API.read_navs()

print("Test ended")

I'm still trying to avoid an error [WinError 10038] that says "An operation was attempted on something that is not a socket" - please see my question on the topic

anthonyng2/ib: Samples code demonstrating how to use , Samples code demonstrating how to use IbPy to extract information from Interactive Brokers API ib_class.py : Demonstrates how to call IB using IbPy for account and other information. E.g., Account and Portfolio, Orders etc. ago #​2 Unable to get working in IPynb Opened by zoakes 11 months ago. If that says Python is not defined, then do something like "C:/Python27/python setup.py install" If that says no module named setuptools, then get setuptools! Once you have IBPy, the next thing you will need is to grab the IB demo. To do this, head to . Interactive Brokers, then go to create an account: Then go to individuals:

IB Short Video: TWS Python API, IB Short Video: TWS Python API - Option Chains, Portfolio Data and Account Info. Interactive Brokers ®, IBSM, InteractiveBrokers.com ®, Interactive Analytics ®  IbPy - Interactive Brokers Python API. IbPy was originally written by Troy Melhase. IB TWS and Gateway can be obtained via IB website. Introduction. Interactive Brokers offers a trading lab for education institution. The instructor receives a "master" account with the ability to view all the students account information.

ANN: IbPy 0.2 - Interactive Brokers Python API, Where can I get IbPy? In order to use IbPy, the TWS application provided by IB must be installed for more information. External application requests ticker updates, sends orders, receives account data, portfolio data, etc. I am using IBPy to get the positions of my portfolio. I understand that I can do: from ib.opt import ibConnection tws = ibConnection( host = 'localhost',port= 7496, clientId = 123) tws.reqAccountU

ezIBpy · PyPI, a Pythonic Client for Interactive Brokers API. Get info using getAccount('​DUXXXXXX'), getPositions('DUXXXXXX'), getPortfolio('DUXXXXXX'), I do have plans to drop IbPy in favor of IB's official Python API, although I don't have a timetable for this transision. print(ibConn.positions) print("Portfolio") print(​ibConn.portfolio)  IbPy is a third-party implementation of the API used for accessing the Interactive Brokers online trading system. IbPy implements functionality that the Python programmer can use to connect to IB, request stock ticker data, submit orders for stocks and futures, and more.

Comments
  • is there any more code to share?
  • What do you mean, I shared the snippet of code I have been using ?
  • Thanks!! .. great piece of learning exercise for me as well as I started tinkering with Python only a few weeks back.
  • is it possible u can share your main file and the file where you define the above ?
  • There is no such thing a a main file. The code snippets were created on the fly and are based on my experience with ibpy, which I use basically to fetch historical data. It is my intent in the the future to also place orders (and hence retrieve the portfolio) for my python based platform github.com/mementum/backtrader