About this guide: I'm Lawrence, the writer behind supa.is. Between February and May 2026 I've published 150+ articles on supa.is across crypto and brokerage tooling — including 30+ Interactive Brokers-specific guides (recent examples: IBKR Python API Error Handling: Codes & Fixes, Fix IBKR API calculateImpliedVolatility Timeout, IBKR Python API Connection Timeout: 8 Common Fixes). The most-repeated reader question across that IBKR API archive is exactly how to align timestamps between historical and real-time data, which is why I'm publishing this standardized guide instead of answering one-off.
Stitching historical and live data from the Interactive Brokers API hits a wall: the timestamps don't match. reqHistoricalDataAsync returns times in one timezone, while reqRealTimeBars returns them in another.
For algorithmic traders, this isn't just an annoyance—it's a data integrity nightmare. If your backtesting engine assumes historical and live data share the same time reference, your entry signals will drift, your stop-losses will misfire, and your P&L calculations will be fundamentally flawed.
This guide breaks down exactly why this timezone mismatch happens in the IBKR API, how it affects your trading logic, and the proven methods to normalize your timestamps so your data pipeline runs smoothly.
Why IBKR API Uses Different Timezones
To fix the problem, you first need to understand why it exists. Interactive Brokers operates globally, serving clients across dozens of time zones and trading multiple asset classes (stocks, options, futures, forex) on exchanges with vastly different operating hours.
The IBKR API is built with this global reality in mind, but the implementation leaves a lot to be desired for developers:
reqHistoricalDataAsyncreturns Exchange Local Time: When you pull historical data, the API returns timestamps in the local time of the exchange where the instrument is listed. If you're pulling NASDAQ data, you get Eastern Time (ET). If you're pulling LSE data, you get London time.reqRealTimeBarsreturns Client Local Time: When you request real-time bars, the API returns timestamps based on the local time of your client machine (or the server running your script).
This exact issue has been documented by the community, with developers noting the timezone discrepancies causing alignment failures in backtesting frameworks (ib_async issue #181). The core premise of this mismatch is detailed in the official IBKR API documentation for Historical Bars and Real-Time Bars, which specify the differing timezone behaviors for each method.
The Real-World Impact on Your Trading Logic
A timezone mismatch might seem like a minor formatting issue, but it has cascading effects on your trading system:
Signal Drift
If your strategy relies on a specific time-based trigger (e.g., "buy at 9:30 AM ET"), a mismatch means your historical backtest will trigger at 9:30 AM ET, but your live execution might trigger at 9:30 AM your local time. If you're in London, that's a 5-hour difference.Data Gaps and Overlaps
When merging historical and live data, timezones can cause you to either skip data points (gaps) or double-count them (overlaps). If your historical data ends at 16:00 ET and your live data starts at 16:00 your local time, you might miss the transition entirely or process the same tick twice.Broken Rolling Windows
Indicators like RSI, MACD, or Bollinger Bands rely on rolling windows of data. If a timestamp is off by a few hours, your rolling window calculation will include the wrong data points, completely invalidating your indicator values.Comparison: reqHistoricalDataAsync vs reqRealTimeBars Timezones
To visualize the exact discrepancy, here is a side-by-side comparison of how these two API methods handle timezones:
| Feature | reqHistoricalDataAsync | reqRealTimeBars |
|---|---|---|
| Timezone Returned | Exchange Local Time (e.g., ET for NYSE) | Client Local Time (e.g., your server's OS time) |
| DST Handling | Automatically adjusts based on exchange rules | Depends on client machine configuration |
| Best For | Backtesting, historical analysis | Live execution, real-time monitoring |
| Common Pitfall | Assuming it's UTC or your local time | Assuming it matches historical data |
| Normalization Needed | Yes (convert to UTC) | Yes (convert to UTC) |
How to Normalize IBKR API Timestamps
The solution lies in converting all timestamps to a single, universal reference point: UTC (Coordinated Universal Time). UTC is the standard for algorithmic trading because it is unambiguous and unaffected by daylight saving time (DST) shifts.
Here is the step-by-step approach to normalizing your data:
Like what you're reading? Try it yourself — this link supports ChartedTrader at no cost to you.
Open an IBKR Account →Step 1: Identify the Source Timezone
ForreqHistoricalDataAsync, you need to know the timezone of the exchange you are querying. Common exchange timezones include:
- NYSE / NASDAQ: America/New_York (ET)
- LSE: Europe/London (GMT/BST)
- TOPIX: Asia/Tokyo (JST)
- FOREX: Usually UTC, but depends on the broker's feed
reqRealTimeBars, the timezone is your local machine's timezone, which you can check via your Python environment (datetime.now().astimezone().tzname).
Step 2: Convert to UTC
Before merging your datasets, convert both historical and real-time timestamps to UTC. In Python, thepytz or zoneinfo libraries make this straightforward.
from zoneinfo import ZoneInfo
import pandas as pd
# Example: Converting historical data (ET) to UTC
historical_df['timestamp'] = pd.to_datetime(historical_df['timestamp'])
historical_df['timestamp_utc'] = historical_df['timestamp'].dt.tz_localize('America/New_York').dt.tz_convert('UTC')
# Example: Converting real-time data (Local) to UTC
realtime_df['timestamp'] = pd.to_datetime(realtime_df['timestamp'])
realtime_df['timestamp_utc'] = realtime_df['timestamp'].dt.tz_localize('US/Eastern').dt.tz_convert('UTC') # Adjust to your local tz
Step 3: Merge on UTC Timestamps
Once both datasets share a UTC timestamp, you can safely concatenate or merge them without worrying about temporal misalignment.
# Merge the two dataframes on the UTC timestamp
combined_df = pd.concat([historical_df, realtime_df], ignore_index=True)
# Sort by the unified UTC timestamp to ensure chronological order
combined_df = combined_df.sort_values(by='timestamp_utc').reset_index(drop=True)
# You can now safely drop the original timezone-specific columns if you want
combined_df.drop(columns=['timestamp'], inplace=True)
combined_df.rename(columns={'timestamp_utc': 'timestamp'}, inplace=True)
Common Pitfalls When Aligning IBKR Data
Even after converting to UTC, developers often run into secondary issues. Here are the most common pitfalls and how to avoid them:
The Daylight Saving Time (DST) Trap
Exchanges like the NYSE observe DST, shifting clocks forward in spring and back in autumn. If your historical data spans across a DST transition, a naive timezone conversion will result in a 1-hour gap or overlap. Always use IANA timezone strings (likeAmerica/New_York) rather than fixed offsets (like UTC-5), as IANA strings automatically account for DST transitions.
Real-Time Bar Gaps
reqRealTimeBars does not return data continuously. It only sends a new bar when a new tick occurs. If the market is quiet, you might not receive a bar for several minutes. When merging historical and live data, ensure your system can handle these irregular intervals without assuming a strict 1-minute or 5-minute cadence.
Exchange Halts
If an exchange halts trading,reqRealTimeBars will stop sending data, but your system might still be expecting timestamps. A sudden jump in UTC timestamps can indicate a halt, which your algorithm should be programmed to detect and handle gracefully.
IBKR API Alternatives: Should You Use reqMktData Instead?
Some developers avoid reqRealTimeBars altogether, opting for reqMktData (market data) to build their own bars. While reqMktData gives you raw ticks, it requires significantly more processing power and bandwidth.
For most retail algorithmic traders, reqRealTimeBars is the more efficient choice, provided you handle the timezone normalization correctly. The overhead of building bars from scratch rarely justifies the marginal gain in data granularity.
Best Practices for IBKR API Data Pipelines
To ensure your trading system remains robust, follow these best practices:
- Always use UTC internally: Never do calculations or comparisons in local time. Local time is only for human-readable outputs.
- Log timezones explicitly: When debugging, print the timezone of your incoming data. It's easy to assume a timezone and be wrong.
- Test across DST boundaries: If your strategy runs year-round, test your data pipeline with historical data that crosses a DST transition to ensure no gaps appear.
- Handle missing data gracefully: Use forward-filling or interpolation for missing timestamps, but be aware that this introduces assumptions into your data.
Conclusion
The timezone mismatch between reqHistoricalDataAsync and reqRealTimeBars is one of the most common—and most dangerous—pitfalls for IBKR API users. By understanding the root cause and systematically converting all timestamps to UTC, you can eliminate signal drift, prevent data overlaps, and ensure your algorithmic trading system operates on a solid foundation.
If you are just starting your algorithmic trading journey with Interactive Brokers, setting up the right data pipeline is the most critical step.
Open an IBKR Account to get started with their API, and take advantage of the referral bonus which offers up to $1,000 in IBKR stock depending on your deposit tier (as of 2026-07).FAQ
Does IBKR API support UTC timestamps natively?
No. The IBKR API does not have a native flag to force all data streams into UTC. You must handle the timezone conversion on your end after receiving the data.Will this timezone issue affect my paper trading account?
Yes. Paper trading uses the exact same API endpoints as live trading, so the timezone mismatch between historical and real-time data applies equally to both.Can I use pandas to automatically fix the timezone mismatch?
Yes, pandas is excellent for this. By usingpd.to_datetime() and the tz_localize() / tz_convert() methods, you can easily convert disparate timezones into a unified UTC format.
Is this a known bug in the IBKR API?
It is not a bug, but rather a documented quirk of the API. The community has widely discussed this issue, including on the ib_async GitHub repository, noting that historical data defaults to exchange time while real-time data defaults to client time.Does this affect forex trading data?
Forex data is typically already in UTC, but if you are merging forex data with stock data from another exchange, you will still need to normalize the stock data to UTC to align them properly.Risk Warning
Risk Warning: Crypto trading involves substantial risk of loss. Never invest more than you can afford to lose. This is not financial advice. Algorithmic trading carries additional risks, including technical failures, data inaccuracies, and unexpected market conditions. Always backtest your strategies thoroughly and use paper trading before risking real capital.
`