ADR-004: FX spot curves by base currency
Status
Accepted
Context
FX data can be stored either as pair-named curves or as a base-currency-centric grid. Pair-named storage creates duplication, makes inversion rules inconsistent across callers, and encourages product code to construct curve names directly.
OpenTRMS needs a simpler and more uniform convention.
Decision
OpenTRMS stores one spot curve per configured base currency:
- curve name:
FX_SPOT.{BASE} - grid point label: counter currency ISO code
- grid point value: counter per
1base
All inversion and cross-currency triangulation happen inside FxRateService.
For pairs that do not directly include the system base currency, resolution is a
single hop through that base currency.
The deployment must set system.base_currency. Missing rates fail loudly with
FxRateUnavailableException.
Consequences
This model keeps storage and lookup rules predictable:
- one canonical place stores spot FX for the deployment
- product code does not invent FX index names
- inverse rates are derived consistently instead of stored redundantly
- cross-currency conversion stays easy to reason about
The tradeoff is that the platform is opinionated about spot-rate storage and defers more advanced FX conventions. Forward curves, bid/ask treatment, and other richer market-data shapes remain future work.