• C#
  • Java
  • VB
  • C++
  • Python
Contact us
Historical Bar Data

Requesting Historical Bar Data

Historical data is obtained from the the TWS via the IBApi.EClient.reqHistoricalData function. Every request needs:

  • tickerId, A unique identifier which will serve to identify the incoming data.
  • contract, The IBApi.Contract you are interested in.
  • endDateTime, The request's end date and time (the empty string indicates current present moment).
  • durationString, The amount of time (or Valid Duration String units) to go back from the request's given end date and time.
  • barSizeSetting, The data's granularity or Valid Bar Sizes
  • whatToShow, The type of data to retrieve. See Historical Data Types
  • useRTH, Whether (1) or not (0) to retrieve data generated only within Regular Trading Hours (RTH)
  • formatDate, The format in which the incoming bars' date should be presented. Note that for day bars, only yyyyMMdd format is available.
  • keepUpToDate, Whether a subscription is made to return updates of unfinished real time bars as they are available (True), or all data is returned on a one-time basis (False). Available starting with API v973.03+ and TWS v965+. If True, and endDateTime cannot be specified.

For example, making a request with an end date and time of "20160127-23:59:59", a duration string of "3 D" and a bar size of "1 hour" will return three days worth of 1 hour bars data in which the most recent bar will be the closest possible to 20160127-23:59:59.

  • String queryTime = DateTime.Now.ToUniversalTime().AddMonths(-6).ToString("yyyyMMdd-HH:mm:ss");
    client.reqHistoricalData(4001, ContractSamples.EurGbpFx(), queryTime, "1 M", "1 day", "MIDPOINT", 1, 1, false, null);
    client.reqHistoricalData(4002, ContractSamples.EuropeanStock(), queryTime, "10 D", "1 min", "TRADES", 1, 1, false, null);
    client.reqHistoricalData(4003, ContractSamples.USStockAtSmart(), queryTime, "1 M", "1 day", "SCHEDULE", 1, 1, false, null);
  • Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    cal.add(Calendar.MONTH, -6);
    SimpleDateFormat form = new SimpleDateFormat("yyyyMMdd-HH:mm:ss");
    String formatted = form.format(cal.getTime());
    client.reqHistoricalData(4001, ContractSamples.EurGbpFx(), formatted, "1 M", "1 day", "MIDPOINT", 1, 1, false, null);
    client.reqHistoricalData(4002, ContractSamples.EuropeanStock(), formatted, "10 D", "1 min", "TRADES", 1, 1, false, null);
    client.reqHistoricalData(4003, ContractSamples.USStockAtSmart(), formatted, "1 M", "1 day", "SCHEDULE", 1, 1, false, null);
    Thread.sleep(2000);
    /*** Canceling historical data requests ***/
    client.cancelHistoricalData(4001);
    client.cancelHistoricalData(4002);
    client.cancelHistoricalData(4003);
  • Dim queryTime As String = DateTime.Now.ToUniversalTime.AddMonths(-6).ToString("yyyyMMdd-HH:mm:ss")
    client.reqHistoricalData(4001, ContractSamples.EurGbpFx(), queryTime, "1 M", "1 day", "MIDPOINT", 1, 1, False, Nothing)
    client.reqHistoricalData(4002, ContractSamples.EuropeanStock(), queryTime, "10 D", "1 min", "TRADES", 1, 1, False, Nothing)
    client.reqHistoricalData(4003, ContractSamples.USStockAtSmart(), queryTime, "1 M", "1 day", "SCHEDULE", 1, 1, False, Nothing)
  • std::time_t rawtime;
    std::tm timeinfo;
    char queryTime[80];
    std::time(&rawtime);
    gmtime_s(&timeinfo, &rawtime);
    std::strftime(queryTime, sizeof queryTime, "%Y%m%d-%H:%M:%S", &timeinfo);
    m_pClient->reqHistoricalData(4001, ContractSamples::EurGbpFx(), queryTime, "1 M", "1 day", "MIDPOINT", 1, 1, false, TagValueListSPtr());
    m_pClient->reqHistoricalData(4002, ContractSamples::EuropeanStock(), queryTime, "10 D", "1 min", "TRADES", 1, 1, false, TagValueListSPtr());
    m_pClient->reqHistoricalData(4003, ContractSamples::USStockAtSmart(), queryTime, "1 M", "1 day", "SCHEDULE", 1, 1, false, TagValueListSPtr());
  • 1  queryTime = (datetime.datetime.today() - datetime.timedelta(days=180)).strftime("%Y%m%d-%H:%M:%S")
    2  self.reqHistoricalData(4102, ContractSamples.EurGbpFx(), queryTime,
    3  "1 M", "1 day", "MIDPOINT", 1, 1, False, [])
    4  self.reqHistoricalData(4103, ContractSamples.EuropeanStock(), queryTime,
    5  "10 D", "1 min", "TRADES", 1, 1, False, [])
    6  self.reqHistoricalData(4104, ContractSamples.EurGbpFx(), "",
    7  "1 M", "1 day", "MIDPOINT", 1, 1, True, [])
    8  self.reqHistoricalData(4103, ContractSamples.USStockAtSmart(), queryTime,
    9  "1 M", "1 day", "SCHEDULE", 1, 1, False, [])

