Euro Reference Rates
AvailableThe ECB's daily reference rates for 30 currencies against the euro, on the day they're published.
One rate per working day for each of 30 currencies against the euro, set by the ECB around 14:10 Frankfurt time and published around 16:00. Each pair is named by market convention, so EURUSD is dollars per euro.
These are reference rates for signals and research, not prices you can trade. The ECB publishes them for information only.
How the data works
- Pairs are EUR plus AUD, BGN, BRL, CAD, CHF, CNY, CZK, DKK, GBP, HKD, HUF, IDR, ILS, INR, ISK, JPY, KRW, MXN, MYR, NOK, NZD, PHP, PLN, RON, SEK, SGD, THB, TRY, USD or ZAR.
- 16:00 in Frankfurt is usually 10:00 in New York, and 11:00 for the few weeks a year when the two change their clocks on different dates.
- Not every pair runs throughout. BRL, CNY, ILS and INR start in January 2000, BGN in July 2000, TRY in 2005 and RON in July 2005. ISK has a gap from December 2008 to February 2018, and BGN ends in December 2025.
- There's no rate on TARGET closing days, such as 1 May and 25 December.
- With daily forex bars, trade when the bar arrives rather than on the rate's row, as the example does. An order placed on the row fills at the previous bar's price, which flatters results.
- This dataset is a snapshot to 30 October 2026, and doesn't update yet.
Fields
3 columns| Field | Description |
|---|---|
| available_time | When the row becomes visible to an algorithm: 16:00 Frankfurt time on its date |
| date | Day the rate was set |
| rate | Units of the second currency per euro. Also the row's value |
Example algorithm
# region imports
from AlgorithmImports import *
# endregion
from lean_platform_data import EcbFxRate
class EuroTrendAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2008, 1, 1)
self.set_end_date(2018, 12, 1)
self.set_cash(100000)
self.eurusd = self.add_forex("EURUSD", Resolution.DAILY, Market.OANDA).symbol
# Pairs are EUR plus the other currency, such as EURUSD or EURJPY.
self.rate = self.add_data(EcbFxRate, "EURUSD").symbol
self.average = SimpleMovingAverage(50)
self.latest = None
def on_data(self, slice):
if self.rate in slice:
self.latest = slice[self.rate].rate
self.average.update(self.time, self.latest)
# Trade on the forex bar, which closes after the rate came out, not on the rate's own row:
# an order placed then would fill at the previous bar's price.
bar = slice.quote_bars.get(self.eurusd)
if bar is None or bar.is_fill_forward or not self.average.is_ready:
return
# Hold euros while the reference rate is above its 50-day average.
above = self.latest > self.average.current.value
if above and not self.portfolio.invested:
self.set_holdings(self.eurusd, 1)
elif not above and self.portfolio.invested:
self.liquidate(self.eurusd)
Euro reference rates from the European Central Bank, taken from the Deutsche Bundesbank's statistics.