Chapter 2, part 4 of 4: Example
Hello everybody. This is the final post in a series of four covering chapter 2 of the book; part 1, 2 and 3 can be found here, here and here. I look forward to your feedback. Next time, an interlude with an ubiquitous utility class.
As you might have heard if you follow me in Google+, last week we had a major release in the family (word to the wise: this is where having prepared a few posts in advance paid off). In lesser news, QuantLib 1.3 is ready, too. Like Bob Dylan, it shall be released—that is, after I package and check it, which will take a day or two.
Registration for the next Introduction to QuantLib Development course is still open; 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.
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
Example: plain-vanilla option
At this point, an example is necessary to show how the facilities
described in the previous post can be used to implement an
instruments. A word of warning, though: although a class exists in
QuantLib which implements plain-vanilla options—i.e., simple
call and put equity options with either European, American or Bermudan
exercise—such class is actually the lowermost leaf of a deep
class hierarchy. Having the Instrument
class at its root, such
hierarchy specializes it first with an Option
class, then again with
a OneAssetOption
class generalizing options on a single underlying,
passing through another class or two until it finally defines the
VanillaOption
class we are interested in.
There are good reasons for this; for instance, the code in the
OneAssetOption
class can naturally be reused for, say, Asian
options, while that in the Option
class lends itself for reuse when
implementing all kinds of basket options. Unfortunately, this causes
the code for pricing a plain option to be spread among all the members
of the described inheritance chain, which would not make for an
extremely clear example. Therefore, I will describe a simplified
VanillaOption
class with the same implementation as the one in the
library, but inheriting directly from the Instrument
class; all code
implemented in the intermediate classes will be shown as if it were
implemented in the example class rather than inherited.
Listing 2.7 shows the interface of our vanilla-option class. It
declares the required methods from the Instrument
interface, as well
as accessors for additional results, namely, the greeks of the
options; as pointed out in the previous section, the corresponding
data members are declared as mutable so that their values can be set
in the logically constant calculate
method.
Besides its own data and methods, VanillaOption
declares a number of
accessory classes: that is, the specific argument and result
structures and a base pricing engine. They are defined as inner
classes to highlight the relationship between them and the option
class; their interface is also shown in the listing.
Listing 2.7: Interface of the VanillaOption
class and its inner
classes.
Two comments can be made on such accessory classes. The first is that,
making an exception to what I said in my introduction to the example,
I didn’t declare all data members into the results
class. This was
done in order to point out an implementation detail. One might want to
define structures holding a few related and commonly used results;
such structures can then be reused by means of inheritance, as
exemplified by the Greeks
structure that is here composed with
Instrument::results
to obtain the final structure. In this case,
virtual inheritance from PricingEngine::results
must be used to
avoid the infamous inheritance diamond (see, for instance, [1]; the
name is in the index).
The second comment is that, as shown, it is sufficient to inherit from
the class template GenericEngine
(instantiated with the right
argument and result types) to provide a base class for
instrument-specific pricing engines. We will see that derived classes
only need to implement their calculate
method.
We now turn to the implementation of the VanillaOption
class, shown
in listing 2.8. Its constructor takes a few objects defining the
instrument. Most of them will be described in later posts or in
appendix A of the book. For the time being, suffice to say that the
payoff contains the strike and type (i.e., call or put) of the option,
and the exercise contains information on the exercise dates and
variety (i.e., European, American, or Bermudan). The passed arguments
are stored in the corresponding data members. Also, note that they do
not include market data; those will be passed elsewhere.
Listing 2.8: Implementation of the VanillaOption
class.
The methods related to expiration are simple enough; isExpired
checks whether the latest exercise date is passed, while
setupExpired
calls the base-class implementation and sets the
instrument-specific data to 0.
The setupArguments
and fetchResults
methods are a bit more
interesting. The former starts by downcasting the generic argument
pointer to the actual type required, raising an exception if another
type was passed; it then turns to the actual work. In some cases, the
data members are just copied verbatim into the corresponding argument
slots. However, it might be the case that the same calculations (say,
converting dates into times) will be needed by a number of engines;
setupArguments
provides a place to write them just once.
The fetchResults
method is the dual of setupArguments
. It also
starts by downcasting the passed results
pointer; after verifying
its actual type, it just copies the results into his own data members.
Albeit simple, the above implementation is everything we needed to
have a working instrument—working, that is, once it is set an
engine which will perform the required calculations. Such an engine is
sketched in listing 2.9 and implements the analytic
Black-Scholes-Merton formula for European options. Its constructor
takes (and registers itself with) a Black-Scholes stochastic process
that contains market-data information about the underlying including
present value, risk-free rate, dividend yield, and volatility. Once
again, the actual calculations are hidden behind the interface of
another class, namely, the BlackCalculator
class. However, the code
has enough detail to show a few relevant features.
Listing 2.9: Sketch of an engine for the VanillaOption
class.
The method starts by verifying a few preconditions. This might come as
a surprise, since the arguments of the calculations were already
validated by the time the calculate
method is called. However, any
given engine can have further requirements to be fulfilled before its
calculations can be performed. In the case of our engine, one such
requirement is that the option is European and that the payoff is a
plain call/put one, which also means that the payoff will be cast down
to the needed class. (boost::dynamic_pointer_cast
is the equivalent
of dynamic_cast
for shared pointers.)
In the middle section of the method, the engine extracts from the passed arguments any information not already presented in digested form. Shown here is the retrieval of the spot price of the underlying; other quantities needed by the engine, e.g., the forward price of the underlying and the risk-free discount factor at maturity, are also extracted. (You can find the full code of the engine in the QuantLib sources.)
Finally, the calculation is performed and the results are stored in
the corresponding slots of the results structure. This concludes both
the calculate
method and the example.
Bibliography
[1] B. Stroustrup, The C++ Programming Language, 4th edition. Addison-Wesley, 2013.