Odds and ends: interest rates
Welcome back.
This post marks a break in the series on chapter 3 which started in this post and ran for the past few weeks. It covers interest rates, which are relevant to its subject but are not technically part of the chapter.
The idea is that a number of basic classes are glossed over in the main part of the book and are described in an appendix instead, so they don’t interrupt the flow of the chapters. As pointed out by Douglas Adams in the fourth book of his Hitchhiker trilogy, (no, that’s right: it’s an inaccurately-named trilogy of five books. It’s a long story.)
“[An excessive amount of detail] is guff. It doesn’t advance the action. It makes for nice fat books such as the American market thrives on, but it doesn’t actually get you anywhere.”
I’m not sure that this is still the case with the blog form. I’m already cutting up every chapter in several posts, so the additional content might follow one of those. We’ll see: I’m still new at this blogging thing, so I’m likely to experiment in the future.
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: interest rates
The InterestRate
class (shown in listing A.6) encapsulates general
interest-rate calculations. Instances of this class are built from a
rate, a day-count convention, a compounding convention, and a
compounding frequency (note, though, that the value of the rate is
always annualized, whatever the frequency). This allows one to specify
rates such as “5%, actual/365, continuously compounded” or “2.5%,
actual/360, semiannually compounded.” As can be seen, the frequency is
not always needed. I’ll return to this later.
Listing A.6: Outline of the InterestRate
class.
Besides the obvious inspectors, the class provides a number of
methods. One is the conversion operator to Rate
, i.e., to
double
. On afterthought, this is kind of risky, as the converted
value loses any day-count and compounding information; this might
allow, say, a simply-compounded rate to slip undetected where a
continuously-compounded one was expected. The conversion was added for
backward compatibility when the InterestRate
class was first
introduced; it might be removed in a future revision of the library,
dependent on the level of safety we want to force on users. (There are
different views on safety among the core developers, ranging from
“babysit the user and don’t let him hurt himself” to “give him his
part of the inheritance, pat him on his back, and send him to find his
place in the world.”)
Other methods complete a basic set of calculations. The
compoundFactor
returns the unit amount compounded for a time t (or
equivalently, between two dates d1 and d2) according to the given
interest rate; the discountFactor
method returns the discount factor
between two dates or for a time, i.e., the reciprocal of the compound
factor; the impliedRate
method returns a rate that, given a set of
conventions, yields a given compound factor over a given time; and the
equivalentRate
method converts a rate to an equivalent one with
different conventions (that is, one that results in the same
compounded amount).
Like the InterestRate
constructor, some of these methods take a
compounding frequency. As I mentioned, this doesn’t always make sense;
and in fact, the Frequency
enumeration has a NoFrequency
item just
to cover this case.
Obviously, this is a bit of a smell. Ideally, the frequency should be
associated only with those compounding conventions that need it, and
left out entirely for those (such as Simple
and Continuous
) that
don’t. If C++ supported it, we would write something like
which would be similar to algebraic data types in functional
languages, or case classes in Scala (both support pattern matching on
an object, which is like a neater switch
on steroids; go have a look
when you have some time) but unfortunately that’s not an option. To
have something of this kind, we’d have to go for a full-featured
Strategy pattern and turn Compounding
into a class hierarchy. That
would probably be overkill for the needs of this class, so we’re
keeping both the enumeration and the smell.