IB API HOWTOs and Guidelines - For Beginners

Discussion in 'App Development' started by Butterfly, Nov 8, 2013.

  1. Butterfly

    Butterfly

    I am quite amazed how little info and understanding there is about the infamous IB API despite the popularity of IB and its platform.

    First a quick summary to understand the IB API Architecture, in an easy to understand format:

    1. IB is built on a client/message server architecture offering trading execution, market data feeds, and trading logic executions. It's very important to understand that each of those functions have a different purpose and should be programmed differently.

    2. IB has two Client interfaces, TWS and IBGW. TWS is the GUI trading console which offers all the features of a commercial OMS/EMS. The IBGW is the other client for IB message server but it doesn't offer the rich interface of TWS, it is simply a gateway to send and receive "IB messages" to/from the IB Message Server. It can be regarded as a bare-bone version of TWS, and for that reason all the functions found in TWS needs to be custom built through libraries of code available in another package called IB API. The IB API is available in a number of programming languages. For this guide, I will focus on Java and Python.

    3. The core of programming with IB API will focus on sending Requests to IB Message Server and capturing their replies. The IB API will wrap and parse all those IB messages for the IB Message Server to process. The IB API will parse the replies into programming language objects which make it easy to structure the programming code for other IB functions.

    4. The IB API offers 2 implementations of the IB message parsing/wrapping into code objects. The "ib.ext" tree which is very "low level" and kind of clumsy as most "low level" systems are, and the "ib.opt" tree which is more "elegant" and "higher level" and not as awkward as "ib.ext". The "ib.opt" tree obviously uses calls to "ib.ext", so "ib.ext" is still fundamental for your IB code to function.

    To structure the IB functions into your Java and Python code, you need to perform the followings steps (see next post below):
     
    riothead, pstrusi and Bizzy Bee like this.
  2. Nice thread! Keep it coming ...
     
  3. Butterfly

    Butterfly

    To structure the IB functions, you will need to perform the followings:

    1. Launch the IBGW with your login/passwd.

    2. The IBGW will have the following parameter: port=4001

    3. Connect to the IBGW with the "ib.opt" classes using the IBGW port=4001

    4. For each connection to the IBGW, you need to assign a "clientId" to the connection. This can be the source of confusion in the majority of undocumented IB API Frameworks. The "clientId" is not your customer id, but a "socket" client id, and it's an arbitrary number. It can be random or ordered as you wish. Another possible confusion is to create a new connection for each action on the IB Message Server. Making a new connection for requesting a new quote or sending a new order. One good practice is to have a connection channel for all related tasks, for example one connection channel for all trading executions, one connection channel for all quote actions, and one connection channel for portfolio positions. Again separating OMS functions is important to make your Java or Python code fluid and readable, and above all, maintainable.

    5. Next, create your own classes to process replies from the IBGW Server. Again, this is key to structure your code. Sending requests to the IBGW is quite simple with existing IB API classes in "ib.opt", but catching the replies is really what it's all about.
     
  4. Butterfly

    Butterfly

    now, let's practice what we preach. The following example assume that IbPy has already been installed in your Python installation.

    First, launch the IBGW and enter your login/passwd

    This is a Python code example, to be executed through the Python shell with or without GUI:

    Code:
    #!/usr/bin/env python
    
    from time import sleep
    
    # LOAD the ib.ext and ib.opt Libraries
    from ib.ext.Contract import Contract
    from ib.opt import ibConnection, message
    
    # DEFINE a basic function to capture error messages
    def error_handler(msg):
        print "Error", msg
    
    # DEFINE a basic function to print the "raw" server replies
    def replies_handler(msg):
        print "Server Reply:", msg
    
    # DEFINE a basic function to print the "parsed" server replies for an IB Request of "Portfolio Update" to list an IB portfolio position
    def print_portfolio_position(msg):
        print "Position:", msg.contract.m_symbol, msg.position, msg.marketPrice, msg.contract.m_currency, msg.contract.m_secType
    
    # Main code - adding "if __name__ ==" is not necessary
    
    # Create the connection to IBGW with client socket id=1234
    ibgw_conChannel = ibConnection(port=4001,clientId=1234)
    ibgw_conChannel.connect()
    
    # Map server replies for "Error" messages to the "error_handler" function
    ibgw_conChannel.register(error_handler, 'Error')
    
    # Map server replies to "print_portfolio_position" function for "UpdatePortfolio" client requests
    ibgw_conChannel.register(print_portfolio_position, 'UpdatePortfolio')
    
    # Map server "raw" replies to "replies_handler" function for "UpdateAccount" client requests
    ibgw_conChannel.register(replies_handler, 'UpdateAccountValue')
    
    # Make client request for AccountUpdates (includes request for Portfolio positions)
    ibgw_conChannel.reqAccountUpdates(1, '')
    
    # Stop client request for AccountUpdates
    ibgw_conChannel.reqAccountUpdates(0, '')
    
    sleep(5)
    
    # Disconnect - optional
    # print 'disconnected', ibgw_conChannel.disconnect()
    
    
    The output will be something like that:

    Code:
    Server Version: 59
    TWS Time at connection:20131108 18:55:57 ICT
    Server Reply: <updateAccountValue key=AccountCode, value=XXXX, currency=None, accountName=XXXX>
    ....
    Server Reply: <updateAccountValue key=TradingType-S, value=STKNOPT, currency=None, accountName=XXXX>
    Server Reply: <updateAccountValue key=UnrealizedPnL, value=-9765.22, currency=BASE, accountName=XXXX>
    Server Reply: <updateAccountValue key=UnrealizedPnL, value=-9765.22, currency=USD, accountName=XXXX>
    Server Reply: <updateAccountValue key=WarrantValue, value=0.00, currency=BASE, accountName=XXXX>
    Server Reply: <updateAccountValue key=WarrantValue, value=0.00, currency=USD, accountName=XXXX>
    Server Reply: <updateAccountValue key=WhatIfPMEnabled, value=true, currency=None, accountName=XXXX>
    Position: HTS 50 17.3999996 USD STK
    Position: MITT 70 16.1100006 USD STK
    Position: MTGE 50 19.7800007 USD STK
    Position: NYMT 100 6.6199999 USD STK
    Position: REM 130 11.85999965 USD STK
    Position: STWD 50 25.94000055 USD STK
    Position: WMC 50 15.98999975 USD STK
    
     
  5. Butterfly

    Butterfly

    It is important to understand that the requests will trigger different replies with different frequencies. Some requests will trigger long replies that can be "attributed" to different message handlers, like we saw in the example above with reqAccountUpdates(1, ''). The request gave replies to Portfolio Positions and Account Positions. This is a bit clumsy though, but that's how IBGW respond to such request.

    Some requests are not simple one time request, but actual request for "continuous streams". When reqAccountUpdates(1, '') is sent to the IBGW, it will send the "Portfolio Positions" message only once, but it will send the "Account Position" message every 3 minutes until you suspend the "continuous stream" with reqAccountUpdates(0, '').

    The purpose of requesting streams serves the need of processing market data systems when you subscribe to such services from IB. The handling of Market Data streams in your Python code doesn't have to be exclusively from your broker or IB, it can also be sourced from a different vendor like REUTERS or IQ or even Yahoo/Google and you will need a different API to access those. But if you do subscribe to IB Market Data services, the request to IBGW for such service will trigger a continuous stream of quotes that will call your function code that was "mapped" or "registered" with that request.
     
  6. gmst

    gmst

    This thread has the potential to become one of hall of fame threads!!!
     
  7. There's already a Yahoo group for the IB API that's very active and has plenty of source code available.

    I use the C++ class wrapper from there for all my apps.
     
  8. Butterfly

    Butterfly

    The Yahoo groups are mostly for trading logic, which is another topic in itself. This is what I am referring to in the intro, many times there is a confusion between trading logic and the execution side of an OMS.

    In HFT (High Frequency Trading), the trading logic is basically bound to the execution, so the code for those 2 normally separated functions is basically merged. HFT is the equivalent of "hacking". There is no distinction between the execution of the code and the "hacking" of that code. In normal programming, you build the code and then run it, not "hack" it when it's running. It's the same with trading. You need to build the trading logic first before the execution, not "hacking" it while executing it at the same time.

    The purpose of this tutorial is to give tools for actual seasoned traders with a real long term strategy they want to automate, not for the HFT players.
     
  9. Butterfly

    Butterfly

    ok next example, how to send an actual trade to IBGW, in this case buying shares on a company with a limit price.
     
  10. ofthomas

    ofthomas

    this might be of use as well...

    Join IB’s Senior API Developers for an Advanced API Q&A, Wednesday 11/13 at 12:00 PM ET close

    If you are using IB’s TWS API to create your own custom trading application, then this Special Event is for you! Get your TWS API for DDE for Excel, ActiveX, Java and C++ API questions answered by IB’s Senior API Developers.

    For more information and to submit your questions, visit https://plus.google.com/events/cd9jo1jbg391oatfb80hovvaos0?cfem=1
     
    #10     Nov 8, 2013