Monday, January 27, 2014

Chapter 4, part 2 of 5: floating-rate coupons

Welcome back.

Today's post is the second part of a series that started here and covers chapter 4 of my book.

In other news, you're still in time to register for my Introduction to QuantLib Development course with a 10% early-bird discount. If you haven't been here recently, it's the course that I teach once or twice a year based on the contents of my book. A good part of the learning experience is doing a number of exercises (which you don't get to do on the blog) so you'll have to bring your laptop and get ready to code.

Follow me on Twitter if you want to be notified of new posts, or add me to your circles, or subscribe via RSS: the widgets for that are in the sidebar, at the top right of the page. Also, make sure to check my Training page.

Floating-rate coupons

The FloatingRateCoupon class is emblematic of the life of most software. It started simple, became more complex as time went by, and might now need some refactoring; its current implementation (sketched in listing 4.4) has a number of issues that I'll point out as I describe it. (Unless they can be fixed without breaking backward compatibility, we'll have to live with any shortcomings until the yet unplanned release 2.0.)

Listing 4.4: Sketch of the FloatingRateCoupon class.
    class FloatingRateCoupon : public Coupon, public Observer {
public:
FloatingRateCoupon(
const Date& paymentDate,
const Real nominal,
const Date& startDate,
const Date& endDate,
const Natural fixingDays,
const shared_ptr<InterestRateIndex>& index,
const Real gearing = 1.0,
const Date& refPeriodStart = Date(),
const Date& refPeriodEnd = Date(),
const DayCounter& dayCounter = DayCounter(),
bool isInArrears = false);

Real amount() const;
Rate rate() const;
Real accruedAmount(const Date&) const;
DayCounter dayCounter() const;

const shared_ptr<InterestRateIndex>& index() const;
Natural fixingDays() const;
Real gearing() const;
virtual Date fixingDate() const;
virtual Rate indexFixing() const;
bool isInArrears() const;

void update();
virtual void accept(AcyclicVisitor&);

void setPricer(const shared_ptr<FloatingRateCouponPricer>&);
shared_ptr<FloatingRateCouponPricer> pricer() const;
protected:
// data members
};

The first issue might be the name itself: FloatingRateCoupon suggests a particular type of coupon, i.e., one that pays some kind of LIBOR rate. However, the class is more general that this and can model coupons paying different kind of rates—CMS or whatnot. Unfortunately, other names might be even worse; for instance, the one I briefly considered while writing this paragraph (VariableRateCoupon) suggests that the definition of the rate might change besides the value, which is not the case. All in all, I don't think there's any point in changing it now.

But enough with my ramblings; let's look at the implementation.
    FloatingRateCoupon::FloatingRateCoupon(
const Date& paymentDate, const Real nominal,
...other arguments...)
: Coupon(nominal, paymentDate,
startDate, endDate, refPeriodStart, refPeriodEnd),
/* store the other data members */ {
registerWith(index_);
registerWith(Settings::instance().evaluationDate());
}

The constructor takes (and forwards to the base-class constructor) the dates and notional needed by the Coupon class, a day counter, and a number of arguments related to the interest-rate fixing. These include an instance of the InterestRateIndex class taking care of the rate calculation (see this post for details on this class; for the purpose of this section, it is enough to note that it can retrieve past index fixings and forecast future ones) as well as other details of the fixing; namely, the number of fixing days, whether or not the rate is fixed in arrears, and an optional gearing and spread. The arguments that are not passed to the Coupon constructor are stored in data members; moreover, the instance registers as an observer of its interest-rate index and of the current evaluation date. As we will see shortly, the fixingDays and inArrears arguments are used to determine the fixing date. When given, the gearing and spread cause the coupon to pay a rate R = g × F + s where g is the gearing, F is the fixing of the underlying index, and s is the spread. (In principle, one could model reverse-floater coupons by passing a negative gearing; but in practice, this is not advisable as it would neglect the implicit floor at zero that such coupons usually sport.)

This choice of the constructor signature (and therefore, of the stored data members) implies a constraint on the kinds of coupon that can be adequately modeled by this class. We are limiting them to those whose rate is based on the fixing of a single index; others, such as those paying the spread between two rates, are excluded. True, they can be forcibly bolted on the FloatingRateCoupon class by creating some kind of spread class and inheriting it from InterestRateIndex; but this would somewhat break the mapping between the financial concepts being modeled and the class hierarchy, since the spread between two indexes is not itself an index (or at least, it is not usually considered one).

