Chapter 4, part 3 of 5: coupon examples
Welcome back.
This post is the third in a series covering chapter 4 of my book; the first post is here. This week, a few examples of interest-rate coupons.
Registration for my Introduction to QuantLib Development course is still open; it’s three days of presentations and exercises about the architecture of QuantLib, and it’s going to be in London from 24 to 26 March. 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.
Example: LIBOR coupons
The most common kind of floating-rate coupon is the one paying the rate fixed by a LIBOR index. A minimal implementation of such a coupon is shown in listing 4.6.
Listing 4.6: Minimal implementation of the IborCoupon
class.
The only required member is the constructor. It takes the same
arguments as FloatingRateCoupon
, but specializes the type of the
passed index; it constrains this argument to be a pointer to an
instance of the IborIndex
class, rather than the more generic
InterestRateIndex
(the Ibor name was generalized from the common
suffix of EURIBOR, LIBOR, and a number of like indexes). All arguments
are simply forwarded to the constructor of the parent class; index
needs no particular treatment, since shared pointers to a derived
class can be implicitly upcast to pointers to its base class.
Of course, the real pricing work wil be done by pricers. Listing 4.7
shows a partial implementation of one of them, namely, the
BlackIborCouponPricer
class; the Black part of the name refers to
the Black model used for calculating the adjustment (if any) and
possible caps or floors on the index fixing.
Listing 4.7: Partial implementation of the BlackIborCouponPricer
class.
The constructor takes a handle to a term structure that describes the volatility of the LIBOR rate, stores it, and registers with it as an observer. If the coupon rate is not fixed in arrears, and if no cap or floor is defined, the volatility is not used; in that case, the handle can be empty (or can be omitted from the constructor call).
The initialize
method checks that the passed coupon has the correct
type by downcasting it to IborCoupon
. If the cast succeeds, a few
results can then be precomputed. Here—more for illustration than
for anything else—we store the coupon gearing and spread in two
data members; this will allow to write the remaining code more
concisely. The swapletRate
method simply applies the stored gearing
and spread to the adjusted rate, whose calculation is delegated to the
adjustedFixing
method. If the coupon fixes at the beginning of its
tenor, the adjusted rate is just the fixing of the underlying
index. If the coupon fixes in arrears, a convexity adjustment is
calculated and added to the fixing; I don’t show the formula
implementation here, but only the check for a valid caplet
volatility. Other methods such as capletRate
are not shown here; you
can read their implementation in the library.
This would be all (and would make for a clean but very short example) were it not for those meddling kids—namely, for the common practice of using par coupons to price floating-rate notes. The library should allow one to choose whether or not to follow this practice; and as usual, there’s at least a couple of ways to do it.
One possible way (shown in listing 4.8) is to bypass the pricer
machinery and override the rate
method for LIBOR coupons.
Listing 4.8: Extension of the IborCoupon
class to support par coupons.
If par coupons are enabled by setting a compilation flag, and if the coupon is not in arrears (in which case we still need a pricer), a built-in par-rate calculation is used; otherwise, the method call is forwarded to the base-class method, which in turn delegates the calculation to the pricer. This works, but it has disadvantages. On the one hand, one can still set pricers to the coupon, but with no observable effect. On the other hand, different index fixings would be used for in-arrears and not in-arrears coupons fixing on the same date, which could throw off parity relationships or, worse, hedges.
A probably better way would be to implement a par-coupon pricer explicitly. As shown in listing 4.9, this can be done by inheriting from the Black pricer described earlier.
Listing 4.9: Sketch of the ParCouponPricer
class.
The derived pricer just needs to override the adjustedFixing
method;
instead of asking the stored index for its fixing, it would extract
its risk-free curve and use it to calculate the par rate. This is
somewhat cleaner than overriding rate
in the coupon class, doesn’t
suffer from the same disadvantages, and allows one to make the choice
at run time.
This approach still has a problem, though; the convexityAdjustment
method will return the difference between the par fixing and the index
fixing, which is not due to convexity effects. (The same problem must
be faced when overriding the coupon’s rate
method.) Unfortunately,
it is not clear how to fix this—or at least, it is not clear to
me—although a few possibilities come to mind. One is to override
convexityAdjustment
to detect par coupons and return a null
adjustment, but it wouldn’t work for in-arrears coupons. Another is to
rename the method to adjustment
and make it more generic, but this
would lose information. The best one is probably to delegate the
calculation of the convexity adjustment to the pricer; this might also
help to overcome the fragility issues that I mentioned on the
previous post when I described
the adjustedFixing
method.
The current way? It’s a bit of a bummer. Read the aside below.
Aside: breach of contract.
The current implementation of IborCoupon
enables par coupons by
overriding the indexFixing
method and making it return the par
rate. It works, in a way; the coupon methods return the correct
amount, and even the expected null convexity adjustment (the latter
doesn’t hold for other implementations and might be the reason of this
choice).
However, the implementation is wrong, since it breaks the semantics of the method; it no longer returns the index fixing. A future release should change the code so that the whole class interface works as declared.
Example: capped/floored coupons
Caps and floors are features that can be applied to any kind of
floating-rate coupon. In our framework, that means that we’ll want to
add the features, possibly in a generic way, to a number of classes
derived from FloatingRateCoupon
.
This requirement suggests some flavor of the Decorator pattern. The
implementation of the resulting CappedFlooredCoupon
class is shown
in listing 4.10.
Listing 4.10: Implementation of the CappedFlooredCoupon
class.
As we will see shortly, the class follows the canonical form of the
Decorator pattern, storing a pointer to the base FloatingRateCoupon
class, adding behavior where required and calling the methods of the
stored object otherwise. However, note that C++, unlike other
languages, provides another way to implement the Decorator pattern:
namely, we could have combined templates and inheritance to write
something like
This class template would be used to instantiate a number of classes
(such as, e.g., CappedFloored<IborCoupon>
or
CappedFloored<CmsCoupon>
) that would add behavior where required and
call the methods of their respective base classes otherwise. At this
time, I don’t see any compelling reason for the template
implementation to replace the existing one; but out of interest,
during the description of CappedFlooredCoupon
—which I’ll start
without further ado—I’ll point out where the class template
would have differed, for better or worse.
Not surprisingly, the constructor takes a FloatingRateCoupon
instance to decorate and stores it in a data member.
What might come as a surprise is that the constructor also extracts
data from the passed coupon and copies them into its own data members
by passing them to the base FloatingRateCoupon
constructor. This is
a departure from the usual implementation of the pattern, which would
forward all method calls to the stored underlying coupon using code
such as
Instead, this implementation holds coupon state of its own and uses it
to provide non-decorated behavior; for instance, the startDate
method will just return the copied data member. This causes some
duplication of state, which is not optimal; but on the other hand, it
avoids writing quite a few forwarding methods. The alternative would
be to make all Coupon
methods virtual and override them all.
The design might be a bit cleaner if we were to use template inheritance. In that case, the coupon to be decorated would be the decorator itself, and duplication of state would be avoided. However, the constructor would still need to copy state; we’d have to write it as
and not in the more desirable way, i.e., as a constructor taking the
arguments required to instantiate the underlying; we’d have to build
it externally to pass it, copy it, and throw it away afterwards. This
is on the one hand, because of the so-called forwarding problem [1];
and on the other hand, because coupons tend to take quite a few
parameters, and we’d probably need to give CappedFlooredCoupon
about
a dozen template constructors to accept them all. Note that both
problems are due to the fact that we’re still using C++03 to support
older compiler; they would be solved in C++11 by perfect forwarding
[2] and variadic templates [3], respectively, so we might revisit this
design in the future.
The other constructor arguments are the cap and floor rates. If either
of them is not needed, client code can pass Null<Rate>()
to disable
it. The passed rates are stored in two data members—with a
couple of twists. The first is that, besides two data members for the
cap and floor rates, the class also stores two booleans that tell
whether they’re enabled or disabled. This is somewhat different from
what is done in several other places in the library; usually, we just
store the value and rely on comparison with Null<Rate>()
to see
whether it’s enabled. Storing a separate boolean member might seem
redundant, but it avoids using the null value as a magic number. It
would be better yet to use a type, such as boost::optional
, that is
designed to store a possibly null value and has cleaner semantics. In
fact, I’d like to delete the Null
class and replace it with
optional
everywhere, but it would break too much client code at this
time.
The second twist is that a cap might not be stored as a cap. If the
gearing of the underlying is positive, all is as expected. If it’s
negative, the cap is stored in the floor_
data member and vice
versa. This was probably based on the fact that, when the gearing is
negative, a cap on the coupon rate is in fact a floor on the
underlying index rate. However, it might be confusing and complicates
both the constructor and the inspectors. I think it would be better to
store the cap and floor as they are passed.
The rate
method is where the behavior of the underlying coupon is
decorated.
In our case, this means modifying the coupon rate by adding a floorlet rate (i.e., the rate that, accrued over the life of the coupon, gives the price of the floorlet) and subtracting a caplet rate. The calculation of the two rates is delegated to the pricer used for the underlying coupon, which requires as arguments the effective cap and floor rates; as we’ll see shortly, these are the cap and floor rates that apply to the underlying index fixing rather than to the coupon rate.
The next method is convexityAdjustment
.
It forwards to the corresponding method in the underlying coupon, and returns the result without changes (incidentally, we’d get this behavior for free—i.e., without having to override the method—if we were to use template inheritance). This might look a bit strange, since applying the cap or floor to the coupon can change the rate enough to make the adjustment moot; but taking the cap and floor rates into account would change the meaning of the method, which was defined to return the adjustment of the underlying index fixing.
The cap
and floor
inspectors return the passed cap and floor,
possibly performing an inverse flip if a negative coupon gearing
caused the constructor to flip the cap and floor data members.
As I said, this might be improved by storing cap and floor
unmodified. If necessary, the flip would be performed inside the
effectiveCap
and effectiveFloor
method, that currently (the flip
being already performed) only adjust the cap and floor for the coupon
gearing and spread, thus returning the cap and floor on the underlying
index fixing.
Finally, the setPricer
method.
In order to keep everything consistent, the passed pricer is set to both the underlying coupon and to this instance. It smells a bit: it’s a bit of duplication of state, and a bit more work than would be necessary if we had written a pure Decorator—or if we had used template inheritance. But I’ve committed worse sins in my life as a developer; and such duplication as we have is confined in this single method.
At this point, the CappedFlooredCoupon
class is complete. To wrap up
the example, I’ll mention that it’s possible to inherit from it as a
convenience for instantiating capped or floored coupons; one such
derived class is shown in listing 4.11 and specializes the base class
to build capped or floored LIBOR coupons.
Listing 4.11: Implementation of the CappedFlooredIborCoupon
class.
The class only defines a constructor; instead of a built coupon
instance, it takes the arguments needed to build the underling coupon,
instantiates it, and passes it to the constructor of the base
class. This way, it takes away a bit of the chore in creating a
coupon. The implementation would be identical if CappedFlooredCoupon
were a class template.
Finally, a word on a possible alternative implementation. The class I described in this example applies a cap and a floor, both possibly null; which forces the class to contain a couple of booleans and some logic to keep track of what is enabled or disabled. This might be avoided if the cap and the floor were two separate decorators; each one could be applied separately, without the need of storing a null for the other one. However, two separate decorators with similar semantics would probably cause some duplicated code; and one decorator with a flag to select whether it’s a cap or a floor would need some logic to manage the flag. If you want to get some exercise by giving this implementation a try, you’re welcome to contribute it to see how it compares to the current one.
Bibliography
[1] P. Dimov, H.E. Hinnant and D. Abrahams, The Forwarding Problem:
Arguments. C++
Standards Committee Paper N1385, 2002.
[2] H.E. Hinnant, B. Stroustrup and B. Kozicki, A Brief Introduction
to Rvalue
References. C++
Standards Committee Paper N2027, 2006.
[3] D. Gregor, A Brief Introduction to Variadic
Templates. C++
Standards Committee Paper N2087, 2006.