# Chapter 3, part 2 of n: Yield term structures

Hello everybody.

This post is the second in a series of a still undetermined number; the first part is here.

Call me a slowcoach (or whatever the expression might be in your part of the world), but I only found out this week that there’s a Twitter feed for the Quantitative Finance Stack Exchange site. I’ll be retweeting the QuantLib-related questions when the answers are useful, so you can push that “follow” button on the right if you’re interested in those but don’t want to get the full site feed. Or you can push it anyway. I won’t mind.

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

### Yield Term Structures

The `YieldTermStructure`

class predates `TermStructure`

—in fact,
it was even called `TermStructure`

back in the day, when it was the
only kind of term structure in the library and we still hadn’t seen
the world. Its interface provides the means to forecast interest rates
and discount factors at any date in the curve domain; also, it
implements some machinery to ease the task of writing a concrete yield
curve.

#### Interface and implementation

The interface of the `YieldTermStructure`

class is sketched in listing
3.3.

Listing 3.3: Partial interface of the `YieldTermStructure`

class.

The constructors just forward their arguments to the corresponding
constructors in the `TermStructure`

class—nothing to write home
about. The other methods return information on the yield structure in
different ways: on the one hand, they can return zero rates, forward
rates, and discount factors (rates are returned as instances of the
`InterestRate`

class, that I’ll describe briefly in a future post); on
the other hand, they are overloaded so that they can return
information as function of either dates or times.

Of course, there is a relationship between zero rates, forward rates,
and discount factors; the knowledge of any one of them is sufficient
to deduce the others. (I won’t bore you with the formulas
here—you know them.) This is reflected in the implementation,
outlined in listing 3.4; the Template Method patterns is used to
implement all public methods directly or indirectly in terms of the
protected `discountImpl`

abstract method. Derived classes only need to
implement the latter in order to return any of the above quantities.

Listing 3.4: Partial implementation of the `YieldTermStructure`

class.

#### Discount, forward-rate, and zero-rate curves

What if the author of a derived class doesn’t want to implement
`discountImpl`

, though? After all, one might want to describe a yield
curve in terms, say, of zero rates. Ever ready to serve (just like
Jeeves in the P. G. Wodehouse novels—not that you’re Bernie
Wooster, of course) QuantLib provides a couple of classes to be used
in this case. The two classes (outlined in listing 3.5) are called
`ZeroYieldStructure`

and `ForwardRateStructure`

. They use the Adapter
pattern (in case you’re keeping count, this would be another notch in
the spine of our Gang-of-Four book) to transform the discount-based
interface of `YieldTermStructure`

into interfaces based on zero-yield
and instantaneous-forward rates, respectively.

Listing 3.5: Outline of the `ZeroYieldStructure`

and
`ForwardRateStructure`

classes.

The implementation of `ZeroYieldStructure`

is simple enough. A few
constructors (not shown here) forward their arguments to the
corresponding constructors in the parent `YieldTermStructure`

class. The Adapter pattern is implemented in the protected section: an
abstract `zeroYieldImpl`

method is declared and used to implement the
`discountImpl`

method. Thus, authors of derived classes only need to
provide an implementation of `zeroYieldImpl`

to obtain a fully
functional yield curve. (Of course, the other required methods (such
as `maxDate`

) must be implemented as well.) Note that, due to the
formula used to obtain the discount factor, such method must return
zero yields as continuously-compounded annualized rates.

In a similar way, the `ForwardRateStructure`

class provides the means
to describe the curve in terms of instantaneous forward rates (again,
on an annual basis) by implementing a `forwardImpl`

method in derived
classes. However, it has an added twist. In order to obtain the
discount at a given time T, we have to average the instantaneous
forwards between 0 and T, thus retrieving the corresponding zero-yield
rate. This class can’t make any assumption on the shape of the
forwards; therefore, all it can do is to perform a numerical
integration—an expensive calculation. In order to provide a hook
for optimization, the average is performed in a virtual
`zeroYieldImpl`

method that can be overridden if a faster calculation
is available. You might object that if an expression is available for
the zero yields, one can inherit from `ZeroYieldStructure`

and be done
with it; however, it is conceptually cleaner to express the curve in
terms of the forwards if they were the actual focus of the model.