Other methods implement the required CashFlow and Coupon interfaces.
    Real FloatingRateCoupon::amount() const {
return rate() * accrualPeriod() * nominal();
}

Rate FloatingRateCoupon::rate() const {
pricer_->initialize(*this);
return pricer_->swapletRate();
}

Curiously enough, even though floating-rate coupons are more complex than fixed-rate ones, the amount method has the simpler implementation: it multiplies the rate by the accrual time and the nominal. This seems to support moving it to the Coupon class. The accrualAmount method has a similar implementation (not shown in the listing) with a different accrual time. For the time being, I'll skip the rate method; we'll come back to its implementation in a short while.

Next come a number of inspectors. Besides dayCounter (which is required by the Coupon interface) we have those returning the parameters specific to floating-rate coupons, such as index, fixingDays, gearing, and spread. Finally, a number of methods are defined which implement some business logic.

    Date FloatingRateCoupon::fixingDate() const {
Date d = isInArrears_ ? accrualEndDate_ : accrualStartDate_;
d, -fixingDays_, Days, Preceding);
}

Rate FloatingRateCoupon::indexFixing() const {
return index_->fixing(fixingDate());
}

The first two methods are fixingDate and indexFixing. They are both straightforward enough. The fixingDate method checks whether or not the coupon fixes in arrears, chooses a reference date accordingly (the end date of the coupon when in arrears, the start date otherwise) and moves it backward for the required fixing days; holidays are skipped according to the index calendar. The indexFixing method asks the stored index for its fixing at the relevant date.

Although the implementations of both methods are, as I said, straightforward, there is an issue with their signature. Just as the constructor assumes a single index, these two methods assume a single index fixing. This results in a loss of generality; for instance, it excludes coupons that pay the average fixing of an index over a set of several fixing dates, or that compounds rates over a number of sub-periods of the coupon life.

The last methods deal with the convexity adjustment (if any) to apply to the index fixing.
    Rate FloatingRateCoupon::adjustedFixing() const {
}

return (gearing() == 0.0 ? 0.0 : adjustedFixing()-f);
}

}

