Monday, December 23, 2013

Intermission: book update and holiday hiatus

Hello, everybody.

Not much to report this week. On the book front, I've uploaded chapter 5 (previously available only as a series of posts) as a PDF file; it's with on the book page with the others. Also, I've added a bibliography page on this blog; this makes it easier for me to provide links to the sources I'm citing.

In other news: like many others all over the world, the Ballabio household is celebrating Christmas.


The schedule of this blog will be affected: I won't be posting over the holiday. You'll hear from me again in January. Have a nice holiday, everybody!

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.

Share this post:

Monday, December 16, 2013

Odds and ends: error reporting

Welcome back.

In this post, some old content from appendix A of the book, Odds and ends. Yes, this is what's affectionately known as a filler post. It's technical, rather than finance-related; but it's about a part of coding that everybody bumps into eventually, and I hope that you will find it interesting.

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.

Error reporting

There are a great many places in the library where some condition must be checked. Rather than doing it as
    if (i >= v.size())
        throw Error("index out of range");
we wanted to express the intent more clearly, i.e., with a syntax like
    require(i < v.size(), "index out of range");
where on the one hand, we write the condition to be satisfied and not its opposite; and on the other hand, terms such as require, ensure, or assert—which have a somewhat canonical meaning in programming—would tell whether we're checking a precondition, a postcondition, or a programmer error.

We provided the desired syntax with macros. "Get behind thee", I hear you say. True, macros have a bad name, and in fact they caused us a problem or two, as we'll see below. But in this case, functions had a big disadvantage: they evaluate all their arguments. Many times, we want to create a moderately complex error message, such as:
    require(i < v.size(),
            "index " + to_string(i) + " out of range");
If require were a function, the message would be built whether or not the condition is satisfied, causing a performance hit that would not be acceptable. With a macro, the above is textually replaced by something like:
    if (!(i < v.size()))
        throw Error("index " + to_string(i) + " out of range");
which builds the message only if the condition is violated.

Listing A.3 shows the current version of one of the macros, namely, QL_REQUIRE; the other macros are defined in a similar way.

Listing A.3: Definition of the QL_REQUIRE macro.
    #define QL_REQUIRE(condition,message) \
    if (!(condition)) { \
        std::ostringstream _ql_msg_stream; \
        _ql_msg_stream << message; \
        throw QuantLib::Error(__FILE__,__LINE__, \
                              BOOST_CURRENT_FUNCTION,
                              _ql_msg_stream.str()); \
    } else

Its definition has a few more bells and whistles that might be expected. Firstly, we use an ostringstream to build the message string. This allows one to use a syntax like
    QL_REQUIRE(i < v.size(),
              "index " << i << " out of range");
to build the message (you can see how that works by replacing the pieces in the macro body). Secondly, the Error instance is passed the name of the current function as well as the line and file where the error is thrown. Depending on a compilation flag, this information can be included in the error message to help developers; the default behavior is to not include it, since it's of little utility for users. Lastly, you might be wondering why we added an else at the end of the macro. That is due to a common macro pitfall, namely, its lack of a lexical scope. The else is needed by code such as
    if (someCondition())
        QL_REQUIRE(i < v.size(), "index out of bounds");
    else
        doSomethingElse();
Without the else in the macro, the above would not work as expected. Instead, the else in the code would pair with the if in the macro and the code would translate into
    if (someCondition()) {
        if (!(i < v.size()))
            throw Error("index out of bounds");
        else
            doSomethingElse();
    }
which has a different behavior.

As a final note, I have to describe a disadvantage of these macros. As they are now, they throw exceptions that can only return their contained message; no inspector is defined for any other relevant data. For instance, although an out-of-bounds message might include the passed index, no other method in the exception returns the index as an integer. Therefore, the information can be displayed to the user but would be unavailable to recovery code in catch clauses—unless one parses the message, that is; but that is hardly worth the effort. There's no planned solution at this time, so drop us a line if you have one.

