treewolf
treewolf

Reputation: 1

Interactive Brokers API not storing historical price data into xlsx, how to resolve?

I want to distinguish the historical price data for e-mini S&P500 (ES) by RTH and ETH sessions and store them into xlsx files. The xlsx files are only showing 1 row containing: "Date, Open, High, Low, Close" without the historical price data. I am subscribed to the proper CME data. Any assistance with this issue would be greatly appreciated.

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
import pandas as pd

class HistoricalDataApp(EWrapper, EClient):
    def __init__(self):
        EWrapper.__init__(self)
        EClient.__init__(self, wrapper=self)
        self.rth_data = []  # Initialize rth_data attribute
        self.eth_data = []  # Initialize eth_data attribute

    def historicalData(self, reqId, bar):
        # Callback function to receive historical data
        if reqId == 1:  # Check if this is the request you made
            date = bar.date.strftime("%Y-%m-%d %H:%M:%S")
            if bar.time == "16:00:00":
                self.rth_data.append([date, bar.open, bar.high, bar.low, bar.close])
            else:
                self.eth_data.append([date, bar.open, bar.high, bar.low, bar.close])

    def historicalDataEnd(self, reqId, start, end):
        # Callback function indicating the end of historical data
        if reqId == 1:
            self.disconnect()

def get_futures_historical_data():
    app = HistoricalDataApp()
    app.connect("127.0.0.1", 7497, clientId=0)  # Modify host and port as per your configuration

    contract = Contract()
    contract.symbol = "ES"
    contract.secType = "FUT"
    contract.exchange = "CME"
    contract.currency = "USD"
    contract.lastTradeDateOrContractMonth = "202309"  # Modify contract expiry as per your requirement

    # Request historical data
    app.reqHistoricalData(1, contract, "", "3 Y", "1 day", "TRADES", 1, 1, False, [])

    # Start the event loop
    app.run()

    # Store data in separate arrays
    rth_df = pd.DataFrame(app.rth_data, columns=["Date", "Open", "High", "Low", "Close"])
    eth_df = pd.DataFrame(app.eth_data, columns=["Date", "Open", "High", "Low", "Close"])

    # Export data to Excel
    rth_df.to_excel("rth_data.xlsx", index=False)
    eth_df.to_excel("eth_data.xlsx", index=False)

if __name__ == "__main__":
    get_futures_historical_data()

Added print(f"Received historical data. reqId: {reqId}, Date: {bar.date}, Time: {bar.time}") to see if the historicalData is actually being called. When I run the code, nothing shows up in the console output. TWS is open and API ActiveX and socket clients are enabled.

I also added print statements before and after app.connect, which was successful.

def get_futures_historical_data():
    app = HistoricalDataApp()
    print("Before connecting to API")
    app.connect("127.0.0.1", 7497, clientId=0)  # Modify host and port as per your configuration
    print("After connecting to API")

Upvotes: 0

Views: 164

Answers (1)

brian
brian

Reputation: 10989

You have to wait for historicalDataEnd before saving the data.

You ask for the data (possibly even before you have a connection) : app.reqHistoricalData

And then you start the read loop : app.run()

And then you immediately make a DF with data not yet returned : rth_df = pd.DataFrame

If you are having a problem with asynchronous programming I would suggest:

https://nbviewer.org/github/erdewit/ib_insync/blob/master/notebooks/bar_data.ipynb

Main docs:https://ib-insync.readthedocs.io/readme.html

If you would like to see an asynchronous method: https://stackoverflow.com/a/57502748/2855515

Upvotes: 0

Related Questions