Duration: 11:37
Level: Intermediate

This lesson will explore how to request market and historical data using the TWS Python API. Code examples will be presented which show the minimum Python code necessary to request streaming and historical data and display market data in the console. Finally, we will discuss limitations on requesting data, and the types of data which are included in IBKR’s real time feed as compared to the historical database.

Study Notes:

Hello, and welcome to a short video discussing how to request market data using the TWS Python API.

There are several calls for market data.

The most popular of these include:

  • reqMktData
  • reqHistoricalData
  • reqTickByTickData

However, we offer several other market data requests, that you may wish to explore.

  • reqRealTimeBars
  • reqMktDepth
  • reqHistoricalTicks
  • reqHistogramData

reqMktData is used to request aggregate real time data that is streamed several times per second. This is the most common method of requesting Live market data.

User Guide: https://interactivebrokers.github.io/tws-api/md_request.html

reqTickByTickData – Unlike reqMktData, this will provide every individual tick on the request. This is a mirror of Trader Workstation’s ‘Time & Sales’ window.

User Guide: https://interactivebrokers.github.io/tws-api/tick_data.html

reqHistoricalData – This is a means to request historical data bars through the API. reqHistoricalData is identical to TWS’s bar charts. This is the most common method of requesting historical market data.

User Guide: https://interactivebrokers.github.io/tws-api/historical_bars.html

With reqMktData, we can use reqMktDataType to change the exact data that is streamed to us.

  • This allows us to request a value, like 1, or Live market data. This will provide the live, top of book market data.
  • We can also request 2, which is Frozen Data. In the event we want to request the market data from close, this would be an optimal way to do so.
  • We can request 3, or Delayed Data. Like TWS, if we do not have any market data subscriptions, we are able to use this request to receive delayed data.
  • Lastly we can use 4, or Frozen Delayed data, which will work as a combination of the two so that you can request market data outside of regular trading hours even without a subscription.

It is important to note that for both live and historical market data, your account must have an active market data subscription for the relevant account. You can subscribe to these market data subscriptions in client portal. One way to reach directly to this page is to open Trader Workstation, then select “Account” in the top left corner, followed by “Subscribe to Market Data/Research” near the bottom. This will take you directly to the relevant market data subscriptions page.

In today’s video, we will be primarily focusing on reqMktData and reqHistoricalData. As we move forward, I would like to specify that the Interactive Brokers TWS API has a pacing limitation of 50 messages per second. As such, a total of 50 messages may be sent AND received within each one second span. Please keep this in mind as you move forward with your coding.

