# 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 ComputePayOffmethod 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".

• I would say this is a problem that requires a lot of experience to get right from the start - the reality is that you'll make design decisions to begin with that seem like good ideas that later on end up hamstringing you - this is a problem you'll encounter in building any large system, it's not an easy problem. You'll then need to think about calculating Greeks on all the products, calculating pnl and attributing it to certain Greeks, how deep down the rabbit hole do you plan on going? Do you plan on making a full risk management system?
– will
Mar 7, 2019 at 17:46
• The end of the road is indeed a full risk management system. But for a start it can be a generic MC pricer only. Still I guess there are bad habits to avoid from a start, and I am trying to avoid them. As I said, I am not really satisfied with QL nor with Strata. Mar 7, 2019 at 18:49
• So, I created a generic mc pricer which had mutlple models, prngs, correlation models, etc, all as you mentioned above. After I moved to an IB and saw how the rm system worked, as well. If you have the pricing system, then wrapping rm and pnl scalloping around it is not too hard, as it's all just going to be applying a series of bumps to the market data. The main bits of advice I'd give are 1. Make everything generic. 2. Be very strick about how you allow your objects to interact, if you let them mess with the internals of each other it quickly becomes very difficult to change your code.
– will
Mar 7, 2019 at 20:17
• Why everything generic ? Mar 8, 2019 at 6:53
• Generic is potentially the wrong word, abstract is better. Not everything will have to be, but I just found it easier to outline everything in abstract classes and then have factory methods that instantiated the specific moving parts based on a load of config variables. There was a function that sat outside the whole thing and controlled the flow of information, but as sides from thst it was all abstractm
– will
Mar 8, 2019 at 12:49

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.

• "A Pricing Engine knows about Payoffs, not the other way around". I would tend to agree. But then, how do you design your library in such a way that the pricing engine knows that some payoff CANNOT be priced with a given numerical method or SHOULD NOT be priced under a given model? What is your solution if the payoff cannot provide this information? Jan 29 at 6:38

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.