The adjustedFixing method is written in terms of the rate method and inverts the R = g × F' + s formula to return the adjusted fixing F' = (R - s)/g. Its implementation is rather fragile, since it depends on the previous relationship between the rate and the fixing. If a derived class were to modify it (for instance, by adding a cap or floor to the paid rate—which has happened already, as we'll see later) this method should be modified accordingly. Unfortunately, this is left to the programmer; there's no language feature that can force one to override two methods at the same time.

The convexityAdjustment method returns the adjustment alone by taking the difference between the original fixing and the adjusted one. It does this by delegating to a protected convexityAdjustmentImpl method; this is a leftover of a previous implementation, in which the presence of a separate method allowed us to optimize the calculation. This is no longer needed in the current implementation; for the sake of simplicity, the protected method might be inlined into the public one and removed.

Aside: keeping one's balance.

The assumptions built into the FloatingRateCoupon class (single index, single fixing date) are, of course, unfortunate. However, it is caused by the need to balance generality and usefulness in the class interface; the more general a class is, the fewer inspectors it can have and the less information it can return. The problem could be solved in part by adding more levels of inheritance (we might do that, if the need arises); but this adds complexity and brings its own problems. The current implementation of FloatingRateCoupon is probably not the best compromise; but it's one we can live with for the time being.

Back to the rate method. In previous versions of the library, it was implemented as you might have expected—something like
    Rate f = index_->fixing(fixingDate());

based on the fixing provided by the stored InterestRateIndex instance. (As you might have noted, the current convexityAdjustment implementation would cause an infinite recursion together with the code above. Its implementation was also different at that time and returned an explicit calculation of the adjustment.) As much as I liked its simplicity, that implementation had to be changed when a new requirement came in: namely, that floating-rate coupons may be priced in several different ways. This was an issue that we had already faced with the Instrument class (see this post for details).

Like we did for Instrument, we used the Strategy pattern [1] to code our solution. However, the implementation we chose in this case was different. On the one hand, the context was more specific; we knew what kind of results we wanted from the calculations. On the other hand, FloatingRateCoupon had a richer interface than Instrument. This allowed us to avoid the opaque argument and result structures used in the implementation of the PricingEngine class.

The resulting FloatingRateCouponPricer class is sketched in listing 4.5.

Listing 4.5: Sketch of the \texttt{FloatingRateCouponPricer} class.
    class FloatingRateCouponPricer: public virtual Observer,
public virtual Observable {
public:
virtual ~FloatingRateCouponPricer();
virtual void initialize(const FloatingRateCoupon&) = 0;
virtual Rate swapletRate() const = 0;
virtual Rate capletRate(Rate effectiveCap) const = 0;
virtual Rate floorletRate(Rate effectiveFloor) const = 0;
// other methods
};

It declares methods for returning a number of rates: swapletRate returns the coupon rate, adjusted for convexity, gearing and spread (if any); capletRate returns the adjusted rate paid by a cap on the index fixing; and floorletRate returns does the same for a floor. (The class declares other methods, not shown here.) The initialize method causes the pricer to store a reference to the passed coupon that will provide any information not passed to the other methods as part of the argument list.

The FloatingRateCoupon class defines a setPricer method that takes a pricer instance and stores it into the coupon. (The implementation is not as simple as that, but we can skip the details here.) Finally, the rate method is defined as shown below: the stored pricer is initialized with the current coupon and the calculated rate is returned.
    Rate FloatingRateCoupon::rate() const {
pricer_->initialize(*this);
return pricer_->swapletRate();
}

You might have noted that initialization is performed in the rate method, rather than in the setPricer method. This is done because the same pricer instance can be used for several coupons; therefore, one must make sure that the current coupon is stored each time the pricer is asked for a result. A previous calculation might have stored a different reference—which by now might even be dangling.

Of course, this implementation is not entirely satisfactory (and furthermore, it hinders parallelism, which is becoming more and more important since the last couple of years; as of now, we cannot pass the same pricer to several coupons and evaluate them simultaneously). It might have been a better design to define the pricer methods as, for instance,
    Rate swapletRate(const FloatingRateCoupon& coupon);

and avoid the repeated call to initialize. Once again, I have to admit that we are guilty of premature optimization. We thought that, when swapletRate and other similar methods were called in sequence (say, to price a floored coupon), a separate initialization method could precompute some accessory quantities that would be needed in the different rate calculations; and we let that possibility drive the design. As it turned out, most pricers do perform some computations in their initialize method; but in my opinion, not enough to justify doing a Texas two-step to calculate a rate.

A refreshing remark to end this section. If you want to implement a specific floating-rate coupon but you don't care for the complexity added by the pricer machinery, you can inherit your class from FloatingRateCoupon, override its rate method to perform the calculation directly, and forget about pricers. They can be added later if the need arises.

Bibliography

[1] E. Gamma, R. Helm, R. Johnson and J. Vlissides, Design Patterns: Element of Reusable Object-Oriented Software. Addison-Wesley, 1995.

Monday, January 20, 2014

Chapter 4, part 1 of 5: Cash flows and coupons

Welcome back.

This week, I'm starting a new series of posts on chapter 4. Into the limelight: the various kinds of cash flows and coupons, and what we can do with them.

Did I mention that I'll teach another Introduction to QuantLib Development course in March? In the tasteful banner above there's a link for more details and for registering. Click on it. Also, what with the holidays and all, you might have missed the new Bibliography page on this blog. Go check it now if you still didn't.

On the QuantLib front, not much to say—yet. I'm currently knee-deep in version-control logs, looking at the changes since the 1.3 release and deciding if I should do a bug-fix 1.3.1 release or a 1.4 release with the new features people have contributed. It will depend on how much new stuff there is. I'll let you know as soon as I pick one.

Follow me on Twitter if you want to be notified of new posts, or add me to your circles, or subscribe via RSS: the widgets for that are in the sidebar, at the top right of the page. Also, make sure to check my Training page.

Cash flows and coupons

"Cash is king," says a sign in the office of StatPro's CFO. (I trust I'm not revealing any secret business practice.) In order to deal with the comings and goings of its Majesty (yes, I'm ironic), QuantLib must provide the means not only to price, but also to analyze coupon-bearing instruments such as bonds and interest-rate swaps. This chapter describes the classes that model different kinds of cash flows and coupons.

The CashFlow class

As usual, we start at the top of the class hierarchy. The CashFlow class provides the basic interface for all cash flows. As this level of abstraction, the information is of course rather poor; namely, the only provided inspectors return the date and amount of the cash flow. To save one from comparing dates explicitly (and for consistency, as explained in the aside below) another convenience method tells whether the cash flow has already occurred at a given date. Finally, yet another method allows cash-flow classes to take part in the Acyclic Visitor pattern [1]; an example of its use will be provided in a later post.

In earlier versions of the library, all these methods were declared in the CashFlow class. Later on, the date-related methods were moved into a separate class, Event, from which CashFlow inherits (ok, so we didn't start from the very top of the hierarchy. It's still the top of the cash-flow related classes, though. I'm not here to con you, you know) and which is reused in other parts of the code. The interfaces of the two classes are shown in listing  4.1.

Listing 4.1: Interfaces of the Event and CashFlow classes.
    class Event : public Observable {
public:
virtual Date date() const = 0;
bool hasOccurred(const Date &d) const;
virtual void accept(AcyclicVisitor&);
};

class CashFlow : public Event {
public:
virtual Real amount() const = 0;
virtual void accept(AcyclicVisitor&);
};

The library provides a simple implementation of the interface in the aptly named SimpleCashFlow class. It's boring enough that I won't show it here; it takes a date and an amount to be paid, and returns them from the date and amount methods, respectively. To find more interesting classes, we have to turn to interest-rate coupons—the subject of next section.

Aside: late payments.

The implementation of the Event::hasOccurred method is simple enough: a date comparison. However, what should it return when the cash-flow date and the evaluation date are the same—or in other words, should today's payments be included in the present value of an instrument? The answer is likely to depend on the conventions of any given desk. QuantLib lets the user make his choice by means of a few global settings; the choice can be overridden at any given time by passing the appropriate boolean flag to hasOccurred.

Interest-rate coupons

The Coupon class (shown in listing 4.2) can be used as a parent class for any cash-flow that accrues an interest rate over a given period and with a given day-count convention. Of course, it is an abstract base class; it defines additional interface methods for any such cash flow, and implements a few concrete methods dealing with date calculations.

Listing 4.2: Interface of the Coupon class.
    class Coupon : public CashFlow {
public:
Coupon(Real nominal,
const Date& paymentDate,
const Date& accrualStartDate,
const Date& accrualEndDate,
const Date& refPeriodStart = Date(),
const Date& refPeriodEnd = Date());

Date date() const {
return paymentDate_;
}

Real nominal() const {
return nominal_;
}
const Date& accrualStartDate() const;  // similar to the above
const Date& accrualEndDate() const;
const Date& referencePeriodStart() const;
const Date& referencePeriodEnd() const;
Time accrualPeriod() const {
return dayCounter().yearFraction(accrualStartDate_,
accrualEndDate_,
refPeriodStart_,
refPeriodEnd_);
}
Integer accrualDays() const;  // similar to the above

virtual Rate rate() const = 0;
virtual DayCounter dayCounter() const = 0;
virtual Real accruedAmount(const Date&) const = 0;

virtual void accept(AcyclicVisitor&);

protected:
Real nominal_;
Date paymentDate_, accrualStartDate_, accrualEndDate_,
refPeriodStart_, refPeriodEnd_;
};


The abstract interface includes a rate method, which in derived classes will return the interest rate accrued by the coupon; and the dayCounter and accruedAmount methods, which return, respectively, the day-count convention used for accrual and the cash amount accrued until the given date.

The choice to declare the rate method as purely abstract seems obvious enough. However, the same doesn't hold for the other two methods. As for dayCounter, one could make a case for storing the day counter as a data member of the Coupon class; as discussed in this post, this is what we did for the TermStructure class. Furthermore, the nominal method (which is conceptually similar) is not abstract and is based on a corresponding data member. As I'm all for abstract interfaces, I don't complain—well, apart from playing the devil's advocate here for illustration's purposes. But I admit that the asymmetry is somewhat disturbing.

The accruedAmount method is another matter; it is abstract for the wrong reason. It could have a default implementation in terms of the rate method, whose result would be multiplied by the notional and the accrual time up to the given date. To make it abstract was a choice a posteriori, due to the fact that a few derived classes define the rate method in terms of the amount method instead of the other way around. In such classes, accruedAmount is defined in terms of amount, on the dubious grounds that this might be more efficient. However, the correct choice would be to add the default implementation to the Coupon class and override it when (and if) required. We might do this in a future release. (The same could be said for the amount method; it could, too, have a default implementation.)

The rest of the interface is made of concrete methods. The constructor takes a set of data and stores them in data members; the data include the nominal of the coupon, the payment date, and the dates required for calculating the accrual time. Usually, such dates are just the start and end date of the accrual period. Depending on the chosen day-count convention, two more dates (i.e., the start and end date of a reference period) might be needed.

For each of the stored data, the Coupon class defines a corresponding inspector; in particular, the one which returns the payment date implements the date method required by the CashFlow interface. Furthermore, the accrualPeriod and accrualDays methods are provided; as shown in the listing, they use the given day-count convention and dates to implement the corresponding calculations.

Two notes before proceeding. The first is that, as for the dayCounter method, we had an alternative here between storing the relevant dates and declaring the corresponding methods as abstract. As I said, I'm all for abstract interfaces; but in this case, a bit of pragmatism suggested that it probably wasn't a good idea to force almost every derived class to store the dates as data members and implement the same inspectors. (The only derived classes that wouldn't need to store the coupon dates as data members would probably be those decorating an existing coupon.) If you like, that's yet another hint that we should make dayCounter a concrete method.

The second note: exposing the dates through the corresponding inspectors is obviously the right thing to do, as the information might be needed for reporting or all kind of purposes. However, it might also give one the idea of using them for calculations, instead of relying on the provided higher-level methods such as accrualPeriod. Of course, it's not possible to restrict access, so all we can do is warn against it.

And finally—no, I haven't forgot to describe the accept method. I'll get back to it in a future post, as we tackle the Visitor pattern.

Fixed-rate coupons

Let's now turn to concrete classes implementing the Coupon interface. The simplest is of course the one modeling a fixed-rate coupon; it is called FixedRateCoupon and its implementation is sketched in listing 4.3. Actually, the current implementation is not the very simplest: although it started as a simply-compounding coupon, it was later generalized (by a user who needed it; as you know, premature generalization is evil) to support different compounding rules.

Listing 4.3: Sketch of the FixedRateCoupon class.
    class FixedRateCoupon : public Coupon {
public:
FixedRateCoupon(Real nominal,
const Date& paymentDate,
Rate rate,
const DayCounter& dayCounter,
const Date& accrualStartDate,
const Date& accrualEndDate,
const Date& refPeriodStart = Date(),
const Date& refPeriodEnd = Date())
: Coupon(nominal, paymentDate,
accrualStartDate, accrualEndDate,
refPeriodStart, refPeriodEnd),
rate_(InterestRate(rate,dayCounter,Simple)),
dayCounter_(dayCounter) {}
Real amount() const {
return nominal() *
(rate_.compoundFactor(accrualStartDate_,
accrualEndDate_,
refPeriodStart_,
refPeriodEnd_) - 1.0);
}
Rate rate() const { return rate_; }
DayCounter dayCounter() const { return dayCounter_; }
Real accruedAmount(const Date&) const; // similar to amount
private:
InterestRate rate_;
DayCounter dayCounter_;
};


The constructor takes the arguments required by the Coupon constructor, as well as the rate to be paid and the day-count convention to be used for accrual. The constructor in the listing takes a simple rate; another constructor, not shown here for brevity, takes an InterestRate instance instead. The nominal and dates are forwarded to the Coupon constructor. while the other arguments are stored in two corresponding data members; in particular, the rate (passed as a simple floating-point number) is used to instantiate the required InterestRate.

Part of the required Coupon interface (namely, the rate and dayCounter methods) is easily implemented by returning the stored values. The remaining methods—amount and accruedAmount—are implemented in terms of the available information. The amount is obtained by multiplying the nominal by the rate, compounded over the coupon life, and subtracting the nominal in order to yield only the accrued interest. The accrued amount is obtained in a similar way, but with a different accrual period.

One final note to end this section. I mentioned earlier on that we might include in the base Coupon class a default implementation for the amount method; as you have already guessed, it would multiply the nominal by the rate and the accrual time. Well, that seemingly obvious implementation already breaks in this simple case—which seems to cast a reasonable doubt about its usefulness. Software design is never easy, is it?

Next time: floating-rate coupons.

Bibliography

[1] R.C. Martin, Acyclic Visitor. In Pattern Languages of Program Design 3. Addison-Wesley, 1997.

Monday, January 13, 2014

Chapter 3, part 7 of 7; interest-rate volatilities

Welcome back, and happy new year.

I hope you all had a nice holiday. I had a nice Christmas, thanks for asking; and I finally managed to find a couple of free afternoons to finish chapter 3. This post is the last in a series of seven that covered this chapter and that started with this one.

Important news: thanks to MoneyScience, and in particular to Jacob Bettany, I'll be in London from March 24th to 26th to teach another edition of my Introduction to QuantLib Development course. It is the course that I teach based on the contents of the Implementing QuantLib book, and you can find more information, a brochure and a booking form by clicking on this link. Yes, go ahead, click: I'll wait right here.

Done? Thanks. I look forward to see you there: I'm told London is quite nice in spring. Ok, maybe. You can probably strike that last bit.

Follow me on Twitter if you want to be notified of new posts, or add me to your circles, or subscribe via RSS: the widgets for that are in the sidebar, at the top right of the page. Also, make sure to check my Training page, even if you can't attend the course this time.

Interest-rate volatility structures

Last in our tour are interest-rate volatilities. There are three different hierarchies of them, each with its quirks.

The first hierarchy models cap and floor term volatilities; the base class is the CapFloorTermVolatilityStructure, shown in listing 3.19.

Listing 3.19: Interface of the CapFloorTermVolatilityStructure class.
    class CapFloorTermVolatilityStructure
: public VolatilityTermStructure {
public:
... // constructors, not shown
Volatility volatility(const Period& length, Rate strike,
bool extrapolate = false) const;
Volatility volatility(const Date& end, Rate strike,
bool extrapolate = false) const;
Volatility volatility(Time t, Rate strike,
bool extrapolate = false) const;
protected:
virtual Volatility volatilityImpl(Time length,
Rate strike) const = 0;
};

It is a straightforward application of the patterns seen so far, with one main difference; the volatility is not dependent on the exercise time, which is fixed to today's time, but on the maturity of the strip of caplets or floorlets of which the instrument is composed.

The difference is semantic: volatility(t,strike) has for this class a different meaning, even though the interface and the implementation are the same as for the other volatility classes. In turn, this has a couple of small consequences on the interface: on the one hand, there's an additional overload of the volatility method that takes the length of the cap as a Period instance, as seemed natural; and on the other hand, the volatility doesn't really measure the width of the distribution of any variable at time t, so the variance method was omitted.

The second hierarchy models the volatilities of single caplets and floorlets. (There are ways to convert from cap to caplet volatilities, of course, but I won't cover them here. Look into QuantLib for the OptionletStripper class and its derived classes, if you're interested in their implementation.) Its base class is the OptionletVolatilityStructure class, shown in listing 3.20.

Listing 3.20: Interface of the OptionletVolatilityStructure class.
    class OptionletVolatilityStructure
: public VolatilityTermStructure {
public:
... // constructors, not shown
Volatility volatility(const Period& optionTenor,
Rate strike,
bool extrapolate = false) const;
Volatility volatility(const Date& optionDate,
Rate strike,
bool extrapolate = false) const;
Volatility volatility(Time optionTime,
Rate strike,
bool extrapolate = false) const;

Real blackVariance(const Period& optionTenor,
Rate strike,
bool extrapolate = false) const;
// same overloads as for volatility

shared_ptr<SmileSection> smileSection(
const Period& optionTenor,
bool extrapolate = false) const;
shared_ptr<SmileSection> smileSection(
const Date& optionDate,
bool extrapolate = false) const;
shared_ptr<SmileSection> smileSection(
Time optionTime,
bool extrapolate = false) const;
protected:
virtual shared_ptr<SmileSection> smileSectionImpl(
const Date& optionDate) const;
virtual shared_ptr<SmileSection> smileSectionImpl(
Time optionTime) const = 0;

virtual Volatility volatilityImpl(const Date& d,
Rate strike) const {
return volatilityImpl(timeFromReference(d), strike);
}
virtual Volatility volatilityImpl(Time optionTime,
Rate strike) const = 0;
};

The semantics are back to normal, with the volatility being dependent on the exercise time. The structure of the class is as usual, too, but with a notable addition: besides the usual volatility method, the class declares a smileSection method that takes an exercise date (or the corresponding time or period) and returns an object that models the whole smile at that date and inherits from the base class SmileSection, shown in listing 3.21. The interface is modeled after that of the volatility class and shouldn't need explanation, apart from noting that the time is fixed and doesn't need to be passed as an argument to the various methods.

Listing 3.21: Partial interface of the SmileSection class.
    class SmileSection : public virtual Observable,
public virtual Observer {
public:
SmileSection(Time exerciseTime,
const DayCounter& dc = DayCounter());
virtual ~SmileSection() {}

virtual Real minStrike() const = 0;
virtual Real maxStrike() const = 0;
Real variance(Rate strike) const;
Volatility volatility(Rate strike) const;
virtual Real atmLevel() const = 0;
protected:
virtual Real varianceImpl(Rate strike) const;
virtual Volatility volatilityImpl(Rate strike) const = 0;
};

Simple as it seems, the addition of smile sections yields a new design that sees volatilities not as surfaces, but as collections of smiles at different times. This opens up the possibility to model the smile directly and to reuse the corresponding classes across different types of volatilities (say, for both cap/floors and swaptions).

However, we weren't bold enough to switch completely to the new interface. The two representations (the surface and the series of smiles) still coexist in the base caplet-volatility class, leading to some disadvantages. Any derived class can implement volatilityImpl in terms of smileSectionImpl as
    Volatility volatilityImpl(Time t, Real strike) const {
return smileSectionImpl(t).volatility(strike);
}

but this is only convenient if we're modeling the smile to begin with. If we're modeling the volatility surface, instead, this design makes it a lot more cumbersome to implement a new class. There's no easy way to implement smileSectionImpl in terms of volatilityImpl: we should return an object that's able to call volatilityImpl from its own volatility method, but that would link the lifetimes of the smile section and the volatility surface, and in turn raise all kind of problems. We would probably end up writing a smile-section class that contains the same code as the volatility surface; therefore, we might as well drop volatilityImpl altogether.

Unfortunately, naive implementations of the smileSectionImpl method cause new objects to be allocated at each call, which is obviously not good for performance. Smarter implementations would need to cache objects, and with this comes more complexity. Thus, the smile section is an interesting concept, but maybe more trouble than it's worth. It might be reduced in scope, and used as an implementation detail for classes that model the smile directly.

A final note on the OptionletVolatilityStructure class: unlike the classes we've seen so far, it also declares an overload of volatilityImpl that takes a date. It has a default implementation that converts the date to a time and calls the other overload, so writers of derived classes don't need to override it; but it can increase accuracy when the derived class takes and stores dates as input.

Finally, the third hierarchy models swaption volatilities; its base class is the SwaptionVolatilityStructure, shown in listing 3.22.

Listing 3.22: Interface of the SwaptionVolatilityStructure class.
    class SwaptionVolatilityStructure
: public VolatilityTermStructure {
public:
... // constructors, not shown
Volatility volatility(const Period& optionTenor,
const Period& swapTenor,
Rate strike,
bool extrapolate = false) const;
// various overloads, also for blackVariance and smileSection

virtual const Period& maxSwapTenor() const = 0;
Time maxSwapLength() const;
protected:
virtual Volatility volatilityImpl(Time optionTime,
Time swapLength,
Rate strike) const = 0;
void checkSwapTenor(Time swapLength,
bool extrapolate) const;
};

It has the same new features I just described for caplet volatilities (the use of smile sections and the overload of volatilityImpl) and a new shtick: the additional dimension given by the length of the underlying swap, which in turn brings a few more methods for specifying and checking the range of the corresponding argument.

That's all for term structures. You'll find plenty of examples in the library; I hope this chapter will help you make sense of them.