Monday, December 15, 2014

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 widgets for that are in the sidebar, at the top right of the page. 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.
    class Index : public Observable {
      public:
        virtual ~Index() {}
        virtual std::string name() const = 0;
        virtual Calendar fixingCalendar() const = 0;
        virtual bool isValidFixingDate(const Date& fixingDate) const = 0;
        virtual Real fixing(const Date& fixingDate,
                            bool forecastTodaysFixing = false) const = 0;
        virtual void addFixing(const Date& fixingDate,
                               Real fixing,
                               bool forceOverwrite = false);
        void clearFixings();
    };

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
    registerWith(IndexManager::instance().notifier(name()));
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.
    class InterestRateIndex : public Index, public Observer {
      public:
        InterestRateIndex(const std::string& familyName,
                          const Period& tenor,
                          Natural settlementDays,
                          const Currency& currency,
                          const Calendar& fixingCalendar,
                          const DayCounter& dayCounter);
        : familyName_(familyName), tenor_(tenor), ... {
            registerWith(Settings::instance().evaluationDate());
            registerWith(
                     IndexManager::instance().notifier(name()));
        }

        std::string name() const;
        Calendar fixingCalendar() const;
        bool isValidFixingDate(const Date& fixingDate) const {
            return fixingCalendar().isBusinessDay(fixingDate);
        }
        Rate fixing(const Date& fixingDate,
                    bool forecastTodaysFixing = false) const;
        void update() { notifyObservers(); }

        std::string familyName() const;
        Period tenor() const;
        ... // other inspectors

        Date fixingDate(const Date& valueDate) const;
        virtual Date valueDate(const Date& fixingDate) const;
        virtual Date maturityDate(const Date& valueDate) const = 0;
      protected:
        virtual Rate forecastFixing(const Date& fixingDate) const = 0;
        std::string familyName_;
        Period tenor_;
        Natural fixingDays_;
        Calendar fixingCalendar_;
        Currency currency_;
        DayCounter dayCounter_;
    };
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.
    std::string InterestRateIndex::name() const {
        std::ostringstream out;
        out << familyName_;
        if (tenor_ == 1*Days) {
            if (fixingDays_==0) out << "ON";
            else if (fixingDays_==1) out << "TN";
            else if (fixingDays_==2) out << "SN";
            else out << io::short_period(tenor_);
        } else {
            out << io::short_period(tenor_);
        }
        out << " " << dayCounter_.name();
        return out.str();
    }

    Rate InterestRateIndex::fixing(
                           const Date& d,
                           bool forecastTodaysFixing) const {
        QL_REQUIRE(isValidFixingDate(d), ...);
        Date today = Settings::instance().evaluationDate();
        if (d < today) {
            Rate pastFixing =
                IndexManager::instance().getHistory(name())[d];
            QL_REQUIRE(pastFixing != Null<Real>(), ...);
            return pastFixing;
        }
        if (d == today && !forecastTodaysFixing) {
            Rate pastFixing = ...;
            if (pastFixing != Null<Real>())
                return pastFixing;
        }
        return forecastFixing(d);
    }

    Date InterestRateIndex::valueDate(const Date& d) const {
        QL_REQUIRE(isValidFixingDate(d) ...);
        return fixingCalendar().advance(d, fixingDays_, Days);
    }
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.

Liked this post? Share it:

Tuesday, December 9, 2014

Report from the QuantLib user meeting in Düsseldorf

Welcome back.

This last Thursday and Friday I was in Düsseldorf for the second QuantLib user meeting.

Man, was it good.

It was two days of great talks, with a good mixture of technical and financial content (and by the way, the slides are being collected and some are already available on the QuantLib page for the meeting). Thanks go to IKB, that sponsored the event and provided the venue, and especially to Michael von der Driesch and Peter Caspers, who organized the meeting and kept it running smoothly. I'm looking forward to next year. Really, we should have more of these events around Europe.

I wasn't giving a talk this year, so I just relaxed and enjoyed the show. It started with the keynote of Ferdinando Ametrano (@Ferdinando1970) on open-source finance: QuantLib, OpenGamma and Bitcoin, with the latter being the success story and having the lion's share in the presentation. (If you want to read Ferdinando's papers on Bitcoin, they're here and here). One thing stuck with me among those Ferdinando said about QuantLib: it isn't nearly as used in academia as we would like. If you teach in a university, let me know if there's anything I can do to help with this.

The second talk was by Roland Lichters, which told us of how speed is paramount in the CVA application he and his team at Quaternion develop. They fine-tuned QuantLib until they could price a swap on a given scenario in 30 microseconds (which I thought quite impressive) with a full analysis in about 30 seconds, but Bermudan swaptions were much slower; a full analysis would take some 50 minutes. Taking inspiration from the Longstaff-Schwartz method for American Monte Carlo, they now run an initial simulation to calculate swaption prices as a regression function. This initial time investment allows them to save time during the analysis, bringing its time back to the order of seconds.

