Odds and ends: indexes
Greetings, everybody.
Ok, I’ll make it quick.
First of all: all the slides from the Düsseldorf user meeting are already available on the QuantLib site. Go get ‘em. If you want some introduction, my previous post might help.
Then: this week I’m posting some content from the book appendix, namely, an overview of indexes.
Finally: the holiday season is coming.
It’s likely that I won’t be posting next week, so let me wish a merry Christmas to those who, like my family, celebrate it, a happy holiday to those who celebrate something else, and some holiday cheer to those who don’t (but hey, you’re missing out, people). I’ll see you here after the festivities.
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.
Odds and ends: indexes
Like other classes such as Instrument
and TermStructure
, the
Index
class is a pretty wide umbrella: it covers concepts such as
interest-rate indexes, inflation indexes, stock indexes—you get
the drift.
Needless to say, the modeled entities are diverse enough that the
Index
class has very little interface to call its own. As shown in
the listing below, all its methods have to do with index fixings. The
isValidFixingDate
method tells us whether a fixing was (or will be
made) on a given date; the fixingCalendar
method returns the
calendar used to determine the valid dates; and the fixing
method
retrieves a fixing for a past date or forecasts one for a future
date. The remaining methods deal specifically with past fixings: the
name
method, which returns an identifier that must be unique for
each index, is used to index (pun not intended) into a map of stored
fixings; the addFixing
method stores a fixing (or many, in other
overloads not shown here); and the clearFixing
method clears all
stored fixings for the given index.
Listing: interface of the Index
class.
Why the map, and where is it in the Index
class? Well, we started
from the requirement that past fixings should be shared rather than
per-instance; if one stored, say, the 6-months Euribor fixing for a
date, we wanted the fixing to be visible to all instances of the same
index, and not just the particular one whose addFixing
method we
called. (Note that by “instances of the same index” I mean here
instances of the same specific index, not of the same class, which
might group different indexes; for instance, USDLibor(3*Months)
and
USDLibor(6*Months)
are not instances of the same index; two
different USDLibor(3*Months)
are.) This was done by defining and
using an IndexManager
singleton behind the curtains. Smelly? Sure,
as all singletons. An alternative might have been to define static
class variables in each derived class to store the fixings; but that
would have forced us to duplicate them in each derived class with no
real advantage (it would be as much against concurrency as the
singleton). In any case, this is one of the things we’ll have to
rethink in the next big QuantLib revision, in which we’ll have to
tackle concurrency. If these past years are any indication, we might
expect it around 2020. No, just kidding. Maybe.
Since the returned index fixings might change (either because their
forecast values depend on other varying objects, or because a newly
available fixing is added and replaces a forecast) the Index
class
inherits from Observable
so that instruments can register with its
instances and be notified of such changes.
At this time, Index
doesn’t inherit from Observer
, although its
derived classes do (not surprisingly, since forecast fixings will
almost always depend on some observable market quote). This was not an
explicit design choice, but rather an artifact of the evolution of the
code and might change in future releases. However, even if we were to
inherit Index
from Observer
, we would still be forced to have some
code duplication in derived classes, for a reason which is probably
worth describing in more detail.
I already mentioned that fixings can change for two reasons. One is
that the index depends on other observables to forecast its fixings;
in this case, it simply registers with them (this is done in each
derived class, as each class has different observables). The other
reason is that a new fixing might be made available, and that’s more
tricky to handle. The fixing is stored by a call to addFixing
on a
particular index instance, so it seems like no external notification
would be necessary, and that the index can just call the
notifyObservers
method to notify its observers; but that’s not the
case. As I said, the fixings is shared; if we store today’s 3-months
Euribor fixing, it will be available to all instances of such index,
and thus we want all of them to be aware of the change. Moreover,
instruments and curves might have registered with any of those Index
instances, so all of them must send in turn a notification.
The solution is to have all instances of the same index communicate by
means of a shared object; namely, we used the same IndexManager
singleton that stores all index fixings. As I said, IndexManager
maps unique index tags to sets of fixings; also, by making the sets
instances of the ObservableValue
class, it provides the means to
register and receive notification when one or more fixings are added
for a specific tag (this class will be described in a later post. You
don’t need the details here).
All pieces are now in place. Upon construction, any Index
instance
will ask IndexManager
for the shared observable corresponding to the
tag returned by its name
method. When we call addFixings
on, say,
some particular 6-months Euribor index, the fixing will be stored into
IndexManager
; the observable will send a notification to all
6-months Euribor indexes alive at that time; and all will be well with
the world.
However, C++ still throws a small wrench in our gears. Given the above, it would be tempting to call
in the Index
constructor and be done with it. However, it wouldn’t
work; for the reason that in the constructor of the base class, the
call to the virtual method name
wouldn’t be polymorphic. (If you’re
not familiar with the darker corners of C++: when the constructor of a
base class is executed, any data members defined in derived classes
are not yet built. Since any behavior specific to the derived class is
likely to depend on such yet-not-existing data, C++ bails out and uses
the base-class implementation of any virtual method called in the
base-class constructor body.) From here stems the code duplication I
mentioned a few paragraphs earlier; in order to work, the above method
call must be added to the constructor of each derived index class. The
Index
class itself doesn’t have a constructor (apart from the
default one that the compiler provides).
As an example of a concrete class derived from Index
, the listing
below sketches the InterestRateIndex
class.
Listing: sketch of the InterestRateIndex
class.
As you might expect, such class defines a good deal of specific
behavior besides that inherited from Index
. To begin with, it
inherits from Observer
, too, since Index
doesn’t. The
InterestRateIndex
constructor takes the data needed to specify the
index: a family name, as in “Euribor”, common to different indexes of
the same family such as, say, 3-months and 6-months Euribor; a tenor
that specifies a particular index in the family; and additional
information such as the number of settlement days, the index currency,
the fixing calendar, and the day-count convention used for accrual.
The passed data are, of course, copied into the corresponding data
members; then the index registers with a couple of observables. The
first is the global evaluation date; this is needed because, as I’ll
explain shortly, there’s a bit of date-specific behavior in the class
that is triggered when an instance is asked for today’s fixing. The
second observable is the one which is contained inside IndexManager
and provides notifications when new fixings are stored. We can
identify this observable here: the InterestRateIndex
class has all
the information needed to determine the index, so it can implement the
name
method and call it. However, this also means that classes
deriving from InterestRateIndex
must not override name
; since the
overridden method would not be called in the body of this constructor,
they would register with the wrong notifier. Unfortunately, this can’t
be enforced in C++, which doesn’t have a keyword like final
in Java
or sealed
in C#; but the alternative would be to require that all
classes derived from InterestRateIndex
register with IndexManager
,
which is equally not enforceable, probably more error-prone, and
certainly less convenient.
The other methods defined in InterestRateIndex
have different
purposes. A few implement the required Index
and Observer
interfaces; the simplest are update
, which simply forwards any
notification, fixingCalendar
, which returns a copy of the stored
calendar instance, and isValidFixingDate
, which checks the date
against the fixing calendar.
The name
method is a bit more complicated. It stitches together the
family name, a short representation of the tenor, and the day-count
convention to get an index name such as “Euribor 6M Act/360” or “USD
Libor 3M Act/360”; special tenors such as overnight, tomorrow-next and
spot-next are detected so that the corresponding acronyms are used.
The fixing
method contains the most logic. First, the required
fixing date is checked and an exception is raised if no fixing was
supposed to take place on it. Then, the fixing date is checked against
today’s date. If the fixing was in the past, it must be among those
stored in the IndexManager
singleton; if not, an exception is raised
since there’s no way we can forecast a past fixing. If today’s fixing
was requested, the index first tries looking for the fixing in the
IndexManager
and returns it if found; otherwise, the fixing is not
yet available. In this case, as well as for a fixing date in the
future, the index forecasts the value of the fixing; this is done by
calling the forecastFixing
method, which is declared as purely
virtual in this class and implemented in derived ones. The logic in
the fixing
method is also the reason why, as I mentioned, the index
registers with the evaluation date; the behavior of the index depends
on the value of today’s date, so it need to be notified when it
changes.
Finally, the InterestRateIndex
class defines other methods that are
not inherited from Index
. Most of them are inspectors that return
stored data such as the family name or the tenor; a few others deal
with date calculations. The valueDate
method takes a fixing date and
returns the starting date for the instrument that underlies the rate
(for instance, the deposit underlying a LIBOR, which for most
currencies starts two business days after the fixing date); the
maturityDate
method takes a value date and returns the maturity of
the underlying instrument (e.g., the maturity of the deposit); and the
fixingDate
method is the inverse of valueDate
, taking a value date
and returning the corresponding fixing date. Some of these methods are
virtual, so that their behavior can be overridden; for instance, while
the default behavior for valueDate
is to advance the given number of
fixing days on the given calendar, LIBOR index mandates first to
advance on the London calendar, then to adjust the resulting date on
the calendar corresponding to the index currency. For some reason,
fixingDate
is not virtual; this is probably an oversight that should
be fixed in a future release.
Aside: how much generalization?
Some of the methods of the InterestRateIndex
class were evidently
designed with LIBOR in mind, since that was the first index of that
kind implemented in the library. On the one hand, this makes the class
less generic than one would like: for instance, if we were to decide
that the 5-10 years swap-rate spread were to be considered an
interest-rate index in its own right, we would be hard-pressed to fit
it to the interface of the base class and its single tenor
method. But on the other hand, it is seldom wise to generalize an
interface without having a couple of examples of classes that should
implement it; and a spread between two indexes (being just that; a
spread, not an index) is probably not one such class.