Strata Pricing Design: Currency Amounts, Market Data, and Performance
Summary
The discussion examines whether Strata’s use of currency-aware amounts and market-data lookups creates meaningful overhead in FX forward pricing. It explains that CurrencyAmount carries references to immutable Currency and String objects rather than copying those objects on each creation. Short-lived amount objects may also be inexpensive for Java’s garbage collector, and runtime optimization can sometimes remove their allocation cost.
Strata passes trades and market data into functional pricers. This supports immutable calculations and parallel scenario work, while avoiding the need to create a new trade or pricer object for each changed market state. If map lookup becomes a measured bottleneck, a specialized rates provider can supply a narrower, faster lookup path. These points explain design tradeoffs rather than report benchmarks; actual performance depends on the workload and implementation. The answer contrasts this approach with pricing engines that retain direct market-data references.
Key ideas
- Currency-aware amounts preserve the units needed to interpret financial values.
- Currency and its symbol string are shared by reference rather than copied for each amount.
- Passing market data to functional pricers supports immutable calculations and parallel scenarios.
- A specialized rates provider can reduce lookup overhead if profiling shows it matters.
- The discussion offers design reasoning, not measured performance comparisons.
Tags
Full text
# OpenGamma's Strata - Computational Overhead # OpenGamma's Strata - Computational Overhead I've been looking at the open-source library Strata (maintained by OpenGamma), which is written in Java. Now, upon inspection of the FX Forward Pricer and Payment Pricer I noticed two things: - All its low-level calculations & results (present value, PV01, etc.) are done using classes like CurrencyAmount or MultiCurrencyAmount. What is the computational cost of this in comparison to using double numbers first and enhancing the results with Currency Meta Data after the calculations are completed? E.g. every time a new CurrencyAmount is created one passes the internal Currency property, which itself contains a 3-letter symbol represented as string. So it seems strings are repeatedly copied. - The present value function call receives the trade itself and a market data provider. The trade's currency is then used to obtain the appropriate discount factor curve from the market data provider, from which the final discount factor is then queried. Again, I am wondering what the cost of this constant "curve look-up" is on a larger scale. Why not embed a direct reference in the trade (or pricer, depending on the implementation) to the appropriate discount curve? So repeated function calls (be it present value or pv01) don't have to constantly look up the curve in the market data map. Maybe similarly to having a `shared_ptr` to the curve in C++. QuantLib in comparison embeds the necessary market-data object pointers in the pricing engines when the engine is setup, and it only operates on double numbers, which appears more efficient on first glance. Obviously, one cannot easily parallelise the QuantLib approach, whereas this is possible using Strata. ## Answer by JodaStephen (score 5, accepted) https://quant.stackexchange.com/a/40949 On point 1, Strata takes the view that it is important to have the currency associated with the value. After all, the value is meaningless without the currency. There is a cost to creating a `CurrencyAmount` (although if it is used and discarded quickly, this has minimal cost in the garbage collector (the "young generation") and potentially HotSpot may kick in and remove the object creation cost entirely. Although `Currency` contains a `String`, the string is not copied each time. Java strings are immutable (they cannot be changed), and `Currency` is also immutable. As such, when the `CurrencyAmount` is created, a pointer to the existing `Currency` is included, and that contains a pointer to the existing `String`, thus no string or `Currency` is created. On point 2, Strata follows a functional design, where the pricers are functions that are passed data. This immutable and functional nature is a key part of the design of Strata, particularly as it allows easy parallelism. In this case, the pricer is passed the trade and the market data. The pricer examines the trade to see what market data is needed. This provides flexibility to allow the pricer to obtain whatever market data it needs without having to change the API of the function. Were the market data to be embedded in the object, it would require a new object to be created for every calculation, which would be undesirable, particularly when calculating scenarios (repeated calculation on slightly varying market data). If the performance of the market data lookup proved to be a problem, a special implementation of `RatesProvider` (an interface) could be written that only contains market data for one currency pair. The implementation would return the curves without lookup in a hashmap. The caller would then be responsible for passing the correct implementation to the pricer. This would be the most similar approach to that used in QuantLib. Disclaimer: I'm one of the primary authors of Strata.
Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.