Bodu.Financial.ExchangeRates.Boe
0.7.1
dotnet add package Bodu.Financial.ExchangeRates.Boe --version 0.7.1
NuGet\Install-Package Bodu.Financial.ExchangeRates.Boe -Version 0.7.1
<PackageReference Include="Bodu.Financial.ExchangeRates.Boe" Version="0.7.1" />
<PackageVersion Include="Bodu.Financial.ExchangeRates.Boe" Version="0.7.1" />
<PackageReference Include="Bodu.Financial.ExchangeRates.Boe" />
paket add Bodu.Financial.ExchangeRates.Boe --version 0.7.1
#r "nuget: Bodu.Financial.ExchangeRates.Boe, 0.7.1"
#:package Bodu.Financial.ExchangeRates.Boe@0.7.1
#addin nuget:?package=Bodu.Financial.ExchangeRates.Boe&version=0.7.1
#tool nuget:?package=Bodu.Financial.ExchangeRates.Boe&version=0.7.1
Bodu.Financial.ExchangeRates.Boe
API stability — Preview. The public API surface is largely settled but is still being finalized ahead of the 1.0 release and may change; breaking changes can land in a minor version until then.
A Bodu.Financial exchange-rate provider backed by the Bank of England's daily spot exchange rates, queried from the Bank's Interactive Statistical Database (IADB).
It builds an IADB CSV query for the configured series over a date range, parses the
response with the Bodu.Text.Formats RFC 4180 reader, and serves the results as
Bodu.Financial.ExchangeRates.ExchangeRate values through the standard IDatedRateProvider
and IRateProvider contracts — so it composes with Money.ConvertTo,
the caching and aggregating providers, and the rest of the Bodu.Financial FX stack.
using Bodu.Financial.ExchangeRates;
// The provider builds and owns its HttpClient from the options; dispose it to release the client.
using var provider = new BoeRateProvider(new BoeRateProviderOptions());
// Warm the cache for a range (recommended), then look rates up synchronously.
await provider.LoadRangeAsync(new DateOnly(2023, 1, 1), new DateOnly(2026, 6, 30));
RateLookupResult usd = provider.GetRate("GBP", "USD", new DateOnly(2023, 1, 3));
// usd.Rate.Rate is the number of US dollars per pound on that date.
// Read a whole range at once (GBP-based pairs; the reverse direction is inverted). The result is
// an IReadOnlyList<ExchangeRate> that also reports the requested window and the observed span.
RateRangeResult series =
await provider.GetRatesAsync("GBP", "JPY", new DateOnly(2026, 1, 1), new DateOnly(2026, 6, 12));
// Discover what pairs the loaded data supports.
foreach (BoeSeriesInfo info in provider.GetAvailablePairs())
Console.WriteLine($"{info.Pair.FromIsoCode}/{info.Pair.ToIsoCode} ({info.SeriesCode})");
Behaviour
- GBP-based. The Bank of England quotes each currency's daily spot rate against the
pound (one IADB series per currency, for example
XUDLUSSfor the US dollar). Direct (GBP→X) and inverse (X→GBP) lookups are supported; cross pairs are not. - Range queries. The IADB is queried by date range rather than by fixed file, so
loading is range-based.
LoadRangeAsyncfetches an inclusive range; a synchronous lookup that misses an unloaded date blocks to download a bounded window around it (configurable viaOnDemandWindowDays) only whenAllowSynchronousNetworkAccessis enabled (it isfalseby default, so the provider serves a snapshot of already-loaded data and a synchronous miss does not reach the network). - Caching. Downloaded range responses are cached on disk (configurable) and refreshed on a TTL, since a range ending near today can gain an observation each business day.
- Configuration.
BoeRateProviderOptionscarries working defaults and binds throughMicrosoft.Extensions.Options. The provider's connection to the IADB is grouped under itsEndpoint(BoeEndpointOptions) — base URL, query path, HTTP timeout, and user-agent — so the query can be pointed at a mirror or proxy without touching caching or series configuration. The package ships its ownAddBoeExchangeRatesregistration in theBodu.Financial.ExchangeRatesnamespace.
HTTP client and lifetime
The provider is IDisposable and offers two construction styles:
new BoeRateProvider(options, ...)— the provider builds, owns, and disposes its ownHttpClient, created viaRateProviderHttpClientFactory.Createfrom the configured user agent and timeout. Dispose the provider (for example withusing) to release the client.new BoeRateProvider(httpClient, options, ...)— you supply the client and own its lifetime; the provider never disposes a client it did not create. This is the form the*.DependencyInjectionpackage uses, backed byIHttpClientFactory.
Logging
The provider logs through Microsoft.Extensions.Logging. Pass an ILogger to the
constructor, or let the *.DependencyInjection package wire one for you (category
Bodu.Financial.ExchangeRates.BoeRateProvider). When no logger is supplied it
defaults to NullLogger.Instance, so logging is entirely opt-in and free when unused.
The levels follow the conventions used by Microsoft.Extensions.Http, EF Core, and the
Azure SDK — the completed download is the one Information line per range loaded, payload
detail is Trace, and degraded paths are Warning. Every level is individually
configurable on BoeRateProviderOptions:
| Event | Default level | Option property |
|---|---|---|
| A range download is starting | Debug |
DownloadStartingLogLevel |
| A range loaded (with its observation count) | Information |
DownloadCompletedLogLevel |
| Each individual rate observation ingested | Trace |
ObservationIngestedLogLevel |
| A range download failed (logged, then re-thrown) | Warning |
DownloadFailedLogLevel |
// Quieten the per-range line and turn off per-observation tracing entirely.
var options = new BoeRateProviderOptions
{
DownloadCompletedLogLevel = LogLevel.Debug,
ObservationIngestedLogLevel = LogLevel.None,
};
The default verbosity is deliberately low: at Information you see one line per range
loaded; at Debug you additionally see when downloads start; only at Trace do you get a
line per rate observation (which can be thousands per range — keep it for targeted
debugging).
Part of the Bodu utility library.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Bodu.Core (>= 1.0.0)
- Bodu.Financial (>= 1.0.0)
- Bodu.Financial.DependencyInjection (>= 1.0.0)
- Bodu.Financial.ExchangeRates (>= 1.0.0)
- Bodu.Financial.ExchangeRates.DependencyInjection (>= 1.0.0)
- Bodu.Text.Delimited (>= 1.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.12)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.12)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.12)
- Microsoft.Extensions.Http (>= 10.0.12)
- Microsoft.Extensions.Http.Resilience (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.12)
- Microsoft.Extensions.Options (>= 10.0.12)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.12)
-
net8.0
- Bodu.Core (>= 1.0.0)
- Bodu.Financial (>= 1.0.0)
- Bodu.Financial.DependencyInjection (>= 1.0.0)
- Bodu.Financial.ExchangeRates (>= 1.0.0)
- Bodu.Financial.ExchangeRates.DependencyInjection (>= 1.0.0)
- Bodu.Text.Delimited (>= 1.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Http (>= 8.0.1)
- Microsoft.Extensions.Http.Resilience (>= 8.10.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.