It is important to note that there are several unique historical data limitations which should be reviewed and adhered to as you are writing your programs. These limitations are not unique to the API, as these will also take effect in TWS as well. We would advise reviewing our full historical data limitations page for further details { https://interactivebrokers.github.io/tws-api/historical_limitations.html }.

Some notable historic data limitations include:

  • Not all duration, or the scope of your request, can be used with ever bar size. For example, Interactive Brokers’ largest duration for a 1 second bar is 30 minutes.
  • Interactive Brokers does not provide historical data for expired options.
  • Interactive Brokers does not provide historical data for Futures that expired more than two years ago.

Before moving forward, I would acknowledge that we will be using a different style to code these requests than our previous lesson. There are numerous ways to code the TWS API, and we encourage you to try as many styles as you would like, to see what suits your program best.

Here, I am also introducing a new EWrapper method, nextValidId. This will provide a new order ID for each of my requests, so I avoid duplicating values moving forward. This can be helpful for distinguishing your market data requests, and also your orders, once we reach that step.

Now to begin with our code, we will define the market data type (we’ll request 4). All we need to type for this is simply self.reqMktDataType(4).

Now we’ll start our market data request. Just like before, we include a reqId, and contract. I will be using our orderID variable for the nextValidId method with our request argument.  A new addition will be for the genericTickList. By default, we will receive values like the bid price and size, Ask price and size, along with the closing price, and the days total traded volume. However, we have the option to request more unique values, such as shortable status, or we can request only the amount of shortable shares available.

You can read the full list of these values in our documentation.

Next, you have the option to request a single snapshot of data by setting the snapshot value to 1 or receive an ongoing stream of market data by setting this value to 0.

I have chosen to set this value to 0 for streaming market data.  This is intended for use by individuals who have an active Market data subscription for a given contract.  You may also set an integer variable for requesting regulatory snapshots.  This is intended for accounts that do not have a relevant Market data subscription for a U.S stock.

This will incur a one-time fee of $0.01 to the account per snapshot. In my case, I will set this value to 0.

Finally, we will end with an empty list as this is used for internal use only.  Now that we have all of our EClient requests we will define our EWrapper methods. This will start with tick price which is used for Price values from your market data requests. In this case we will just be printing the return values from tick price.

I would note I am using TickTypeEnum.to_str so I can receive the human readable value of the tick instead of just the tick value. Then we will create tick size. Similar to tick price this will return the size values. This will indicate values like bid size, ask size, last size, or daily volume.

There are several other methods you may wish to include here, such as tick string and tick generic which are needed for some of those generic ticks we had mentioned earlier. Now if you run this request, we could see a variety of values returned. Like we mentioned before, we could see the bid price the ask size, volume and so on.

Request Historical Data

 Now that we’ve received data for our live streaming data request let’s go ahead and request historical data.

Requesting historical data will be very similar. The difference is we will use the EClient method, reqHistoricalData and use the EWrapper method, historicalData.

For reqHistoricalData, we will start by entering a request ID and a contract. Then, we can enter our endDateTime. We can leave this as an empty string, which will then automatically use the current time.

I will specify a request for October 10, 2022 at 3:00 PM US/Central time zone. Then, we can specify the duration, which will be one day in our case. Then we can specify the bar size, and I will specify as one hour.

After specifying our dates, I will specify the whatToShow value.  I will set this to trades to see the trades

value however there are several other options that you may want to review in our documentation.

Finally, we can specify our Booleans. This will be use RTH which I will set to 0, so we include trades outside of regular trading hours. Next ‘formatDate’ is used to display the returned datetime values in epoch time or standard datetime. I will set this to 1, for standard datetime. Then the “keep up to date” flag can be used if we want streaming updates; however, I will leave this as 0. Finally, we will end with an empty list, as this field is for internal use only.

Let’s create our EWrapper method, historicalData. Here, we will include arguments for self, request ID, and ‘bar’. Just like contractDetails in our previous video, our bar object has many attributes, such as the high, low, open, and close. Which you may wish to uniquely specify in your requests.

And again, just like in our contract details request, I will be including the historicalDataEnd method from EWrapper, to safely disconnect from my socket.   This also displays the start and end time of my request.

And so, if we run this request, we can see our historical market data with the datetime for the given market data.

These are just a few simple examples for requesting market data. As we had mentioned before, there are many ways to request your historical and live market data, and we suggest exploring them further in our documentation. However, that concludes our video on requesting market data using the TWS API. Thank you for watching, and we look forward to having you join us for more TWS Python API lessons.

Historical Market Data

Level 1 Market Data

Code Snippet – Request Market Data

from ibapi.client import *
from ibapi.wrapper import *

class TestApp(EClient, EWrapper):
    def __init__(self):
        EClient.__init__(self, self)

    def nextValidId(self, orderId: int):
        mycontract = Contract()
        mycontract.symbol = "AAPL"
        mycontract.secType = "STK"
        mycontract.exchange = "SMART"
        mycontract.currency = "USD"

        self.reqMktData(orderId, mycontract, "", 0, 0, [])

    def tickPrice(self, reqId, tickType, price, attrib):
        print(f"tickPrice. reqId: {reqId}, tickType: {TickTypeEnum.to_str(tickType)}, price: {price}, attribs: {attrib}")

    def tickSize(self, reqId, tickType, size):
        print(f"tickSize. reqId: {reqId}, tickType: {TickTypeEnum.to_str(tickType)}, size: {size}")


app = TestApp()
app.connect("", 7497, 1000)

Code Snippet – Request Historical Market Data

from ibapi.client import *
from ibapi.wrapper import *

class TestApp(EClient, EWrapper):
    def __init__(self):
        EClient.__init__(self, self)

    def nextValidId(self, orderId: int):
        mycontract = Contract()
        mycontract.symbol = "AAPL"
        mycontract.secType = "STK"
        mycontract.exchange = "SMART"
        mycontract.currency = "USD"

        self.reqHistoricalData(orderId, mycontract, "20221010 15:00:00 US/Eastern", "1 D", "1 hour", "TRADES", 0, 1, 0, [])

    def historicalData(self, reqId, bar):
        print(f"Historical Data: {bar}")

    def historicalDataEnd(self, reqId, start, end):
        print(f"End of HistoricalData")
        print(f"Start: {start}, End: {end}")

app = TestApp()
app.connect("", 7497, 1000)

18 thoughts on “Requesting Market Data – Code Walkthrough”

  1. First code is working fine. Code Snippet – Request Market Data But while running
    Code Snippet – Request Historical Market Data

    I am getting below errror
    (ib_venv) akotak@Ankitkumars-MacBook-Pro IBJts % /Users/akotak/Downloads/AlgoTrading/IBJts/source/pythonclient/ib_venv/b
    in/python /Users/akotak/Downloads/AlgoTrading/IBJts/source/pythonclient/my_work/rqst_hist_data.py
    ERROR -1 2104 Market data farm connection is OK:usfarm.nj
    ERROR -1 2104 Market data farm connection is OK:usfuture
    ERROR -1 2104 Market data farm connection is OK:cashfarm
    ERROR -1 2104 Market data farm connection is OK:usfarm
    ERROR -1 2106 HMDS data farm connection is OK:ushmds.nj
    ERROR -1 2106 HMDS data farm connection is OK:ushmds
    ERROR -1 2158 Sec-def data farm connection is OK:secdefil
    ERROR 1 162 Historical Market Data Service error message:No market data permissions for ISLAND STK. Requested market data requires additional subscription for API. See link in ‘Market Data Connections’ dialog for more details.

    1. Hello Ankit, thank you for reaching out. All supported API programming languages offer call back functions to receive error messages sent from the TWS for troubleshooting purposes. Socket-based APIs (e.g., C#, Java, VB.Net, C++, Python and ActiveX) handle error messages within the error() call back function in the EWrapper interface. For additional information, including a list of message codes, please review our API documentation. We hope this helps!
      If your query is still not answered after reviewing the documentation, please create a web ticket in Client Portal with the category “API.” Our experts will be glad to help you out!

  2. Greetings,
    I am trying to download the continous futures historical data for ES. I have set the contract as follows:
    contract = Contract()
    contract.symbol = “ES”
    contract.secType = “CONTFUT”
    contract.exchange = “GLOBEX”
    contract.currency = “USD”
    Fails with 200 contract specification not found. Can you tell me what is wrong here. Here is there any code sample available for getting continous futures.

  3. Hello, when I use “self.reqHistoricalData(orderId, mycontract, “20230908 09:20:00 Asia/Kolkata”, “2 D”, “5 mins”, “TRADES”, 0, 1, 0, [])” why the last of the bar is missing ? The output will be like “Historical Data: Date: 20230907 15:25:00, Open: 250.750000, High: 251.000000, Low: 250.400000, Close: 251.000000, Volume: 3814, Average: 250.765000, BarCount: 56
    Historical Data: Date: 20230908 09:15:00, Open: 252.650000, High: 254.000000, Low: 252.500000, Close: 253.250000, Volume: 7373, Average: 252.950000, BarCount: 45

    As you can see its ended on 15:25 not 15:30 I’m unable to end of the day data for 1min (which ends at 15:29) or 2min which ends at 15:28 – I can’t find the days last bar in any timeframe. What am i missing here? thanks!

    1. Hello Kamal. For this inquiry, please open a web ticket in Client Portal (click the “Help?” in the upper right menu, then “Secure Message Center”). The best category to choose is “API.” Our API experts will be able to help you out from there!

  4. Hi, the thing I don’t understand is when you define class TestApp, and start app.run(), why all the def functions inside the class TestApp are automatically executed? The basic python example tell people that we should explicitly call the function, for example, app.historicalData().

  5. First snippet worked fine, but the second one didn’t. I got the following error message:

    ERROR -1 2104 Market data farm connection is OK:usopt
    ERROR -1 2104 Market data farm connection is OK:usfarm
    ERROR -1 2106 HMDS data farm connection is OK:euhmds
    ERROR -1 2106 HMDS data farm connection is OK:cashhmds
    ERROR -1 2106 HMDS data farm connection is OK:fundfarm
    ERROR -1 2106 HMDS data farm connection is OK:ushmds
    ERROR -1 2158 Sec-def data farm connection is OK:secdefil
    ERROR 1 10314 End Date/Time: The date, time, or time-zone entered is invalid. The correct format is yyyymmdd hh:mm:ss xx/xxxx where yyyymmdd and xx/xxxx are optional. E.g.: 20031126 15:59:00 US/Eastern Note that there is a space between the date and time, and between the time and time-zone. If no date is specified, current date is assumed. If no time-zone is specified, local time-zone is assumed(deprecated). You can also provide yyyymmddd-hh:mm:ss time is in UTC. Note that there is a dash between the date and time in UTC notation.

    When I tried to fix the time (from ’15:00′ to ’15:00:00′) as per the instructions in the error message, the code either hang or said that I didn’t have market data permissions for ISLAND STK. If the previous snippet worked fine for an identical contract, doesn’t this mean that I do have the required permissions? Moreover real-time quotes for AAPL seem to be available normally at TWS.

    1. Hello, thank you for reaching out. You can use TWS Options Trader to modify the expiration date on a selected underlying asset. You can open it from the New Window button in Mosaic or the Trading Tools menu in Classic TWS. Once open, you can enter or change the underlying symbol in the top left. Next, hit enter to load the option chains. You can modify the expiration dates using the settings along the top. We hope this helps!

  6. Hello,
    Curious to know if there is a link that offers a sample for delayed data without a subscription or a subscription that offers this at a basic entry ? Thanks for any feedback or support. Python

  7. Hi,

    I tried the snippet of reqMktData in a paper account and get the error message:
    “ERROR 1 10197 No market data during competing live session”

    This only happens when calling reqMktData. The other two (reqTickByTickData/reqHistoricalData) works fine.

    1. Hi Hao, thank you for reaching out. This error message indicates that the user is logged into the paper account and live account simultaneously trying to request live market data using both accounts. In such a scenario preference would be given to the live account. For more details please refer: https://ibkr.info/node/1719 We hope this helps!

Leave a Reply

Your email address will not be published. Required fields are marked *

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.