In the last talk of the morning, Matthias Groncki presented the work he and Michael von der Driesch did at IKB on ABS. They wanted to make these instruments easier to simulate and price, and they knew that QuantLib could help since it had the basic pieces of the puzzle. Based on those, they wrote an implementation of the instrument in C++ and exposed it to Python. This allowed them to create an easier interface through IPython notebooks, providing graphs as well as numerical results as an aid to understanding.

After lunch, we restarted with Dirk Eddelbuettel (@eddelbuettel).  Let me add a personal note here: Dirk has been helping with the project and packaging the Debian version of QuantLib almost since day one, and we never had the chance to meet in person before. I was delighted we could do it this time.
Dirk gave us a description of his initial work on exporting QuantLib to R, and how this ultimately led to the development of Rcpp which is now used by more than 300 CRAN packages (or about 5% of the total). Other cool tools shown in his talk: Shiny and RMarkdown, which can use R packages (including RQuantLib) to provide interactive web-based reports. One thing I noticed is that most of the problems the RQuantLib package seems to have are shared with the C++ library, or rather caused by it: singletons, no time component in dates, no simple example for textbook calculations such as Black-Scholes. Eventually, we'll have to do something about it.

Next, Sebastian Schlenkrich on the hot topic of this meeting: the modeling of the basic spread between Libor and funding curves (that is, either the OIS curve or possibly a cross-currency curve for deals collateralized in another currency). I won't go into the details, which are in his (and André Miemiec's) paper at SSRN. I'll note, though, that his talk was the one with the most lively discussion at the end, with Sebastian, Daniel Duffy, Ferdinando and myself going over what could be the right design for including his results into QuantLib. No clear winner emerged yet, but the interest in the topic makes me guess that we'll work on it.

The final talk of the day was from Peter Caspers, who described some of his several contributions to QuantLib during the past year. The list is impressive, covering no-arbitrage SABR; ZABR and SVI interpolations; TSR CMS coupon pricers; CMS-spread coupon pricers; Credit Risk+ model; Gaussian 1D models; simulated annealing optimizer; Runge-Kutta ODE solver; and dynamically created Mersenne-Twister RNGs. With a gentle metaphorical nudge in my ribs, Peter noticed that most of them are in the experimental folder. I agree; we need some kind of triage process to look at the contents of that folder and move them in the core library. I'll explore some ideas after next release.

And with the end of this talk (also immortalized by Dirk on Twitter) we were off to dinner.



And there was evening and there was morning.

The second day started with a talk by Daniel Duffy, who described the latest iteration of his PDE and FDM framework. He made a number of interesting points. He told how, in a mathematical domain such as this, functional programming and generics are more suited to the task than object-oriented programming; and how C++11/14 made this style of programming easier with type inference (auto), lambda functions, and generic function objects (std::function). Using loosely coupled functions, instead of class interfaces, made it possible to separate clearly the different layers of the framework (PDEs, FDM, interface, and so on). Daniel's code might get into QuantLib at some point (the main problem being that we're still supporting older compilers that don't implement C++11) but I've also been talking Daniel into releasing his code as a project on its own. We'll see.

Next, Paolo Mazzocchi, who's been working with Ferdinando on modeling basis spreads. In discount-based legacy systems, synthetic deposits are required for maturities shorter than the Libor tenor. Their approach was to parameterize the spread between Libor and funding curve in that range and fit the parameters to the existing market quotes. The details are in the slides (already available): expect a paper soon.

The last talk of Friday morning was by Bernd Lewerenz, on the subject of a new pricing engine he contributed for Asian options based on a model by Jan Večeř (and that, serendipitously, I merged in the main repository just days before the meeting). The engine makes it possible to efficiently price arithmetic-average Asian options, widely used in commodity markets. Also, Bernd told us he's been driving the thing by means of the QuantLib Perl bindings, which makes this their first documented use.

Starting the afternoon talks: Eric Ehlers and his Reposit project. It is a rewrite of his gensrc generator for the QuantLib Excel bindings, it is implemented as a SWIG module, has a web site, and is a work in progress. Eric's talk had the merit of sparking two developments: it attracted some interest in rekindling the QuantLib Calc addin, and made me think that this is probably the time to check SWIG's support for shared_ptr and see if we can simplify our SWIG interfaces.

Next: a joint presentation by Klaus Spanderen and Johannes Göttker-Schnetmann on their quest for a calibrated local volatility. They are pretty well along it (in fact, so much that they changed he title of their talk to be a lot more optimistic than when they proposed it). Not only the details are in their presentation (and I wouldn't do them justice, so go read the slides), but their code is on GitHub, too.

The final talk was from André Miemiec, talking of an open field of research: the arbitrage-free and consistent modeling of swaptions, CMS and CMS spreads. He's been building on QuantLib to price CMS spread options. A simple extension of the existing code gave him a correct implementation on the first try; but there's still work to be done on speed before it can be used in a production setting. It was nice to see the library help getting a working prototype quickly, though.

And with this, we got to the end. All the comments I heard were enthusiastic (and mine, too).  As I said above: definitely something that should be replicated somewhere else.

Thanks again to the sponsor, the organizers, the speakers and all those who attended. I hope I'll see you again next year.

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.

Liked this post? Share it: