Table of Contents

EcbRateProvider Class

Definition

Namespace
Bodu.Financial.ExchangeRates
Assembly
Bodu.Financial.ExchangeRates.Ecb.dll
Package
Bodu.Financial.ExchangeRates.Ecb 0.7.1
Source
EcbRateProvider.cs

Serves European Central Bank euro reference rates as ExchangeRate values, implementing the Bodu.Financial provider contracts over data downloaded from the ECB's published eurofxref XML feeds.

public sealed class EcbRateProvider : WebRateProvider, IDatedRateProvider, IRateProvider, IPairRateLoader, IHistoricalRateProvider, IDisposable
Inheritance
EcbRateProvider
Implements
Inherited Members
Extension Methods

Examples

using var ecb = new EcbRateProvider(new EcbRateProviderOptions());
await ecb.LoadRangeAsync(new DateOnly(2023, 1, 1), new DateOnly(2023, 12, 31));

RateLookupResult usd = ecb.GetRate("EUR", "USD", new DateOnly(2023, 1, 3));
RateLookupResult eur = ecb.GetRate("USD", "EUR", new DateOnly(2023, 1, 3)); // inverted

Remarks

The provider derives from WebRateProvider, which supplies the in-memory accumulator, the immutable snapshot, the full synchronous and asynchronous lookup matrix, and ownership of the HttpClient when this provider creates one. Loading is feed-based: each ECB feed runs from its earliest date to the most recent business day, so the feed covering a requested date also covers the remainder of the range. Use PreloadAsync(CancellationToken), LoadFeedAsync(EcbRateFeed, CancellationToken), or LoadRangeAsync(DateOnly, DateOnly, CancellationToken) to warm the store.

HttpClient ownership. The constructor that takes only options builds and owns an HttpClient configured from UserAgent and HttpTimeout, disposing it with the provider. The constructor that takes an HttpClient uses the caller-supplied client as-is; this is the path the dependency-injection package uses.

Logging. When an ILogger is supplied (directly or through the dependency-injection package) the provider records: the start of a feed download (Debug), a completed download with its observation count (Information), each ingested observation ( Information), a failed download (Warning, then re-thrown), and a synchronous on-demand network fetch (Warning). Every level is configurable through the corresponding *LogLevel property on EcbRateProviderOptions; omitting the logger selects Instance, so logging is opt-in and free when unused.

Constructors

EcbRateProvider(EcbRateProviderOptions, ILogger?, TimeProvider?)

Initializes a new instance of the EcbRateProvider class backed by an HttpClient the provider creates and owns, configured from the supplied options.

public EcbRateProvider(EcbRateProviderOptions options, ILogger? logger = null, TimeProvider? timeProvider = null)

Parameters

options EcbRateProviderOptions

The provider options.

logger ILogger

The logger. null selects Instance.

timeProvider TimeProvider

The time source. null selects System.

Exceptions

ArgumentNullException

Thrown when options is null.

ArgumentException

Thrown when options fails validation.

EcbRateProvider(HttpClient, EcbRateProviderOptions, ILogger?, TimeProvider?)

Initializes a new instance of the EcbRateProvider class backed by the ECB eurofxref feeds, downloaded with the caller-supplied HTTP client. The caller owns the client's configuration and lifetime.

public EcbRateProvider(HttpClient httpClient, EcbRateProviderOptions options, ILogger? logger = null, TimeProvider? timeProvider = null)

Parameters

httpClient HttpClient

The HTTP client used to download feed files.

options EcbRateProviderOptions

The provider options.

logger ILogger

The logger. null selects Instance.

timeProvider TimeProvider

The time source. null selects System.

Exceptions

ArgumentNullException

Thrown when httpClient or options is null.

ArgumentException

Thrown when options fails validation.

Fields

BaseCurrency

The base currency the ECB quotes against.

public const CurrencyCode BaseCurrency = EUR

Field Value

CurrencyCode

ProviderName

The provider identifier stamped on every rate this provider produces.

public const string ProviderName = "ECB"

Field Value

string

Properties

AllowSynchronousNetworkAccess

Gets a value indicating whether a synchronous lookup may block to fetch a missing window on demand.

protected override bool AllowSynchronousNetworkAccess { get; }

Property Value

bool

true when synchronous getters may block on the network; otherwise false.

Remarks

When enabled, the synchronous getters block on the async fetch, which can deadlock if invoked on a thread carrying a captured SynchronizationContext (classic ASP.NET, a WPF/WinForms UI thread). The synchronous path guards against this by throwing InvalidOperationException when Current is non-null; enable this only for code that calls the getters from a thread-pool thread (or use the asynchronous API).

DefaultLookback

Gets the look-back window used when a single-rate lookup must fetch on demand; the provider fetches the window ending on the requested date and spanning this duration.

protected override TimeSpan DefaultLookback { get; }

Property Value

TimeSpan

The look-back window.

HistoryAvailability

Gets the history depth this provider advertises: how far back it can serve rates.

public override RateHistoryAvailability HistoryAvailability { get; }

Property Value

RateHistoryAvailability

The advertised availability; the base reports Unbounded. A derived type whose feed publishes only a bounded window overrides this to declare it.