The daily bar size has several unique characteristics. This is true both in TWS and the API:

  • For futures, the close price of daily bars can be the settlement price if provided by the exchange. Generally the official settlement price is not available until several hours after a trading session closes. The Friday settlement price will sometimes not be available until Saturday.
  • A daily bar will refer to a trading session which may cross calendar days. In that case the date of the bar will correspond to the day on which the bar closes.

Receiving Historical Bar Data

The historical data will be delivered via the IBApi::EWrapper::historicalData method in the form of candlesticks. The time zone of returned bars is the time zone chosen in TWS on the login screen. If reqHistoricalData was invoked with keepUpToDate = false, once all candlesticks have been received the IBApi.EWrapper.historicalDataEnd marker will be sent. Otherwise updates of the most recent partial five-second bar will continue to be returned in real time to IBApi::EWrapper::historicalDataUpdate. The keepUpToDate functionality can only be used with bar sizes 5 seconds or greater and requires the endDate is set as the empty string. Also, with keepUpToDate = true, if bust event happens, then bust event error (code=10225) is reported to all API client versions connected to TWS version 981+.

  • Note: IB's historical data feed is filtered for some types of trades which generally occur away from the NBBO such as combos, block trades, and derivatives. For that reason the historical data volume will be lower than an unfiltered historical data feed.
  • IB does not maintain separate historical data for combos. Historical data returned for a combo contract will be the sum of data from the individual legs.
  • public class EWrapperImpl : EWrapper
    {
    ...
    public virtual void historicalData(int reqId, Bar bar)
    {
    Console.WriteLine("HistoricalData. " + reqId + " - Time: " + bar.Time + ", Open: " + Util.DoubleMaxString(bar.Open) + ", High: " + Util.DoubleMaxString(bar.High) +
    ", Low: " + Util.DoubleMaxString(bar.Low) + ", Close: " + Util.DoubleMaxString(bar.Close) + ", Volume: " + Util.DecimalMaxString(bar.Volume) +
    ", Count: " + Util.IntMaxString(bar.Count) + ", WAP: " + Util.DecimalMaxString(bar.WAP));
    }
    ...
    public virtual void historicalDataEnd(int reqId, string startDate, string endDate)
    {
    Console.WriteLine("HistoricalDataEnd - "+reqId+" from "+startDate+" to "+endDate);
    }
  • public class EWrapperImpl implements EWrapper {
    ...
    @Override
    public void historicalData(int reqId, Bar bar) {
    System.out.println("HistoricalData: " + EWrapperMsgGenerator.historicalData(reqId, bar.time(), bar.open(), bar.high(), bar.low(), bar.close(), bar.volume(), bar.count(), bar.wap()));
    }
    ...
    @Override
    public void historicalDataEnd(int reqId, String startDateStr, String endDateStr) {
    System.out.println("HistoricalDataEnd. " + EWrapperMsgGenerator.historicalDataEnd(reqId, startDateStr, endDateStr));
    }
  • Public Class EWrapperImpl
    Implements EWrapper
    ...
    Public Sub historicalData(reqId As Integer, bar As Bar) Implements IBApi.EWrapper.historicalData
    Console.WriteLine("HistoricalData - ReqId [" & reqId & "] Date [" & bar.Time & "] Open [" & Util.DoubleMaxString(bar.Open) & "] High [" &
    Util.DoubleMaxString(bar.High) & "] Low [" & Util.DoubleMaxString(bar.Low) & "] Volume [" & Util.DecimalMaxString(bar.Volume) & "] Count [" & Util.IntMaxString(bar.Count) &
    "] WAP [" & Util.DecimalMaxString(bar.WAP) & "]")
    End Sub
    ...
    Public Sub historicalDataEnd(reqId As Integer, start As String, [end] As String) Implements IBApi.EWrapper.historicalDataEnd
    Console.WriteLine("HistoricalDataEnd - ReqId [" & reqId & "] Start [" & start & "] End [" & [end] & "]")
    End Sub
  • class TestCppClient : public EWrapper
    {
    ...
    void TestCppClient::historicalData(TickerId reqId, const Bar& bar) {
    printf( "HistoricalData. ReqId: %ld - Date: %s, Open: %s, High: %s, Low: %s, Close: %s, Volume: %s, Count: %s, WAP: %s\n", reqId, bar.time.c_str(),
    Utils::doubleMaxString(bar.open).c_str(), Utils::doubleMaxString(bar.high).c_str(), Utils::doubleMaxString(bar.low).c_str(), Utils::doubleMaxString(bar.close).c_str(),
    DecimalFunctions::decimalStringToDisplay(bar.volume).c_str(), Utils::intMaxString(bar.count).c_str(), DecimalFunctions::decimalStringToDisplay(bar.wap).c_str());
    }
    ...
    void TestCppClient::historicalDataEnd(int reqId, const std::string& startDateStr, const std::string& endDateStr) {
    std::cout << "HistoricalDataEnd. ReqId: " << reqId << " - Start Date: " << startDateStr << ", End Date: " << endDateStr << std::endl;
    }
  • 1 class TestWrapper(wrapper.EWrapper):
    ...
    1  def historicalData(self, reqId:int, bar: BarData):
    2  print("HistoricalData. ReqId:", reqId, "BarData.", bar)
    ...
    1  def historicalDataEnd(self, reqId: int, start: str, end: str):
    2  super().historicalDataEnd(reqId, start, end)
    3  print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to", end)


  • public void historicalDataUpdate(int reqId, Bar bar)
    {
    Console.WriteLine("HistoricalDataUpdate. " + reqId + " - Time: " + bar.Time + ", Open: " + Util.DoubleMaxString(bar.Open) + ", High: " + Util.DoubleMaxString(bar.High) +
    ", Low: " + Util.DoubleMaxString(bar.Low) + ", Close: " + Util.DoubleMaxString(bar.Close) + ", Volume: " + Util.DecimalMaxString(bar.Volume) +
    ", Count: " + Util.IntMaxString(bar.Count) + ", WAP: " + Util.DecimalMaxString(bar.WAP));
    }
  • @Override
    public void historicalDataUpdate(int reqId, Bar bar) {
    System.out.println("HistoricalDataUpdate. " + EWrapperMsgGenerator.historicalData(reqId, bar.time(), bar.open(), bar.high(), bar.low(), bar.close(), bar.volume(), bar.count(), bar.wap()));
    }
  • Public Sub historicalDataUpdate(reqId As Integer, bar As Bar) Implements IBApi.EWrapper.historicalDataUpdate
    Console.WriteLine("HistoricalDataUpdate - ReqId [" & reqId & "] Date [" & bar.Time & "] Open [" & Util.DoubleMaxString(bar.Open) & "] High [" &
    Util.DoubleMaxString(bar.High) & "] Low [" & Util.DoubleMaxString(bar.Low) & "] Volume [" & Util.DecimalMaxString(bar.Volume) & "] Count [" & Util.IntMaxString(bar.Count) &
    "] WAP [" & Util.DecimalMaxString(bar.WAP) & "]")
    End Sub
  • void TestCppClient::historicalDataUpdate(TickerId reqId, const Bar& bar) {
    printf( "HistoricalDataUpdate. ReqId: %ld - Date: %s, Open: %s, High: %s, Low: %s, Close: %s, Volume: %s, Count: %s, WAP: %s\n", reqId, bar.time.c_str(),
    Utils::doubleMaxString(bar.open).c_str(), Utils::doubleMaxString(bar.high).c_str(), Utils::doubleMaxString(bar.low).c_str(), Utils::doubleMaxString(bar.close).c_str(),
    DecimalFunctions::decimalStringToDisplay(bar.volume).c_str(), Utils::intMaxString(bar.count).c_str(), DecimalFunctions::decimalStringToDisplay(bar.wap).c_str());
    }
  • 1  def historicalDataUpdate(self, reqId: int, bar: BarData):
    2  print("HistoricalDataUpdate. ReqId:", reqId, "BarData.", bar)

Historical Data with whatToShow "SCHEDULE"

A new whatToShow = SCHEDULE parameter has been introduced in the TWS API 10.12.
The data is requested via IBApi.EClient.reqHistoricalData method with whatToShow "SCHEDULE" and delivered via IBApi.EWrapper.historicalSchedule method.

  • public void historicalSchedule(int reqId, string startDateTime, string endDateTime, string timeZone, HistoricalSession[] sessions)
    {
    Console.WriteLine($"Historical Schedule. ReqId: {reqId}, Start: {startDateTime}, End: {endDateTime}, Time Zone: {timeZone}");
    foreach (var session in sessions)
    {
    Console.WriteLine($"\tSession. Start: {session.StartDateTime}, End: {session.EndDateTime}, Ref Date: {session.RefDate}");
    }
    }
  • @Override
    public void historicalSchedule(int reqId, String startDateTime, String endDateTime, String timeZone, List<HistoricalSession> sessions) {
    System.out.println(EWrapperMsgGenerator.historicalSchedule(reqId, startDateTime, endDateTime, timeZone, sessions));
    }
  • Public Sub historicalSchedule(reqId As Integer, startDateTime As String, endDateTime As String, timeZone As String, sessions As HistoricalSession()) Implements EWrapper.historicalSchedule
    Console.WriteLine($"Historical Schedule. ReqId: {reqId}, Start: {startDateTime}, End: {endDateTime}, Time Zone: {timeZone}")
    For Each session In sessions
    Console.WriteLine($"{Chr(9)}Session. Start: {session.StartDateTime}, End: {session.EndDateTime}, Ref Date: {session.RefDate}")
    Next
    End Sub
  • void TestCppClient::historicalSchedule(int reqId, const std::string& startDateTime, const std::string& endDateTime, const std::string& timeZone, const std::vector<HistoricalSession>& sessions) {
    printf("Historical Schedule. ReqId: %d, Start: %s, End: %s, TimeZone: %s\n", reqId, startDateTime.c_str(), endDateTime.c_str(), timeZone.c_str());
    for (unsigned int i = 0; i < sessions.size(); i++) {
    printf("\tSession. Start: %s, End: %s, RefDate: %s\n", sessions[i].startDateTime.c_str(), sessions[i].endDateTime.c_str(), sessions[i].refDate.c_str());
    }
    }
  • 1  def historicalSchedule(self, reqId: int, startDateTime: str, endDateTime: str, timeZone: str, sessions: ListOfHistoricalSessions):
    2  super().historicalSchedule(reqId, startDateTime, endDateTime, timeZone, sessions)
    3  print("HistoricalSchedule. ReqId:", reqId, "Start:", startDateTime, "End:", endDateTime, "TimeZone:", timeZone)
    4 
    5  for session in sessions:
    6  print("\tSession. Start:", session.startDateTime, "End:", session.endDateTime, "Ref Date:", session.refDate)

Valid Duration String units

UnitDescription
SSeconds
DDay
WWeek
MMonth
YYear

Valid Bar Sizes

Size
1 secs 5 secs 10 secs 15 secs 30 secs
1 min 2 mins 3 mins 5 mins 10 mins 15 mins 20 mins 30 mins
1 hour 2 hours 3 hours 4 hours 8 hours
1 day
1 week
1 month

Historical Data Types

(whatToShow)

All different kinds of historical data are returned in the form of candlesticks and as such the values return represent the state of the market during the period covered by the candlestick.

TypeOpenHighLowCloseVolume
TRADESFirst traded priceHighest traded priceLowest traded priceLast traded priceTotal traded volume
MIDPOINTStarting midpoint priceHighest midpoint priceLowest midpoint priceLast midpoint priceN/A
BIDStarting bid priceHighest bid priceLowest bid priceLast bid priceN/A
ASKStarting ask priceHighest ask priceLowest ask priceLast ask priceN/A
BID_ASKTime average bidMax AskMin BidTime average askN/A
ADJUSTED_LASTDividend-adjusted first traded priceDividend-adjusted high tradeDividend-adjusted low tradeDividend-adjusted last tradeTotal traded volume
HISTORICAL_VOLATILITYStarting volatilityHighest volatilityLowest volatilityLast volatilityN/A
OPTION_IMPLIED_VOLATILITYStarting implied volatilityHighest implied volatilityLowest implied volatilityLast implied volatilityN/A
FEE_RATEStarting fee rateHighest fee rateLowest fee rateLast fee rateN/A
YIELD_BIDStarting bid yieldHighest bid yieldLowest bid yieldLast bid yield N/A
YIELD_ASKStarting ask yieldHighest ask yieldLowest ask yieldLast ask yieldN/A
YIELD_BID_ASKTime average bid yieldHighest ask yieldLowest bid yieldTime average ask yieldN/A
YIELD_LASTStarting last yieldHighest last yieldLowest last yieldLast last yieldN/A
SCHEDULEN/AN/AN/AN/AN/A
AGGTRADESFirst traded priceHighest traded priceLowest traded priceLast traded priceTotal traded volume


  • TRADES data is adjusted for splits, but not dividends.
  • ADJUSTED_LAST data is adjusted for splits and dividends. Requires TWS 967+.
  • SCHEDULE returns historical trading schedule only with no information about OHLCV. Requires TWS API 10.12+.
  • AGGTRADES data should only be used with Crypto contracts.

Available Data per Product

Product Type
TRADES
MIDPOINT
BID
ASK
BID_ASK
HISTORICAL_VOLATILITY
OPTION_IMPLIED_VOLATILITY
YIELD_BID
YIELD_ASK
YIELD_BID_ASK
YIELD_LAST
SCHEDULE
AGGTRADES
Stocks
Y
Y
Y
Y
Y
Y
Y
N
N
N
N
Y
N
Commodities
N
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
Options
Y
Y
Y
Y
Y
N
N
N
N
N
N
N
N
Futures
Y
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
FOPs
Y
Y
Y
Y
Y
N
N
N
N
N
N
N
N
ETFs
Y
Y
Y
Y
Y
Y
Y
N
N
N
N
Y
N
Warrants
Y
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
Structured Products
Y
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
SSFs
Y
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
Forex
N
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
Metals
Y
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
Indices
Y
N
N
N
N
Y
Y
N
N
N
N
Y
N
Bonds*
Y
Y
Y
Y
Y
N
N
Y
Y
Y
Y
Y
N
Funds
N
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
CFDs*
N
Y
Y
Y
Y
N
N
N
N
N
N
Y
N
Cryptocurrency
Y
Y
Y
Y
Y
N
N
N
N
N
N
Y
Y
  • Yield historical data only available for corporate bonds.
  • SCHEDULE data returns only on 1 day bars.