Separating Immutable Payoffs from Pricing Engines
Summary
The document discusses how to design a cross-asset pricing library that supports multiple models and numerical methods while keeping products and payoffs immutable for serialization. Its central design principle is to keep a payoff focused on contract terms and cashflow calculation, without embedding a model, random number generator, or pricing state inside it. The pricing engine should instead take the payoff, market data, and model parameters as inputs.
An engine can combine a model with an analytic method, Monte Carlo, or a finite-difference solver, while checking whether that combination can handle the payoff’s features. Numerical engines may decompose payoffs into reusable calculation components and generate schedules as needed. The examples explain how a finite-difference or Monte Carlo engine can be separated from pricing-specific logic. A model’s ability to simulate relevant underlyings and triggers does not by itself establish that it is appropriate for a product; model suitability remains a separate judgment. The discussion offers architectural guidance rather than a complete implementation or benchmark.
Key ideas
- A payoff should represent contract terms and calculate cashflows without holding mutable model or pricing state.
- Pricing engines should combine payoffs with market data, model parameters, and numerical methods.
- Analytic, Monte Carlo, and finite-difference approaches can be treated as engine choices.
- Payoff features determine whether a particular engine and model can support the requested calculation.
- A model may technically price a product while still being unsuitable for its trading risks.
Tags
Full text
# Architecture of a global pricing library with immutable payoffs # Architecture of a global pricing library with immutable payoffs By global pricing library I mean a library - handling equity, rate etc, hybrid products - having several models (BS, LV, SV, LSV) - having several numerical methods (analytic formula, MC, PDE FD/FE) I never had to design a global pricing library, only had to write isolated MC or PDE FD pricing libraries, with BS, LV and SV mainly, in a purely front office setting, so I was quite free for the modelling and designing. In these cases I always used the following architecture (in the case of a toy MC) : - a `Product` has a (reference to) a `PayOff` - a `PayOff` has a `Model` and a `ComputePayOff`method that computes the payoff on a path generated by the model - a `Model` has a `RandomNumberGenerator` and a `GenerateMCPath` method that generates an MC path given dates with the given random generator `PayOff` is abstract, as well as `Model` and `RandomNumberGenerator`, even if I always had issues with avoiding exponential increase of subclasses due to transverse functionality, as I am not a design pattern (bridge ?) expert. So that `PayOff` has a lot of "non-immutable" information. For instance if my `RandomNumberGenerator` is a Sobol, it may have a member that changes after generating random number, so that after a pricing, PayOff has a information that has changed. I never cared about that. Now, I have the task of laying out a poc for a global pricing library, with the constraint that `Product` and `PayOff` must not change (they going to be (de)serialized). I could of course, with a lot of contorsions, continue to do as in the previous toy-example, but it would be wrong. Still, after thinking, some things do not change : I indeed want to have three categories of "objects" : - products (or payoffs to make it simple) - models - numerical methods and these categories may intersect, for instance : - the intersection of european payoffs, BS model and closed formulae (a special kind of numerical method) yields the BS formula - the intersection of european payoffs and Heston model yields as numerical methods either closed formulas, PDE FD2D or MC etc. In fact, the library needs to process a given payoff under a given model, using a given numerical method, keeping track of the fact that it cannot price everything in any model and with any numerical method ... Is there a classic way to design this ? As I do not intend to necessarily reinvent the wheel, I looked at QuantLib and Strata so far, but they both have "non-immutable" "payoffs". ## Answer by user47501 (score 4) https://quant.stackexchange.com/a/54783 That's the best question that nearly no one asks. I'm with you on Quantlib and Strata, haven't really seen a very good design around but I've seen quite a few bad ones. It is definitely doable and has big advantages in terms of testing, maintenance, scalability. The golden rule is that your objects must correspond to concepts. The core problem (in bad designs) is that the Payoff has a Model or pricing engine etc. Conceptually the payoff is simply a translation of the calculation part of a termsheet. Anything you add on top of that will be simply too much and will not be a clean design. The functionality of Payoff is resumed to calculating cashflow amounts given prices of underlyings. You can have get functions for dates, types of events (barriers), key levels (strike) etc. of course. A Pricing Engine knows about Payoffs, not the other way around. On top of Payoffs you needs one or more Markets and some model parameters. Internally the Pricing engine creates a Model from Market objects (to get drift, vol etc) and model parameters. The pricing engine can be Analytic or Numeric. Analytic is straightforward. A numeric pricing engine needs to produce the date schedule for calculation based on what set of Payoffs it has to price. It also needs to collect a representation of all the calculations needed. IF you want efficiency then you want to decompose each payoff into smaller components describing the basic calculations like averages, digitals etc. You can have PDE(FD) or MC based engines. An FD-based pricing engine will combine Model and NumericMethod(FD) to solve a PDE with boundary conditions. The PricingPDE class models the usual Backward pricing PDE plus a postStep() method to perform Payoff calculations. The FD engine itself doesn't know about pricing. It is simply solving a PDE with boundary conditions. All reference to "pricing" is in the PricingPDE class. Same FD engine can be used for calibration or, why not, solving the basic heat equation. Same goes for a MonteCarlo engine. ## Answer by user47501 (score 1) https://quant.stackexchange.com/a/69728 Payoffs can be broken down into actual cashflows driven by underlying variables (calculated from simulated assets/rates etc). On top of that there would be a list of features e.g. barriers, callability, early exercise and so on. The engine has to deal with all these characteristics of the payoff, and if it can't, it means that payoff cannot be priced. Re models, if a model can simulate all the underlying variables and feature triggers, then it can be used to price that payoff. If it's the right model in the sense that it covers or not all the factors that can impact the price, that's to be decided upfront. E.g. pricing a cliquet with local vol would be possible but not the way to go when trading them.
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.