RateSeries Class
Definition
- Namespace
- Bodu.Financial.ExchangeRates
- Assembly
- Bodu.Financial.dll
- Package
- Bodu.Financial 1.0.0
- Source
- RateSeries.cs
Stores the ordered set of dated exchange-rate observations for a single provider and currency pair, optimised for
read-heavy lookup with allocation-free O(log n) resolution under any RateDateResolution
policy.
public sealed class RateSeries
- Inheritance
-
RateSeries
- Inherited Members
- Extension Methods
Remarks
The collection is immutable after construction. Internally it stores observations in a shared Bodu.Financial.ExchangeRates.RateSeriesStorage backed by two parallel sorted arrays - an int array of day numbers (DayNumber) and a decimal array of rates - so that the binary search at lookup time touches only the compact date array. Compared with SortedDictionary<TKey, TValue> this gives substantially better cache locality, no per-node allocation, and predictable hot-path performance for the multi-year daily series typical of FX data.
Instances are safe to share across threads after construction because all read paths only touch read-only arrays. Use RateSeriesBuilder to construct or edit observations imperatively before producing a snapshot via ToSeries().
using Bodu.Financial;
var series = new RateSeries(
new CurrencyPair(CurrencyCode.USD, CurrencyCode.EUR),
"ECB",
new[] { (new DateOnly(2024, 3, 1), 0.92m), (new DateOnly(2024, 3, 4), 0.93m) });
// Resolve a date that has no exact observation, falling back to the previous one.
bool ok = series.TryGetRate(
new DateOnly(2024, 3, 3),
RateLookupOptions.PreviousWithin(5),
out DateOnly resolvedDate, // 2024-03-01
out decimal rate); // 0.92
Constructors
RateSeries(CurrencyPair, string, IEnumerable<RateObservation>, DateTimeOffset?)
Initializes a new instance of the RateSeries class from a sequence of RateObservation records.
public RateSeries(CurrencyPair pair, string provider, IEnumerable<RateObservation> observations, DateTimeOffset? fetchedAtUtc = null)
Parameters
pairCurrencyPairThe currency pair this series describes.
providerstringThe non-empty identifier of the publishing source.
observationsIEnumerable<RateObservation>The observations to include. Must contain at least one entry and must not contain duplicate dates.
fetchedAtUtcDateTimeOffset?The UTC instant at which the load that produced this series downloaded its source data, or null when not tracked.
Exceptions
- ArgumentNullException
Thrown if
providerorobservationsis null.- ArgumentException
Thrown if
provideris empty or white-space, ifobservationsis empty, or if it contains duplicate dates.- ArgumentOutOfRangeException
Thrown if any rate in
observationsis zero or negative.
RateSeries(CurrencyPair, string, IEnumerable<(DateOnly Date, decimal Rate)>, DateTimeOffset?)
Initializes a new instance of the RateSeries class from a sequence of date/rate tuples.
public RateSeries(CurrencyPair pair, string provider, IEnumerable<(DateOnly Date, decimal Rate)> rates, DateTimeOffset? fetchedAtUtc = null)
Parameters
pairCurrencyPairThe currency pair this series describes.
providerstringThe non-empty identifier of the publishing source.
ratesIEnumerable<(DateOnly Date, decimal Rate)>The observations to include. Must contain at least one entry and must not contain duplicate dates.
fetchedAtUtcDateTimeOffset?The UTC instant at which the load that produced this series downloaded its source data, or null when not tracked.
Exceptions
- ArgumentNullException
Thrown if
providerorratesis null.- ArgumentException
Thrown if
provideris empty or white-space, ifratesis empty, or if it contains duplicate dates.- ArgumentOutOfRangeException
Thrown if any rate in
ratesis zero or negative.
Properties
Count
Gets the number of observations stored in this series.
public int Count { get; }
Property Value
- int
A non-negative count equal to the number of rate entries supplied at construction.
FetchedAtUtc
Gets the UTC instant at which the load that produced this series downloaded its source data, or null when not tracked.
public DateTimeOffset? FetchedAtUtc { get; }
Property Value
- DateTimeOffset?
The fetch instant when known; otherwise null.
Remarks
The fetch instant is recorded at the series grain and stamped onto every ExchangeRate the series materializes, so downstream audit consumers can attribute a served rate to the moment its backing data was fetched. It is provenance metadata only and does not affect resolution.
Pair
Gets the currency pair this series describes.
public CurrencyPair Pair { get; }
Property Value
- CurrencyPair
The series pair.
Provider
Gets the identifier of the source that published the rates in this series.
public string Provider { get; }
Property Value
- string
A non-empty provider identifier.
Methods
GetObservations()
Enumerates the observations in strictly ascending date order.
public IEnumerable<RateObservation> GetObservations()
Returns
- IEnumerable<RateObservation>
A lazy sequence of RateObservation values.
ToBuilder()
Creates a mutable builder pre-populated from this series.
public RateSeriesBuilder ToBuilder()
Returns
- RateSeriesBuilder
A new RateSeriesBuilder seeded with the current observations.
TryGetRate(DateOnly, RateLookupOptions?, out DateOnly, out decimal)
Attempts to resolve a rate for requestedDate under options.
public bool TryGetRate(DateOnly requestedDate, RateLookupOptions? options, out DateOnly resolvedDate, out decimal rate)
Parameters
requestedDateDateOnlyThe calendar date the caller is asking about.
optionsRateLookupOptionsThe lookup rules to apply.
resolvedDateDateOnlyWhen this method returns true, the observation date selected as the answer; otherwise default.
ratedecimalWhen this method returns true, the rate observed on
resolvedDate; otherwise default.
Returns
Remarks
The resolution algorithm performs a single BinarySearch<T>(T[], T) over the day-number
array. On an exact hit the corresponding rate is returned immediately. On a miss the previous and next candidate
indices are derived from the bitwise complement of the returned index, then selected per
options. For Nearest with a tie (the requested date lies
exactly midway between two observations), this method returns false so callers receive a
deterministic failure rather than an arbitrary pick.
WithRate(DateOnly, decimal)
Returns a new series with the observation for date upserted to rate.
public RateSeries WithRate(DateOnly date, decimal rate)
Parameters
Returns
- RateSeries
A new RateSeries reflecting the updated observation.
Remarks
Each call materialises a complete new immutable series, so this method is intended for occasional, functional-style single updates. For bulk import or repeated mutation, accumulate observations in an RateSeriesBuilder and build the series once rather than calling WithRate(DateOnly, decimal) in a loop.
Exceptions
- ArgumentOutOfRangeException
Thrown if
rateis zero or negative.
WithoutRate(DateOnly)
Returns a new series with the observation for date removed if present.
public RateSeries WithoutRate(DateOnly date)
Parameters
dateDateOnlyThe observation date to remove.
Returns
- RateSeries
A new RateSeries reflecting the removal.
Exceptions
- InvalidOperationException
Thrown if removing the observation would leave the series empty.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |