lballabio / QuantLib

The QuantLib C++ library
http://quantlib.org
Other
5.19k stars 1.77k forks source link

GeneralizedHullWhite improvements #439

Closed zywina closed 4 years ago

zywina commented 6 years ago

I'm working on calibration of a BK/HW tree to a swaption portfolio. The GeneralizedHullWhite class can handle this but I've needed to modify it to get things working. The existing implementation has some inconsistencies and could use an API cleanup.

The first issue is that the main constructor (below) uses linear interpolation when constructing a tree and piecewise constant values if you access the ShortRateDynamics. I generally find that calibrations run faster and more accurately if the trees are built with piecewise constant vols and would like to be able to chose my interpolation method. Either way it should be consistent.

GeneralizedHullWhite(
            const Handle<YieldTermStructure>& yieldtermStructure,
            const std::vector<Date>& speedstructure,
            const std::vector<Date>& volstructure,
            const std::vector<Real>& speed,
            const std::vector<Real>& vol,
            const boost::function<Real(Real)>& f =
                                            boost::function<Real(Real)>(),
            const boost::function<Real(Real)>& fInverse =
                                            boost::function<Real(Real)>());

My current solution is to add a constructor that accepts boost::function objects for mean reversion and volatility. While its a good answer if someone wants to do something exotic, I'm not sure if this is the best solution for the common cases.

The ideal API would look something like the one below. I would appreciate comments and suggestions before I start checking code in.

enum InterpolationType{
    LinearInterpolation,
    PiecewiseConstant
};
// main constructor
GeneralizedHullWhite(
            const Handle<YieldTermStructure>& yieldtermStructure,
            const std::vector<Date>& speedstructure,
            const std::vector<Date>& volstructure,
            const std::vector<Real>& speed,
            const std::vector<Real>& vol,
            const boost::function<Real(Real)>& f =
                                            boost::function<Real(Real)>(),
            const boost::function<Real(Real)>& fInverse =
                                            boost::function<Real(Real)>(),
            InterpolationType interpolationType = LinearInterpolation);
// generalized constructor
GeneralizedHullWhite(
            const Handle<YieldTermStructure>& yieldtermStructure,
            const boost::function<Real(Time)>& speed,
            const boost::function<Real(Time)>& vol,
            const boost::function<Real(Real)>& f =
                                            boost::function<Real(Real)>(),
            const boost::function<Real(Real)>& fInverse =
                                            boost::function<Real(Real)>());
lballabio commented 6 years ago

Instead of using an enum, you might turn the constructor taking an interpolation into a template (or add a template constructor to the existing one) and use the traits classes already available (Linear, BackwardFlat etc.) I'd wait for the constructor taking a boost::function until someone actually needs to do something exotic, since otherwise you'd have to add data members for both interpolations and functions as well as code to manage which ones to use.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 4 years ago

This issue has been automatically closed as stale.