The two adapter classes I just described and the base
`YieldTermStructure`

class itself were used to implement interpolated
discount, zero-yield, and forward curves. Listing 3.6 outlines the
`InterpolatedZeroCurve`

class template; the other two
(`InterpolatedForwardCurve`

and `InterpolatedDiscountCurve`

) are
implemented in the same way.

Listing 3.6: Outline of the `InterpolatedZeroCurve`

class template.

The template argument `Interpolator`

has a twofold task. On the one
hand, it acts as a traits class [1]. It specifies the kind of
interpolation to be used as well as a few of its properties, namely,
how many points are required (e.g., at least two for a linear
interpolation) and whether the chosen interpolation is global (i.e.,
whether or not moving a data point changes the interpolation in
intervals that do not contain such point; this is the case, e.g., for
cubic splines). On the other hand, it doubles as a poor man’s factory;
when given a set of data points, it is able to build and return the
corresponding `Interpolation`

instance. (The `Interpolation`

class
will be described in a later post).

The public constructor takes the data needed to build the curve: the
set of dates over which to interpolate, the corresponding zero yields,
the day counter to be used, and an optional `Interpolator`

instance. For most interpolations, the last parameter is not needed;
it can be passed when the interpolation needs parameters. The
implementation forwards to the parent `ZeroYieldStructure`

class the
first of the passed dates, assumed to be the reference date for the
curve, and the day counter; the other arguments are stored in the
corresponding data members. After performing a few consistency checks,
it converts the dates into times (using, of course, the passed
reference date and day counter), asks the interpolator to create an
`Interpolation`

instance, and stores the result.

At this point, the curve is ready to be used. The other required
methods can be implemented as one-liners; `maxDate`

returns the latest
of the passed dates, and `zeroYieldImpl`

returns the interpolated
value of the zero yield. Since the `TermStructure`

machinery already
takes care of range-checking, the call to the `Interpolation`

instance
includes a `true`

argument. This causes the value to be extrapolated
if the passed time is outside the given range.

Finally, the `InterpolatedZeroCurve`

class also defines a few
protected constructors. They take the same arguments as the
constructors of its parent class `ZeroYieldStructure`

, as well as an
optional `Interpolator`

instance, and forward them to the
corresponding parent-class constructors; however, they don’t create
the interpolation—they cannot, since they don’t take any
zero-yield data. These constructors are defined so that it is possible
to inherit from `InterpolatedZeroCurve`

; derived classes will provide
the data and create the interpolation based on whatever arguments they
take (an example of this will be shown in the remainder of this
section). For the same reason, most data members are declared as
mutable; this makes it possible for derived classes to update the
interpolation lazily, should their data change.

#### Aside: symmetry break.

You might argue that, as in George Orwell’s *Animal Farm*, some term
structures are more equal than others. The discount-based
implementation seems to have a privileged role, being used in the base
`YieldTermStructure`

class. A more symmetric implementation might
define three abstract methods in the base class (`discountImpl`

,
`zeroYieldImpl`

, and `forwardImpl`

, to be called from the
corresponding public methods) and provide three adapters, adding a
`DiscountStructure`

class to the existing ones.

Well, the argument is sound; in fact, the very first implementation of
the `YieldTermStructure`

class was symmetric. The switch to the
discount-based interface and the reasons thereof are now lost in the
mists of time, but might have to do with the use of `InterestRate`

instances; since they can require changes of frequency or compounding,
`zeroYield`

(to name one method) wouldn’t be allowed to return the
result of `zeroYieldImpl`

directly anyway.

#### Aside: twin classes.

You might guess that code for interpolated discount and forward curves would be very similar to that for the interpolated zero-yield curve described here. The question naturally arises: would it be possible to abstract out common code? Or maybe we could even do with a single class template?

The answers are yes and no, respectively. Some code can be abstracted
in a template class (in fact, this has been done already). However,
the curves must implement three different abstract methods
(`discountImpl`

, `forwardImpl`

, and `zeroYieldImpl`

) so we still need
all three classes as well as the one containing the common code.

#### Bibliography

[1] N.C. Myers, *Traits: a new and useful template
technique*. In *The C++ Report*,
June 1995.