Share this post:

Monday, December 9, 2013

The strange case of the changing implied term structure

Hello again.

A quick note on the book chapters available in PDF form. Last month, Creative Commons released version 4.0 of their licenses; so from now on, the available material is released under an Attribution-NonCommercial-NoDerivatives 4.0 International license. Your rights (and mine) remain the same under the new license; but, in the words of Creative Commons, it is more user-friendly and more internationally robust.

Onwards to the content of this post. As I mentioned in the past, sometimes questions about QuantLib are asked on the Quantitative Finance Stack Exchange. One such question was asked recently, and I thought I'd share the answer. It was an interesting question, and it's a curious enough effect that one wouldn't think of it in advance (I, for one, surely didn't). Also, this might be the first in a series of QuantLib recipes. No, I'm not planning another book—I have my hands full enough. But I'm going to need something to write in this blog after the book is done, right?

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.

The Strange Case of the Changing Implied Term Structure

The idea of Lisa Ann (hi, and thanks for the question!) was to forecast a future interest-rate curve based on today's rates, and to use it to estimate some kind of forward price for a bond.

The ImpliedTermStructure class does the job: it takes a given curve, a future date D, and builds a new curve whose reference date is D (that is, a curve that returns a discount factor equal to 1 at D) and that returns the same forward rates as the original curve between any two dates d1 and d2 later than D. Its implementation is simple enough: you can look at the code for the details, but the gist of it is that, for any date d > D, it returns a discount factor B'(d) equal to B(d)/B(D), where the B are the discounts returned by the original curve. You can see how for d = D, the discount factor is B(D)/B(D) = 1; and for any d1 and d2, B'(d1)/B'(d2) = B(d1)/B(d2), which preserves the forward rate between d1 and d2.

Lisa Ann instantiated the original curve and passed it to an ImpliedTermStructure instance with a reference date six months from today. The code was somewhat like the following:
    RelinkableHandle<YieldTermStructure> currentCurve;
    currentCurve.linkTo(depoSwapTermStructure);

    Date futureReference = calendar.advance(todaysDate, 6*Months);

    shared_ptr<YieldTermStructure> impliedDiscountCurve =
        make_shared<ImpliedTermStructure>(currentCurve, futureReference);
