Asset Classes

Free investment financial education

Language

Multilingual content from IBKR

Close Navigation
Learn more about IBKR accounts

Websockets

Lesson 10 of 11
Duration 9:07
Level Intermediate
Close Navigation

Hello, and welcome to this lesson on Websockets in the Interactive Brokers Client Portal API. In this lesson, we will be discussing how to build a websocket, and perform typical tasks like requesting market data or requesting live trade information using the Client Portal API.

Websockets documentation

To begin, let’s start by looking at our documentation page referring to our Websocket values. Just like our standard ‘endpoints’, there is a lot more to be done with websockets that what we will be able to show in this video, but our foundation will allow you to move on with any of these other details you might be interested in.

The documentation will show case how to retrieve streaming data, trades information, as well as notification details for alerts. I would also like to highlight the Websocket Playground at the bottom. While we will be building the websocket ourselves in python, as long as your client portal gateway is up and running, you can use this as a great method to test new requests. After hitting the “Connect” button, you can paste in any of the websocket requests above and send them to the websocket to test the functionality. However, I will disconnect from that, and we can start reviewing how this can be done using Python.

Building the Websocket

Before we move into the file, you will likely need to pip install “websocket-client” module. This will be rather unique from our prior programs, so I will be building this from a fresh file. After installing the websocket-client module, we will need to import “websocket”, “time” and the “ssl” modules into our new python file.

Utilizing websockets will require building out a websocket object. I will define the method on_message and set the arguments to “ws” and “message”. All we will do in this method is print the message value. After that, I will define the method on_error. Just like before, I will pass “ws” and “error” as variables. Next, I can define the method “on_close” and only pass the argument “ws”. This will only be printing the phrase “## CLOSED ##” to make sure I showcase that our websocket had closed.

Moving on to a more exciting method, I can define “on_open” and pass the “ws” argument. Inside the method, I will define a few details. I will start by simply printing “Opened connection” to acknowledge that the connection was established. Now, I will add in ‘time.sleep(3)’ to make our program pause for a few seconds to make sure everything is up and running. Now, I want to make a list, conids, and set it equal to the strings ‘265598’ and ‘8314’. This will be to request market data for AAPL and IBM.

Now I want to iterate through my conids with a for loop, ‘for conid in conids:’. In a new indented line, I can write the method ‘ws.send()’. This will reference our websocket object that was passed in our on_open method, and can send a request. Within the send method, I will pass the following, ‘smd+'+i+'+{“fields”:[“31″,”84″,”86”]}'. I would note that the formatting of single and double quotes is mandatory in this scenario. In our case, we must send the field values with their quoted values. It is worth bearing in mind that all fields that are used on the iserver/marketdata/snapshot endpoint can be used here as well. If you are interested in finding out more about this topic, please reference our prior lesson on requesting market data.

Inside our Name-Main idiom, I will define the variable, ‘ws’. I will set this equal to the ‘websocket.WebSocketApp()’ class. We will need to pass everything we have built up so far, as well as a websocket URL. Starting with our URL, I will create a string for “wss://localhost:5000/v1/api/ws”. I’ll assign the argument, ‘on_open’, to our ‘on_open’ method. Note that we are not actually passing the parentheses this time, only the function name. I will do the same with ‘on_message’ = ‘on_message’, ‘on_error’ = ‘on_error’, and finally ‘on_close’ = ‘on_close’.

Finally, I will call our websocket to run with ‘ws.run_forever()’. I will set the sslopt argument equal to ‘{“cert_reqs”:ssl.CERT_NONE}’. Much like verify=False in our other lessons, this will disable our SSL verification.

We can now run our code. I will see my “Opened connection” message, followed by a few authentication details and my account information. Eventually, I will start seeing a few responses beginning with “server_id” which will identify my requests from one another.

The ‘conidex’ and ‘conid’ fields will show my contract identifier. The ‘_updated’ field will return the epoch time of a given return. Moving along, we can see all of my field values being returned here for a given conid. Now we are able to see an ongoing stream of market data for our two contracts as new data is available.

Requesting Live Orders.

