QuantLib: Pricing Engines Introduction

One of the main aims of the QuantLib library is to provide mechanisms for calculating NPVs and other characteristics of financial instruments. At the heart of these mechanisms lies the purely abstract PricingEngine class. This class provides an interface to all algorithms that provide measures for the financial instruments. In QuantLib these algorithms are called Pricing Engines. These pricing engines range from simple algorithms based on simply discounting cash flows using a specified YieldTermStructure. At the other extreme are pricing engines that use Monte Carlo models to evaluate the desired results. Different pricing engines require different parameters to perform their calculations and each pricing engine can calculate different results. In practice you will probably not need to know about the details of the PricingEngine interface unless you intend to write your own pricing engines.

Here you should note a word of caution. The abstract base class PricingEngine suggests that pricing engines can be used interchangeably between different instrument types. And why not? The Instrument class defines a method called setPricingEngine that takes a pricing engine and then uses that engine to perform any calculations. This generality is, however, misleading. In practice specific pricing engines are tied to specific types of instruments. The checks are performed at run-time and not at compile time, which is, in my view, one of the main points of criticism of the design of the QuantLib library. All this means that you can, for instance, use the DiscountingBondEngine only for Bond type instruments. If you try to use a different engine, your code will compile but will fail when executing.

The basic class API

The PricingEngine class inherits from the Observable class. This means that the Instrument class will register itself as an observer to any changes in the pricing engine. The class API is quite straightforward.

class PricingEngine : public Observable {
    class arguments;
    class results;
    virtual ~PricingEngine() {}
    virtual arguments* getArguments() const = 0;
    virtual const results* getResults() const = 0;
    virtual void reset() = 0;
    virtual void calculate() const = 0;

The PricingEngine class declares four abstract virtual methods and two nested classes, arguments and results. The arguments class is a base class for any arguments that are needed to perform the calculation. Similarly, the results class is the base class for any results that the pricing engine will produce. The getArguments and getResults methods are intended to return pointers to the arguments and results. In addition the reset method should reset all results and make the pricing engine ready for calculating new results. The calculations should be performed by the calculate method.

Note that the virtual destructor does not do any cleaning up but is necessary because C++ needs a virtual destructor to be implemented whenever the class declares any virtual method.

The two nested classes provide a simple interface for interacting with the arguments to the pricing engine and its results.

class PricingEngine::arguments {
    virtual ~arguments() {}
    virtual void validate() const = 0;

class PricingEngine::results {
    virtual ~results() {}
    virtual void reset() = 0;

Arguments can be validated by the validate method to ensure that all parameters are set and are consistent. The results interface class defines the abstract reset method. Similarly to the reset method in the PricingEngine class, this method should reset all previous results so that the pricing engine can store new results in the object.

The Generic Engine

Most pricing engines do not extend from the PricingEngine class directly but from a generic subclass called GenericEngine. The generic engine provides some limited general functionality to the base class. Specifically, the GenericEngine holds instances of arguments and results classes. The template parameters to the GenericEngine specify the types of these two objects.

template<class ArgumentsType, class ResultsType>
class GenericEngine : public PricingEngine,
                      public Observer {
    PricingEngine::arguments* getArguments() const { return &arguments_; }
    const PricingEngine::results* getResults() const { return &results_; }
    void reset() { results_.reset(); }
    void update() { notifyObservers(); }
    mutable ArgumentsType arguments_;
    mutable ResultsType results_;

The getArguments and getResults simply return the pointers to the arguments_ and results_ members. The reset method of the GenericEngine forwards the call to the results_ object.

In addition, the GenericEngine extends from the Observer. This means that it can react to changes in other objects which it observes. It does this by implementing the update method which is called when a change occurs. Above we saw that PricingEngine is also an Observable. This means that it can make its own changes visible to other objects. The implementation of the update method in the GenericEngine now simply notifies its own observers. This means that if any object observed by the GenericEngine changes the objects observing the GenericEngine will get notified.

The GenericEngine provides sensible default implementations for all methods of the PricingEngine, except for the calculate method. Naturally the calculation will depend on the instrument for which the pricing engine is intended and on the specific algorithms used.