A look at the discount factors of the two curves showed that they had been built correctly. As the last step in order to price the bond on the implied curve, Lisa Ann set the evaluation date to the future reference; and to her horror (yes, I'm dramatizing. Bear with me a little, will you?) this action changed the shape of the implied curve.

What had happened? The original curve was built so that it moved with the evaluation date, as described in the posts on term structures. Let's work it out.

Let's say that the original curve was like the fictional one shown in this figure; the x-axis is time and the y-axis shows instantaneous forward rates. From the figure, you can also see that I'm so stuck in my old ways that I'm still using Gnuplot.


The implied curve had the same rates (so I'm now showing it; it would coincide with the original curve) but started at t = 0.5.

When the date changed, the original curve was translated verbatim six months in the future, leading to the next figure. The dashed line is the original curve; the solid line is the curve after moving the evaluation date.


The implied curve was linked to the original one through a handle, and all it could do was to change its rates accordingly.

The solution, as you might have guessed, was to prevent the original curve from moving. In most cases, this can be done by selecting the appropriate constructor; that is, the one that takes an explicit reference date (again, all the details are in this post). This way, the original curve wouldn't change when the evaluation date moved; and neither would the implied curve.

Share this post:

Monday, December 2, 2013

Chapter 3, part 6 of n: volatility term structures

Welcome back.

Two bit of news about the QuantLib site. The first is that we finally collected the material from the QuantLib User Meeting in Düsseldorf, and the slides for most of the talks are now available on the documentation page. The second is that the QuantLib site itself was renovated; I hope that the navigation is a bit more clear now, and that it will be simpler to find stuff.

As promised, this week's post has some new book content. At last, we're nearing the end of chapter 3; all that's missing is a couple of short sections on interest-rate volatilities.

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.

Term structures

Volatility term structures

There are so many types of volatility structures that finding common behavior between them is a bit of a stretch. In fact, I'm not sure that the base class we defined for them (the VolatilityTermStructure class, shown in listing 3.16) is a useful abstraction.

Listing 3.16: Interface of the VolatilityTermStructure class.
    class VolatilityTermStructure : public TermStructure {
      public:
        VolatilityTermStructure(BusinessDayConvention bdc,
                                const DayCounter& dc = DayCounter());
        VolatilityTermStructure(const Date& referenceDate,
                                const Calendar& cal,
                                BusinessDayConvention bdc,
                                const DayCounter& dc = DayCounter());
        VolatilityTermStructure(Natural settlementDays,
                                const Calendar& cal,
                                BusinessDayConvention bdc,
                                const DayCounter& dc = DayCounter());

        virtual BusinessDayConvention businessDayConvention() const {
            return bdc_;
        }
        Date optionDateFromTenor(const Period&) const {
            return calendar().advance(referenceDate(),
                                      p,
                                      businessDayConvention());
        }

        virtual Rate minStrike() const = 0;
        virtual Rate maxStrike() const = 0;
      protected:
        void checkStrike(Rate strike, bool extrapolate) const;
      private:
        BusinessDayConvention bdc_;
    };
The class adds two things to TermStructure, from which it inherits. The first is a method, optionDateFromTenor, that calculates the exercise date of an option from its tenor; to do this, it used the calendar provided by the base-class interface as well as a business-day convention stored in this class (which is passed to the constructors, and from which the usual inspector is provided). Instead, this functionality could be encapsulated in some kind of utility class and used elsewhere. (The idea of such date calculator was suggested years ago on the mailing list by someone who will forgive me if I can no longer recall nor find out his name.)

The second addition involves two pure virtual methods that return the minimum and maximum strike over which the term structure is defined and a protected method that checks a given strike against the defined range. Unfortunately, these don't make sense for a local volatility structure; but leaving them out would require yet another level of hierarchy to hold them (namely, an implied-vol structure class) so I'm not shocked to see them here instead.

Equity volatility structures

Equity and FX-rate Black volatilities are modeled by the BlackVolTermStructure class, shown in listing 3.17. Apart from its several constructors (which, as usual, forward their arguments to the base class and would be made unnecessary by constructor inheritance, introduced in C++11 [1]) the class defines the overloaded blackVol method to retrieve the volatility for a given exercise date or time; the blackVariance method for the corresponding variance (the product of the square of the volatility by the time); and the blackForwardVol and blackForwardVariance methods for the forward volatility and variance between two future dates.

Listing 3.17: Partial interface of the BlackVolTermStructure class.
    class BlackVolTermStructure : public VolatilityTermStructure {
      public:
        Volatility blackVol(const Date& maturity,
                            Real strike,
                            bool extrapolate = false) const;
        Volatility blackVol(Time maturity,
                            Real strike,
                            bool extrapolate = false) const;
        Real blackVariance(const Date& maturity,
                           Real strike,
                           bool extrapolate = false) const;
        Real blackVariance(Time maturity,
                           Real strike,
                           bool extrapolate = false) const;
        Volatility blackForwardVol(const Date& date1,
                                   const Date& date2,
                                   Real strike,
                                   bool extrapolate = false) const;
        Real blackForwardVariance(const Date& date1,
                                  const Date& date2,
                                  Real strike,
                                  bool extrapolate = false) const;
        // same two methods as above, taking two times
      protected:
        virtual Real blackVarianceImpl(Time t,
                                       Real strike) const = 0;
        virtual Volatility blackVolImpl(Time t,
                                        Real strike) const = 0;
    };
Following the Template Method pattern (no surprise there) all these methods are implemented by calling the protected and pure virtual blackVolImpl and blackVarianceImpl methods. The public interface adds range checking and, in the case of forward volatility or variance, the bit of logic required to calculate the forward values from the spot values at the two passed dates.

At the time of this writing, the BlackVolTermStructure class also defines a private static const data member dT that is no longer used—much like we still carry around an appendix, or a vestigial tailbone. By the time you read this, I hope to have it removed. The data member, I mean. Not my appendix.

As usual, adapters are provided to write only one of the blackVolImpl or the blackVarianceImpl method; they are shown in listing 3.18. (For simple examples of either kind, you can look at the ConstantBlackVol and the misleadingly-named ImpliedVolTermStructure classes in the library.) It is unfortunate that the name of one of the adapters, the BlackVolatilityTermStructure class, is so confusingly similar to the name of the base class. I'm open to suggestions for changing either one in a future version of the library.

Listing 3.18: Adapters for the BlackVolTermStructure class.
    class BlackVolatilityTermStructure
                        : public BlackVolTermStructure {
        ... // constructors, not shown
      protected:
        Real blackVarianceImpl(Time maturity, Real strike) const {
            Volatility vol = blackVolImpl(t, strike);
            return vol*vol*t;
        }
    };

    class BlackVarianceTermStructure
                        : public BlackVolTermStructure {
        ... // constructors, not shown
      protected:
        Volatility blackVolImpl(Time t, Real strike) const {
            Time nonZeroMaturity = (t==0.0 ? 0.00001 : t);
            Real var = blackVarianceImpl(nonZeroMaturity, strike);
            return std::sqrt(var/nonZeroMaturity);
        }
    };

Aside: Interpolations and extrapolations.

One of the available volatility classes is the BlackVarianceSurface class, which interpolates a matrix of quoted Black volatilities. I won't describe it here, since you're probably sick of term-structure examples by now; but it has a couple of interesting features.

The first is that the interpolation can be changed once the structure is built; the relevant method is
    template <class Interpolator>
    void setInterpolation(const Interpolator& i = Interpolator()) {
        varianceSurface_ =
            i.interpolate(times_.begin(), times_.end(),
                          strikes_.begin(), strikes_.end(),
                          variances_);
        notifyObservers();
    }
This is not possible in other interpolated curves, in which the type of the interpolation is a template argument and is fixed at instantiation; see, for instance, the PiecewiseYieldCurve class template in this post. The difference is that BlackVarianceSurface doesn't need to store the interpolator, and thus doesn't need to know its type outside the setInterpolation method.

The second feature of BlackVarianceSurface is the possibility to customize the kind of extrapolation to use when the passed strike is outside the range of the interpolation. It is possible either to extend the underlying interpolation or to extrapolate flatly the value at the end of the range; the behavior at either end can be specified independently.

Now, it would be nice if this behavior could be extracted in some base class and reused. The choice of extrapolation can be implemented in a generic way; given any interpolation f defined up to xmax (or down to xmin), and given an x > xmax, the two choices can be realized by returning f(x) for extension of f(xmax) for flat extrapolation.

The Extrapolator class would seem the obvious choice for defining such behavior; but, unfortunately, this wouldn't work if we still want to make different choices on different boundaries. As a base class, Extrapolator would have no knowledge of the fact that, for instance, an interest-rate structure is defined over a time range whose lower bound is 0, while a volatility surface also has a range of strikes. Since it can't distinguish between boundaries, Extrapolator can't define an interface that specifies behavior on any of them; we'd be forced to make a single choice and apply it everywhere.

Therefore, the only possibility I see for code reuse at this time would be to define a polymorphic Extrapolation class, code the different behaviors into derived classes, and store the required number of instances into any given term structure.

Bibliography

[1] International Standards Organization, Programming Languages – C++, International Standard ISO/IEC 14882:2011. Available as a working draft.

Share this post: