Problem Description
Solution
To access historical and live data for EUR/USD in QuantConnect, you must first subscribe to the Forex pair in the initialize method. Once subscribed, you can request historical data using self.history and access real-time data streams via the on_data event handler.
Below is a complete, runnable algorithm demonstrating how to initialize the asset, fetch a pandas DataFrame of historical data, and read live price updates.
QuantConnect Strategy Code
# region imports
from AlgorithmImports import *
# endregion
class EurUsdDataAlgorithm(QCAlgorithm):
def initialize(self):
# 1. Set Strategy Settings
self.set_start_date(2023, 1, 1)
self.set_end_date(2023, 12, 31)
self.set_cash(100000)
# 2. Subscribe to EURUSD data
# We save the Symbol object to a variable for easy reference later
# Resolution.MINUTE provides 1-minute bars. Options: TICK, SECOND, MINUTE, HOUR, DAILY
self.eurusd = self.add_forex("EURUSD", Resolution.MINUTE, Market.OANDA).symbol
# 3. Get Historical Data
# This requests the last 60 bars of data at the resolution defined above (Minute)
# The result is a pandas DataFrame
history_df = self.history(self.eurusd, 60, Resolution.MINUTE)
# Check if history is not empty and log the last historical close
if not history_df.empty:
last_historical_close = history_df.loc[self.eurusd].iloc[-1]['close']
self.debug(f"History loaded. Last historical close: {last_historical_close}")
# Example: Get Daily history even if the subscription is Minute
daily_history = self.history(self.eurusd, 5, Resolution.DAILY)
self.debug(f"Daily history rows: {len(daily_history)}")
def on_data(self, slice: Slice):
# 4. Access Live/Current Data
# The 'slice' object contains all data for the current moment
# Check if EURUSD data is available in this time slice
if self.eurusd in slice.quote_bars:
quote_bar = slice.quote_bars[self.eurusd]
# Forex data usually relies on Bid/Ask rather than just 'Close' (which is the mid-point)
bid_price = quote_bar.bid.close
ask_price = quote_bar.ask.close
mid_price = quote_bar.close
self.plot("Trade Plot", "Price", mid_price)
# Example logic: Log price every 100th bar to avoid log flooding
if self.time.minute % 10 == 0:
self.log(f"{self.time} :: Bid: {bid_price} | Ask: {ask_price} | Mid: {mid_price}")
Implementation Details
add_forex: This method subscribes your algorithm to the data feed. It returns aForexobject, from which we extract the.symbol. This symbol is the unique identifier used throughout the algorithm.self.history: This method is used to get past data.- Arguments: It accepts the symbol (or list of symbols), the lookback period (integer for number of bars, or
timedeltafor a period of time), and the resolution. - Return Type: It returns a pandas DataFrame indexed by Symbol and Time. You can manipulate this using standard pandas techniques (e.g.,
.loc,.iloc,.mean()).
- Arguments: It accepts the symbol (or list of symbols), the lookback period (integer for number of bars, or
on_data: This is the event handler for real-time data.slice: The Slice object groups data packets. For Forex, data usually comes in asQuoteBars(containing Bid and Ask data) rather thanTradeBars(which are for assets that trade on centralized exchanges like Equities).- Accessing Price:
slice[symbol].closegives the mid-price. To get specific bid or ask prices, useslice.quote_bars[symbol].bid.closeorslice.quote_bars[symbol].ask.close.
Q&A: Forex Data in QuantConnect
Q: Why do I get QuoteBars instead of TradeBars for EURUSD?
A: Forex is an Over-The-Counter (OTC) market. There is no centralized exchange recording single "trades." Instead, you receive "Quotes" (Bid and Ask prices) from liquidity providers. Therefore, QuantConnect provides QuoteBars for Forex, which contain the Open, High, Low, and Close for both the Bid and the Ask sides.
Q: Can I get Tick data for EURUSD?
A: Yes. You can change the resolution in the subscription to Resolution.TICK:
self.add_forex("EURUSD", Resolution.TICK).
Be aware that tick data is very high volume and will significantly slow down backtests compared to Minute or Hour resolution.
Q: How do I handle different time zones?
A: By default, QuantConnect converts all data to the time zone specified in set_time_zone (default is New York, Eastern Time). The self.time property in your algorithm will reflect this time zone. You do not need to manually convert data timestamps unless you have specific external requirements.
Q: What happens if I request history for a resolution different from my subscription?
A: QuantConnect allows this. As shown in the example code, you can subscribe to Resolution.MINUTE but request Resolution.DAILY history. The engine will automatically aggregate the data for you.