Monday, August 19, 2013

Chapter 5, part 3 of n: Model parameters

Welcome back.

This is the third in a series of posts on chapter 5 of my book; Part 1 and 2 are here and here. It is still being written as you read, which brings novelty, excitement, and the possibility that I fall behind the schedule. We'll see how this turns out.

From the 2nd to the 4th of September I'll be in London to teach my Introduction to QuantLib Development course. One of those nights I'll go grab a pint or two with a few people; drop me a line if you want to join us. Assuming I find a data connection, I'll try and tweet the place. (And yes, places for the course are still available; go to this link if you're interested).

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.

Parameterized models and calibration

Parameters

There is an ambiguity when we say that a model has a given number of parameters. If they are constant, all is well; for instance, we can safely say that the Hull-White model has two parameters alpha and sigma. What if one of the two was time-dependent, though? In turn, it would have some kind of parametric form. Conceptually, it would still be one single model parameter; but it might add several numbers to the set to be calibrated.

The Parameter class, shown in listing 5.3, takes the above into account—and, unfortunately, embraces the ambiguity: it uses the term "parameter" for both the instances of the class (that represent a model parameter, time-dependent or not) and for the numbers underlying their parametric forms. Our bad: you'll have to be careful not to get confused in the discussion that follows.

Listing 5.3: Sketch of the Parameter class.
    class Parameter {
      protected:
        class Impl {
          public:
            virtual ~Impl() {}
            virtual Real value(const Array& params, Time) const = 0;
        };
        boost::shared_ptr<Impl> impl_;
      public:
        Parameter();
        const Array& params() const;
        void setParam(Size i, Real x) { params_[i] = x; }
        bool testParams(const Array& params) const;
        Size size() const { return params_.size(); }
        Real operator()(Time t) const {
            return impl_->value(params_, t);
        }
      protected:
        Parameter(Size size,
                  const boost::shared_ptr<Impl>& impl,
                  const Constraint& constraint);
        Array params_;
        Constraint constraint_;
    };

Specialized behavior for different parameter will be implemented in derived classes (I'll show you a few of those shortly). However, the way we go about it is somewhat unusual: instead of declaring a virtual method directly, the Parameter class is given an inner class Impl, which declares a purely virtual value method. There's method in this madness; but let me gloss over it for now. (Someone on the Wilmott forums suggested that the reason is job security: if we obfuscate the code enough, nobody else will be able to maintain it. I can see his point, but this is not the reason.) The idiom is used in other classes, and will be explained in appendix A.

Instances of Parameter represent, in principle, a time-dependent parameter and store an array params_ which contain the values of the parameters used to describe its functional form. Most of the interface deals with these underlying parameters; the params method returns the whole array, the setParam method allows to change any of the values, and the size method returns their number.

Parameter instances also store a constraint that limits the range of values that the underlying parameters can take; the testParam method provides the means to check their current values against the constraint. Finally, operator() returns the value of the represented parameter (I'm not sure how I should call it. The main parameter? The outer parameter?) as a function of time, given the current values of the underlying parameters; as I mentioned, the actual implementation is delegated to the stored instance of the inner Impl class.

Finally, the class declared a couple of constructors. One is protected, and allows derived classes to initialize their own instances. Another is public; it creates instances without behavior (and therefore useless) but allows us to use Parameter with containers such as std::vector (I think this is no longer necessary in C++11, but we are still living in the past).

Listing 5.4 shows a few examples of actual parameters; they inherit from the Parameter class and declare inner Impl classes that inherit from Parameter::Impl and implement the required behavior.

Listing 5.4: Sketch of a few classes inherited from Parameter.
    class ConstantParameter : public Parameter {
        class Impl : public Parameter::Impl {
          public:
            Real value(const Array& params, Time) const {
                return params[0];
            }
        };
      public:
        ConstantParameter(const Constraint& constraint)
        : Parameter(1, /* ... */) {}
    };

    class NullParameter : public Parameter {
        class Impl : public Parameter::Impl {
          public:
            Real value(const Array&, Time) const {
                return 0.0;
            }
        };
      public:
        NullParameter() : Parameter(0, /* ... */) {}
    };

    class PiecewiseConstantParameter : public Parameter {
        class Impl : public Parameter::Impl {
          public:
            Impl(const std::vector<Time>& times);
            Real value(const Array& params, Time t) const {
                for (Size i=0; i<times_.size(); i++) {
                    if (t<times_[i])
                        return params[i];
                }
                return params.back();
            }
          private:
            std::vector<Time> times_;
        };
      public:
        PiecewiseConstantParameter(const std::vector<Time>& times,
                                   const Constraint& constraint)
        : Parameter(times.size()+1, /* ... */) {}
    };

The first represents a parameter which is constant in time; this is what we usually think about when we talk of a parameter, and is possibly the most used. The array of internal parameters has just one element (as seen by the 1 passed to the Parameter constructor), and that's what the implementation returns independently of the passed time.

The second is a null parameter; its value is supposed to be 0 and must not be calibrated. In this case, the stored array has no elements (again, see the 0 passed to the Parameter constructor) since nothing will move during calibration. This could probably be a specific case of a more general FixedParameter class, whose fixed value could be different from 0.

Finally, the third class represents a time-dependent parameter. It is modeled as piecewise constant between any two consecutive times in a given set; thus, if the set has n times, we'll have n + 1 different values (including the one before the first time and the one after the last). The implementation is a simple linear search, as we don't expect the times to be too many or we'd be likely to over-calibrate.

The library implements other parameter classes (and we could define others; for instance, using other parameterizations of time dependence) but I won't keep you any longer. At this point (that is, in next post) we need to turn to the class that—I don't really have a less awkward way to say it—models a calibrated model.

Share this post: