Chapter 3, part 6 of n: volatility term structures
Welcome back.
Two bit of news about the QuantLib site. The first is that we finally collected the material from the QuantLib User Meeting in Düsseldorf, and the slides for most of the talks are now available on the documentation page. The second is that the QuantLib site itself was renovated; I hope that the navigation is a bit more clear now, and that it will be simpler to find stuff.
As promised, this week’s post has some new book content. At last, we’re nearing the end of chapter 3; all that’s missing is a couple of short sections on interest-rate volatilities.
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.
Term structures
Volatility term structures
There are so many types of volatility structures that finding common
behavior between them is a bit of a stretch. In fact, I’m not sure
that the base class we defined for them (the VolatilityTermStructure
class, shown in listing 3.16) is a useful abstraction.
Listing 3.16: Interface of the VolatilityTermStructure
class.
The class adds two things to TermStructure
, from which it
inherits. The first is a method, optionDateFromTenor
, that
calculates the exercise date of an option from its tenor; to do this,
it used the calendar provided by the base-class interface as well as a
business-day convention stored in this class (which is passed to the
constructors, and from which the usual inspector is
provided). Instead, this functionality could be encapsulated in some
kind of utility class and used elsewhere. (The idea of such date
calculator was suggested years ago on the mailing list by someone who
will forgive me if I can no longer recall nor find out his name.)
The second addition involves two pure virtual methods that return the minimum and maximum strike over which the term structure is defined and a protected method that checks a given strike against the defined range. Unfortunately, these don’t make sense for a local volatility structure; but leaving them out would require yet another level of hierarchy to hold them (namely, an implied-vol structure class) so I’m not shocked to see them here instead.
Equity volatility structures
Equity and FX-rate Black volatilities are modeled by the
BlackVolTermStructure
class, shown in listing 3.17. Apart from its
several constructors (which, as usual, forward their arguments to the
base class and would be made unnecessary by constructor inheritance,
introduced in C++11 [1]) the class defines the overloaded blackVol
method to retrieve the volatility for a given exercise date or time;
the blackVariance
method for the corresponding variance (the product
of the square of the volatility by the time); and the
blackForwardVol
and blackForwardVariance
methods for the forward
volatility and variance between two future dates.
Listing 3.17: Partial interface of the BlackVolTermStructure
class.
Following the Template Method pattern (no surprise there) all these
methods are implemented by calling the protected and pure virtual
blackVolImpl
and blackVarianceImpl
methods. The public interface
adds range checking and, in the case of forward volatility or
variance, the bit of logic required to calculate the forward values
from the spot values at the two passed dates.
At the time of this writing, the BlackVolTermStructure
class also
defines a private static const
data member dT
that is no longer
used—much like we still carry around an appendix, or a vestigial
tailbone. By the time you read this, I hope to have it removed. The
data member, I mean. Not my appendix.
As usual, adapters are provided to write only one of the
blackVolImpl
or the blackVarianceImpl
method; they are shown in
listing 3.18. (For simple examples of either kind, you can look at the
ConstantBlackVol
and the misleadingly-named
ImpliedVolTermStructure
classes in the library.) It is unfortunate
that the name of one of the adapters, the
BlackVolatilityTermStructure
class, is so confusingly similar to the
name of the base class. I’m open to suggestions for changing either
one in a future version of the library.
Listing 3.18: Adapters for the BlackVolTermStructure
class.
Aside: Interpolations and extrapolations.
One of the available volatility classes is the BlackVarianceSurface
class, which interpolates a matrix of quoted Black volatilities. I
won’t describe it here, since you’re probably sick of term-structure
examples by now; but it has a couple of interesting features.
The first is that the interpolation can be changed once the structure is built; the relevant method is
This is not possible in other interpolated curves, in which the type
of the interpolation is a template argument and is fixed at
instantiation; see, for instance, the PiecewiseYieldCurve
class
template in this post. The difference is
that BlackVarianceSurface
doesn’t need to store the interpolator,
and thus doesn’t need to know its type outside the setInterpolation
method.
The second feature of BlackVarianceSurface
is the possibility to
customize the kind of extrapolation to use when the passed strike is
outside the range of the interpolation. It is possible either to
extend the underlying interpolation or to extrapolate flatly the value
at the end of the range; the behavior at either end can be specified
independently.
Now, it would be nice if this behavior could be extracted in some base class and reused. The choice of extrapolation can be implemented in a generic way; given any interpolation \( f \) defined up to \( x_{max} \) (or down to \( x_{min} \)), and given an \( x > x_{max} \), the two choices can be realized by returning \( f(x) \) for extension of \( f(x_{max}) \) for flat extrapolation.
The Extrapolator
class would seem the obvious choice for defining
such behavior; but, unfortunately, this wouldn’t work if we still want
to make different choices on different boundaries. As a base class,
Extrapolator
would have no knowledge of the fact that, for instance,
an interest-rate structure is defined over a time range whose lower
bound is 0, while a volatility surface also has a range of
strikes. Since it can’t distinguish between boundaries, Extrapolator
can’t define an interface that specifies behavior on any of them; we’d
be forced to make a single choice and apply it everywhere.
Therefore, the only possibility I see for code reuse at this time
would be to define a polymorphic Extrapolation
class, code the
different behaviors into derived classes, and store the required
number of instances into any given term structure.
Bibliography
[1] International Standards Organization, Programming Languages – C++, International Standard ISO/IEC 14882:2011. Available as a working draft.