Some book content, for a change. This is the first in a series of four posts covering chapter 2 of the book; part 2, 3 and 4 are here, here and here. I managed the book footnotes by simply including them in parentheses at the corresponding point in the text; this, too, might change once I get better at this blogging thing I hear so much about. It goes without saying that I’ll be most grateful for any feedback, corrections, and criticisms.
Important news: the good Jacob Bettany of MoneyScience (hi, Jacob) is currently busy organizing the next Introduction to QuantLib Development course, scheduled for September 2nd/4th in London. It is the course that I teach based on the contents of the Implementing QuantLib blog and book, and you can find more information, a brochure and a booking form by clicking on this link. I look forward to see you there.
Follow me on Twitter if you want to be notified of new posts, or add me to your circles, or subscribe via RSS: the buttons for that are in the footer. Also, make sure to check my Training page, even if you can’t make it to the next course.
Financial instruments and pricing engines
THE STATEMENT that a financial library must provide the means to price financial instruments would certainly have appealed to Monsieur de La Palisse. However, that is only a part of the whole problem; a financial library must also provide developers with the means to extend it by adding new pricing functionality.
Foreseeable extensions are of two kinds, and the library must allow either one. On the one hand, it must be possible to add new financial instruments; on the other hand, it must be feasible to add new means of pricing an existing instrument. Both kinds have a number of requirements, or in pattern jargon, forces that the solution must reconcile. This chapter details such requirements and describes the design that allows QuantLib to satisfy them.
The Instrument class
In our domain, a financial instrument is a concept in its own right. For this reason alone, any self-respecting object-oriented programmer will code it as a base class from which specific instruments will be derived.
The idea, of course, is to be able to write code such as
where we don’t have to care about the specific type of each
instrument. However, this also prevents us from knowing what arguments
to pass to the
NPV method, or even what methods to call. Therefore,
even the two seemingly harmless lines above tell us that we have to
step back and think a bit about the interface.
Interface and requirements
The broad variety of traded assets—which range from the simplest to
the most exotic—implies that any method specific to a given class of
instruments (say, equity options) is bound not to make sense for some
other kind (say, interest-rate swaps). Thus, very few methods were
singled out as generic enough to belong to the
interface. We limited ourselves to those returning its present value
(possibly with an associated error estimate) and indicating whether or
not the instrument has expired; since we can’t specify what arguments
are needed (even fancy new C++11 stuff like variadic templates won’t
help) the methods take none; any needed input will have to be stored
by the instrument. The resulting interface is shown in listing 2.1
Listing 2.1: Preliminary interface of the
As is good practice, the methods were first declared as pure virtual ones; but—as Sportin’ Life points out in Gershwin’s Porgy and Bess—it ain’t necessarily so. There might be some behavior that can be coded in the base class. In order to find out whether this was the case, we had to analyze what to expect from a generic financial instrument and check whether it could be implemented in a generic way. Two such requirements were found at different times, and their implementation changed during the development of the library; I present them here in their current form.
One is that a given financial instrument might be priced in different ways (e.g., with one or more analytic formulas or numerical methods) without having to resort to inheritance. At this point, you might be thinking “Strategy pattern”. It is indeed so; I devote the third post of this series to its implementation.
The second requirement came from the observation that the value of a financial instrument depends on market data. Such data are by their nature variable in time, so that the value of the instrument varies in turn; another cause of variability is that any single market datum can be provided by different sources. We wanted financial instruments to maintain links to these sources so that, upon different calls, their methods would access the latest values and recalculate the results accordingly; also, we wanted to be able to transparently switch between sources and have the instrument treat this as just another change of the data values.
We were also concerned with a potential loss of efficiency. For instance, we could monitor the value of a portfolio in time by storing its instruments in a container, periodically poll their values, and add the results. In a simple implementation, this would trigger recalculation even for those instruments whose inputs did not change. Therefore, we decided to add to the instrument methods a caching mechanism: one that would cause previous results to be stored and only recalculated when any of the inputs change.
The code managing the caching and recalculation of the instrument value was written for a generic financial instrument by means of two design patterns.
When any of the inputs change, the instrument is notified by means of the Observer pattern . The pattern itself is briefly described in appendix A (this does not excuse you from reading the Gang of Four book); I describe here the participants.
Obviously enough, the instrument plays the role of the observer while
the input data play that of the observables. In order to have access
to the new values after a change is notified, the observer needs to
maintain a reference to the object representing the input. This might
suggest some kind of smart pointer; however, the behavior of a pointer
is not sufficient to fully describe our problem. As I already
mentioned, a change might come not only from the fact that values from
a data feed vary in time; we might also want to switch to a different
data feed. Storing a (smart) pointer would give us access to the
current value of the object pointed; but our copy of the pointer,
being private to the observer, could not be made to point to a
different object. Therefore, what we need is the smart equivalent of a
pointer to pointer. This feature was implemented in QuantLib as a
class template and given the name of
Handle. Again, details are
given in appendix A; relevant to this discussion is the fact that
copies of a given
Handle share a link to an object. When the link is
made to point to another object, all copies are notified and allow
their holders to access the new pointee. Furthermore,
forward any notifications from the pointed object to their observers.
Finally, classes were implemented which act as observable data and can
be stored into
Handles. The most basic is the
representing a single varying market value. Other inputs for financial
instrument valuation can include more complex objects such as yield or
volatility term structures. (Most likely, such objects ultimately
Quote instances, e.g., a yield term structure might depend
on the quoted deposit and swap rates used for bootstrapping.)
Another problem was to abstract out the code for storing and
recalculating cached results, while still leaving it to derived
classes to implement any specific calculations. This was done by means
of the Template Method pattern . In earlier versions of QuantLib,
the functionality was included in the
Instrument class itself;
later, it was extracted and coded into another class—somewhat
LazyObject—which is now reused in other parts
of the library. An outline of the class is shown in listing 2.2.
Listing 2.2: Outline of the
The code is simple enough. A boolean data member
defined which keeps track of whether results were calculated and still
update method, which implements the
and is called upon notification from observables, sets such boolean to
false and thus invalidates previous results.
calculate method is implemented by means of the Template Method
pattern. As explained in the Gang of Four book, the constant part of
the algorithm (in this case, the management of the cached results) is
implemented in the base class; the varying parts (here, the actual
calculations) are delegated to a virtual method, namely,
performCalculations, which is called in the body of the base-class
method. Therefore, derived classes will only implement their specific
calculations without having to care about caching: the relevant code
will be injected by the base class.
The logic of the caching is simple. If the current results are no longer valid, we let the derived class perform the needed calculations and flag the new results as up to date. If the current results are valid, we do nothing.
However, the implementation is not as simple. You might wonder why we
had to insert a
try block setting
calculated_ beforehand and a
handler rolling back the change before throwing the exception
again. After all, we could have written the body of the algorithm more
simply—for instance, as in the following, seemingly equivalent code,
that doesn’t catch and rethrow exceptions:
The reason is that there are cases (e.g., when the lazy object is a
yield term structure which is bootstrapped lazily) in which
performCalculations happens to recursively call
calculated_ were not set to
if condition would still
performCalculations would be called again, leading to
infinite recursion. Setting such flag to
true prevents this from
happening; however, care must now be taken to restore it to
an exception is thrown. The exception is then rethrown so that it can
be caught by the installed error handlers.
A few more methods are provided in
LazyObject which enable users to
prevent or force a recalculation of the results. They are not
discussed here. If you’re interested, you can heed the advice often
given by master Obi-Wan Kenobi: “Read the source, Luke.”
Instrument class inherits from
LazyObject. In order to
implement the interface outlined in listing 2.1, it decorates the
calculate method with code specific to financial instruments. The
resulting method is shown in listing 2.3, together with other bits of
Listing 2.3: Excerpt of the
Once again, the added code follows the Template Method pattern to
delegate instrument-specific calculations to derived classes. The
class defines an
NPV_ data member to store the result of the
calculation; derived classes can declare other data members to store
specific results (the
Instrument class also defines an
errorEstimate_ member, which is omitted here for clarity of
exposition. The discussion of
NPV_ applies to both). The body of the
calculate method calls the virtual
isExpired method to check
whether the instrument is an expired one. If this is the case, it
calls another virtual method, namely,
setupExpired, which has the
responsibility of giving meaningful values to the results; its default
NPV_ to 0 and can be called by derived
calculated_ flag is then set to
true. If the
instrument is not expired, the
calculate method of
called instead, which in turn will call
needed. This imposes a contract on the latter method, namely, its
implementations in derived classes are required to set
NPV_ (as well
as any other instrument-specific data member) to the result of the
calculations. Finally, the
NPV method ensures that
called before returning the answer.
Aside: const or not const?
It might be of interest to explain why
NPV_ is declared as mutable,
as this is an issue which often arises when implementing caches or
lazy calculations. The crux of the matter is that the
NPV method is
logically a const one: calculating the value of an instrument does not
modify it. Therefore, a user is entitled to expect that such a method
can be called on a const instance. In turn, the constness of
forces us to declare
performCalculations as const,
too. However, our choice of calculating results lazily and storing
them for later use makes it necessary to assign to one or more data
members in the body of such methods. The tension is solved by
declaring cached variables as mutable; this allows us (and the
developers of derived classes) to fulfill both requirements, namely,
the constness of the
NPV method and the lazy assignment to data
Also, it should be noted that the C++11 standard now requires const methods to be thread-safe; that is, two threads calling const members at the same time should not incur in race conditions (to learn all about it, see Sutter ). To make the code conform to the new standard, we should protect updates to mutable members with a mutex. This will likely require some changes in design.
 E. Gamma, R. Helm, R. Johnson and J.Vlissides, Design Patterns:
Element of Reusable Object-Oriented Software. Addison-Wesley, 1995.
 H. Sutter, You don’t know const and mutable. In Sutter’s Mill, 2013.