Now, let’s move on to a new example using the Live Order Updates request instead. This will be built functionally the same as our market data stream. Because of that, I will simply copy over the file for the moment, and work with that foundation.  I will simply modify my on_open method, and instead of sending out my “smd” requests, I will instead be sending ‘sor+{}’. This will key off of my currently active account, so no additional information is needed.

After running this code, I will see all of my other orders placed today. This will show the same authentication status as before, and we will see our heartbeat messages returned to let us know the websocket is still connected. But let’s see how it functions in real time. I will open my place order request from our prior lesson to submit an order to AAPL. 

Running my place order file, I will see my order_id returned, along with my current order status. If I jump back to my websocket’s console, I can see that my new order was activated, and I can see the same orderId mirrored over in my websocket. I can even see the execution return and a description on how the order filled.

Thank you for watching this lesson on websockets in the Client Portal API. If you find this lesson helpful, please check out our other lessons in the Client Portal API tutorial series.

Code Snippet – websocket_md.py

import websocket
import time
import ssl

def on_message(ws, message):
    print(message)

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("## CLOSED! ##")

def on_open(ws):
    print("Opened Connection")
    time.sleep(3)
    conids = ["265598", "8314"]

    for conid in conids:
        ws.send('smd+'+conid+'+{"fields":["31","84","86"]}')

if __name__ == "__main__":
    ws = websocket.WebSocketApp(
        url="wss://localhost:5000/v1/api/ws",
        on_open=on_open,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close
    )
    ws.run_forever(sslopt={"cert_reqs":ssl.CERT_NONE})

Code Snippet – websocket_orders.py

import websocket
import time
import ssl

def on_message(ws, message):
    print(message)

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("## CLOSED! ##")

def on_open(ws):
    print("Opened Connection")
    time.sleep(3)
    ws.send('sor+{}')

if __name__ == "__main__":
    ws = websocket.WebSocketApp(
        url="wss://localhost:5000/v1/api/ws",
        on_open=on_open,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close
    )
    ws.run_forever(sslopt={"cert_reqs":ssl.CERT_NONE})

Join The Conversation

If you have a general question, it may already be covered in our FAQs. If you have an account-specific question or concern, please reach out to Client Services.