Remarks

Computed from the configured Feeds: when the full-history feed is configured the provider reaches back to Epoch (4 January 1999, the start of the euro reference-rate series); otherwise the deepest configured rolling feed bounds the window.

ProviderId

Gets the provider identifier stamped on every rate this provider produces.

protected override string ProviderId { get; }

Property Value

string

The provider identifier.

Methods

EnsureLoadedAsync(CurrencyPair, DateOnly, DateOnly, CancellationToken)

Ensures the inclusive window for a pair has been fetched and accumulated, idempotently. Implementations perform their own coverage check, request coalescing, fetch, and accumulation (via AddObservations(IEnumerable<ExchangeRate>, DateTimeOffset?) and RebuildSnapshot() under SyncRoot).

protected override ValueTask EnsureLoadedAsync(CurrencyPair pair, DateOnly startDate, DateOnly endDate, CancellationToken cancellationToken)

Parameters

pair CurrencyPair

The currency pair to ensure data for. Feeds that fetch by range, feed, or file may ignore it.

startDate DateOnly

The inclusive start of the window.

endDate DateOnly

The inclusive end of the window.

cancellationToken CancellationToken

A token to observe while awaiting the fetch.

Returns

ValueTask

A task that completes when the window has been loaded.

FormatRateNotFound(string, string, DateOnly)

Formats the message for the KeyNotFoundException thrown when a single-rate lookup fails. Derived types may override to use a feed-specific resource string.

protected override string FormatRateNotFound(string fromIsoCode, string toIsoCode, DateOnly date)

Parameters

fromIsoCode string

The source-currency ISO code.

toIsoCode string

The destination-currency ISO code.

date DateOnly

The requested date.

Returns

string

The exception message.

GetAvailablePairs()

Gets the currency pairs discovered across the feeds loaded so far.

public IReadOnlyCollection<EcbSeriesInfo> GetAvailablePairs()

Returns

IReadOnlyCollection<EcbSeriesInfo>

A snapshot of the discovered series, one per currency pair.

IsLoaded(CurrencyPair, DateOnly, DateOnly)

Reports whether the inclusive window for a pair has already been fetched, so the synchronous lookup path can skip a redundant blocking fetch.

protected override bool IsLoaded(CurrencyPair pair, DateOnly startDate, DateOnly endDate)

Parameters

pair CurrencyPair

The currency pair to test.

startDate DateOnly

The inclusive start of the window.

endDate DateOnly

The inclusive end of the window.

Returns

bool

true when the window is already covered; otherwise false.

LoadFeedAsync(EcbRateFeed, CancellationToken)

Downloads and loads a single feed, if it has not already been loaded.

public Task LoadFeedAsync(EcbRateFeed feed, CancellationToken cancellationToken = default)

Parameters

feed EcbRateFeed

The feed to load.

cancellationToken CancellationToken

A token to observe while awaiting the load.

Returns

Task

A task that completes when the feed has been loaded.

Exceptions

ArgumentNullException

Thrown when feed is null.

LoadRangeAsync(DateOnly, DateOnly, CancellationToken)

Downloads and loads the narrowest feed whose coverage reaches the start of the inclusive date range.

public Task LoadRangeAsync(DateOnly startDate, DateOnly endDate, CancellationToken cancellationToken = default)

Parameters

startDate DateOnly

The inclusive start of the range.

endDate DateOnly

The inclusive end of the range.

cancellationToken CancellationToken

A token to observe while awaiting the load.

Returns

Task

A task that completes when the covering feed has been loaded.

Exceptions

ArgumentException

Thrown when endDate precedes startDate.

OnObservationIngested(ExchangeRate)

Called once per observation as it is ingested, for derived-type diagnostics. The default does nothing.

protected override void OnObservationIngested(ExchangeRate rate)

Parameters

rate ExchangeRate

The observation being ingested.

OnSynchronousNetworkFetch(DateOnly)

Called after a synchronous lookup blocks to fetch on demand, for derived-type diagnostics. The default does nothing.

protected override void OnSynchronousNetworkFetch(DateOnly date)

Parameters

date DateOnly

The date around which the fetch was performed.

PreloadAsync(CancellationToken)

Downloads and loads the full-history feed, warming the store with every published day.

public Task PreloadAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

A token to observe while awaiting the load.

Returns

Task

A task that completes when the full history has been loaded.

Remarks

Because each ECB feed extends from its earliest date to the most recent business day, the widest feed in the catalogue subsumes the narrower ones; preloading therefore loads that single feed rather than every overlapping feed.

ValidateRangeRequest(string, string, DateOnly, DateOnly)

Validates a range request against feed-specific preconditions before any fetch is attempted. The default does nothing; derived types may override to reject unsupported pairs (for example, a single-issuer feed that quotes only against one base currency).

protected override void ValidateRangeRequest(string fromIsoCode, string toIsoCode, DateOnly startDate, DateOnly endDate)

Parameters

fromIsoCode string

The source-currency ISO code.

toIsoCode string

The destination-currency ISO code.

startDate DateOnly

The inclusive start of the range.

endDate DateOnly

The inclusive end of the range.

Applies to

ProductVersions
.NET8, 10