11 thoughts on “Websockets”

  • Thomas

    Is there a python example how to send the sessionid. i use the websocket with the following url wss://api.ibkr.com/v1/api/ws

  • Clint

    Is there a way to get market data for an option spread using the smd websockets command? I know that I can get the market data for the individual legs of the spread but the bid and ask of those individual legs never match the bid/ask of the actual spread in TWS. I believe TWS is doing additional calculations to figure out the bid/ask spread and was wondering if there is anyway to get this information through the web sockets api?

    Similar to how you spread orders with multiple conids, is there a way to get the bid/ask market data for a spread using the smd websockets or any other api’s?

    • Interactive Brokers

      Hello, thank you for reaching out. Combos and Spreads are supported for websockets. To retrieve data in this fashion, the ‘conid’ parameter of the websocket request should include the full spread details, similar to a spread order from the /iserver/account/{acctId}/orders endpoint. You can read more about the market data websocket and making a combo request here: https://www.ibkrcampusdev.wpengine.com/campus/ibkr-api-page/cpapi/#ws-sub-watchlist-data

      We hope this helps!

  • Jesus Alonso

    Hello there!
    I’m trying to understand the Historical Data websocket. After I subscribe to a contract, I receive the following messages:
    {“serverId”:”4379500″,”symbol”:”MARA”,”text”:”MARATHON DIGITAL HOLDINGS IN”,”priceFactor”:100,”startTime”:”20240301-18:21:00″,”high”:”2594/62.18/1″,”low”:”2582/197.09/0″,”timePeriod”:”60s”,”barLength”:60,”mdAvailability”:”S”,”mktDataDelay”:0,”outsideRth”:false,”volumeFactor”:1,”priceDisplayRule”:1,”priceDisplayValue”:”2″,”negativeCapable”:false,”messageVersion”:2,”data”:[{“o”:25.87,”c”:25.92,”h”:25.93,”l”:25.82,”v”:197.09},{“o”:25.93,”c”:25.86,”h”:25.94,”l”:25.86,”v”:62.18}],”points”:1,”travelTime”:96,”topic”:”smh+474219659″,”payload”:”{\n \”period\”: \”1min\”,\n \”bar\”: \”1min\”,\n \”source\”: \”trades\”,\n \”format\”: \”%o/%c/%h/%l/%v\”\n}\n”}
    {“serverId”:”4379500″,”tickNum”:1,”negativeCapable”:false,”data”:[{“o”:25.89,”c”:1.111}],”points”:0,”travelTime”:792,”topic”:”smh+474219659″,”payload”:”{\n \”period\”: \”1min\”,\n \”bar\”: \”1min\”,\n \”source\”: \”trades\”,\n \”format\”: \”%o/%c/%h/%l/%v\”\n}\n”}
    ….
    {“serverId”:”4379500″,”tickNum”:4,”negativeCapable”:false,”data”:[{“o”:0.01}],”points”:0,”travelTime”:5725,”topic”:”smh+474219659″,”payload”:”{\n \”period\”: \”1min\”,\n \”bar\”: \”1min\”,\n \”source\”: \”trades\”,\n \”format\”: \”%o/%c/%h/%l/%v\”\n}\n”}

    My questions are:
    1. In the 1st update, the date 20240301-18:21:00 is delayed a couple of seconds. Is this correct? Can’t I receive more updated bars?
    2. How can I know the time of the next updates?
    3. What close = 1.111 represents in tickNum #1?
    4. And open = 0.01 in tickNum #4?

    Thanks in advance!

  • Jesús Alonso

    In the 1st question, I meant, is delayed a couple of minutes
    Thanks

  • rahul

    hii, i have subscribed for NSE market level 2 market data, in order to fetch this through clientportal api what is the Solicited message in the format of TOPIC+[TOPIC_TARGET]+{PARAMETERS} which explained in the api document?

    • Interactive Brokers

      Hello, thank you for reaching out. In order to retrieve the L2 data through the Client Portal API, you will need to request BookTrader Price Ladder Data indicated under the Market Data section of our documentation. This would be in the format of “sbd+acctId+conid+exchange”. If you have any additional questions, please create a web ticket for this inquiry; we have a category specifically for “API.” One of our API experts will be happy to guide you! http://spr.ly/IBKR_ClientServicesCampus

  • Sharon

    Hello , is there a way to connect with websocket to the IBRK web URL, without using the GW?

    • Interactive Brokers

      Hello, thank you for reaching out. For individual accounts, there is no means to authenticate with the WebAPI without using the Client Portal Gateway. Please view this User Guide for more details about the Client Portal Gateway: https://www.interactivebrokers.com/campus/ibkr-api-page/cpapi-v1/#cpgw.

      Please reach back out with any additional questions. We are here to help!

Leave a Reply

Disclosure: Interactive Brokers

The analysis in this material is provided for information only and is not and should not be construed as an offer to sell or the solicitation of an offer to buy any security. To the extent that this material discusses general market activity, industry or sector trends or other broad-based economic or political conditions, it should not be construed as research or investment advice. To the extent that it includes references to specific securities, commodities, currencies, or other instruments, those references do not constitute a recommendation by IBKR to buy, sell or hold such investments. This material does not and is not intended to take into account the particular financial conditions, investment objectives or requirements of individual customers. Before acting on this material, you should consider whether it is suitable for your particular circumstances and, as necessary, seek professional advice.

The views and opinions expressed herein are those of the author and do not necessarily reflect the views of Interactive Brokers, its affiliates, or its employees.

Disclosure: API Examples Discussed

Throughout the lesson, please keep in mind that the examples discussed are purely for technical demonstration purposes, and do not constitute trading advice. Also, it is important to remember that placing trades in a paper account is recommended before any live trading.

IBKR Campus Newsletters

This website uses cookies to collect usage information in order to offer a better browsing experience. By browsing this site or by clicking on the "ACCEPT COOKIES" button you accept our Cookie Policy.