/usr/include/ql/termstructures/yield/fittedbonddiscountcurve.hpp is in libquantlib0-dev 1.9.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2007 Allen Kuo
Copyright (C) 2009 Ferdinando Ametrano
Copyright (C) 2015 Andres Hernandez
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<quantlib-dev@lists.sf.net>. The license is also available online at
<http://quantlib.org/license.shtml>.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
/*! \file fittedbonddiscountcurve.hpp
\brief discount curve fitted to a set of bonds
*/
#ifndef quantlib_fitted_bond_discount_curve_hpp
#define quantlib_fitted_bond_discount_curve_hpp
#include <ql/termstructures/yield/bondhelpers.hpp>
#include <ql/math/optimization/method.hpp>
#include <ql/patterns/lazyobject.hpp>
#include <ql/math/array.hpp>
#include <ql/utilities/clone.hpp>
namespace QuantLib {
//! Discount curve fitted to a set of fixed-coupon bonds
/*! This class fits a discount function \f$ d(t) \f$ over a set of
bonds, using a user defined fitting method. The discount
function is fit in such a way so that all cashflows of all
input bonds, when discounted using \f$ d(t) \f$, will
reproduce the set of input bond prices in an optimized
sense. Minimized price errors are weighted by the inverse of
their respective bond duration.
The FittedBondDiscountCurve class acts as a generic wrapper,
while its inner class FittingMethod provides the
implementation details. Developers thus need only derive new
fitting methods from the latter.
<b> Example: </b>
\link FittedBondCurve.cpp
compares various bond discount curve fitting methodologies
\endlink
\warning The method can be slow if there are many bonds to
fit. Speed also depends on the particular choice of
fitting method chosen and its convergence properties
under optimization. See also todo list for
BondDiscountCurveFittingMethod.
\todo refactor the bond helper class so that it is pure
virtual and returns a generic bond or its cash
flows. Derived classes would include helpers for
fixed-rate and zero-coupon bonds. In this way, both
bonds and bills can be used to fit a discount curve
using the exact same machinery. At present, only
fixed-coupon bonds are supported. An even better way to
move forward might be to get rate helpers to return
cashflows, in which case this class could be used to fit
any set of cash flows, not just bonds.
\todo add more fitting diagnostics: smoothness, standard
deviation, student-t test, etc. Generic smoothness
method may be useful for smoothing splines fitting. See
Fisher, M., D. Nychka and D. Zervos: "Fitting the term
structure of interest rates with smoothing splines."
Board of Governors of the Federal Reserve System,
Federal Resere Board Working Paper, 95-1.
\todo add extrapolation routines
\ingroup yieldtermstructures
*/
class FittedBondDiscountCurve : public YieldTermStructure,
public LazyObject {
public:
class FittingMethod;
friend class FittingMethod;
//! \name Constructors
//@{
//! reference date based on current evaluation date
FittedBondDiscountCurve(
Natural settlementDays,
const Calendar& calendar,
const std::vector<boost::shared_ptr<BondHelper> >& bonds,
const DayCounter& dayCounter,
const FittingMethod& fittingMethod,
Real accuracy = 1.0e-10,
Size maxEvaluations = 10000,
const Array& guess = Array(),
Real simplexLambda = 1.0,
Size maxStationaryStateIterations = 100);
//! curve reference date fixed for life of curve
FittedBondDiscountCurve(
const Date &referenceDate,
const std::vector<boost::shared_ptr<BondHelper> >& bonds,
const DayCounter& dayCounter,
const FittingMethod& fittingMethod,
Real accuracy = 1.0e-10,
Size maxEvaluations = 10000,
const Array &guess = Array(),
Real simplexLambda = 1.0,
Size maxStationaryStateIterations = 100);
//@}
//! \name Inspectors
//@{
//! total number of bonds used to fit the yield curve
Size numberOfBonds() const;
//! the latest date for which the curve can return values
Date maxDate() const;
//! class holding the results of the fit
const FittingMethod& fitResults() const;
//@}
//! \name Observer interface
//@{
void update();
//@}
private:
void setup();
void performCalculations() const;
DiscountFactor discountImpl(Time) const;
// target accuracy level to be used in the optimization routine
Real accuracy_;
// max number of evaluations to be used in the optimization routine
Size maxEvaluations_;
// sets the scale in the (Simplex) optimization routine
Real simplexLambda_;
// max number of evaluations where no improvement to solution is made
Size maxStationaryStateIterations_;
// a guess solution may be passed into the constructor to speed calcs
Array guessSolution_;
mutable Date maxDate_;
std::vector<boost::shared_ptr<BondHelper> > bondHelpers_;
Clone<FittingMethod> fittingMethod_;
};
//! Base fitting method used to construct a fitted bond discount curve
/*! This base class provides the specific methodology/strategy
used to construct a FittedBondDiscountCurve. Derived classes
need only define the virtual function discountFunction() based
on the particular fitting method to be implemented, as well as
size(), the number of variables to be solved for/optimized. The
generic fitting methodology implemented here can be termed
nonlinear, in contrast to (typically faster, computationally)
linear fitting method.
Optional parameters for FittingMethod include an Array of
weights, which will be used as weights to each bond. If not given
or empty, then the bonds will be weighted by inverse duration
\todo derive the special-case class LinearFittingMethods from
FittingMethod. A linear fitting to a set of basis
functions \f$ b_i(t) \f$ is any fitting of the form
\f[
d(t) = \sum_{i=0} c_i b_i(t)
\f]
i.e., linear in the unknown coefficients \f$ c_i
\f$. Such a fitting can be reduced to a linear algebra
problem \f$ Ax = b \f$, and for large numbers of bonds,
would typically be much faster computationally than the
generic non-linear fitting method.
\warning some parameters to the Simplex optimization method
may need to be tweaked internally to the class,
depending on the fitting method used, in order to get
proper/reasonable/faster convergence.
*/
class FittedBondDiscountCurve::FittingMethod {
friend class FittedBondDiscountCurve;
// internal class
class FittingCost;
public:
virtual ~FittingMethod() {}
//! total number of coefficients to fit/solve for
virtual Size size() const = 0;
//! output array of results of optimization problem
Array solution() const;
//! final number of iterations used in the optimization problem
Integer numberOfIterations() const;
//! final value of cost function after optimization
Real minimumCostValue() const;
//! clone of the current object
virtual std::auto_ptr<FittingMethod> clone() const = 0;
//! return whether there is a constraint at zero
bool constrainAtZero() const;
//! return weights being used
Array weights() const;
//! return optimization method being used
boost::shared_ptr<OptimizationMethod> optimizationMethod() const;
//! open discountFunction to public
DiscountFactor discount(const Array& x, Time t) const;
protected:
//! constructor
FittingMethod(bool constrainAtZero = true, const Array& weights = Array(),
boost::shared_ptr<OptimizationMethod> optimizationMethod
= boost::shared_ptr<OptimizationMethod>());
//! rerun every time instruments/referenceDate changes
virtual void init();
//! discount function called by FittedBondDiscountCurve
virtual DiscountFactor discountFunction(const Array& x,
Time t) const = 0;
//! constrains discount function to unity at \f$ T=0 \f$, if true
bool constrainAtZero_;
//! internal reference to the FittedBondDiscountCurve instance
FittedBondDiscountCurve* curve_;
//! solution array found from optimization, set in calculate()
Array solution_;
//! optional guess solution to be passed into constructor.
/*! The idea is to use a previous solution as a guess solution to
the discount curve, in an attempt to speed up calculations.
*/
Array guessSolution_;
//! base class sets this cost function used in the optimization routine
boost::shared_ptr<FittingCost> costFunction_;
private:
// curve optimization called here- adjust optimization parameters here
void calculate();
// array of normalized (duration) weights, one for each bond helper
Array weights_;
// whether or not the weights should be calculated internally
bool calculateWeights_;
// total number of iterations used in the optimization routine
// (possibly including gradient evaluations)
Integer numberOfIterations_;
// final value for the minimized cost function
Real costValue_;
// optimization method to be used, if none provided use Simplex
boost::shared_ptr<OptimizationMethod> optimizationMethod_;
};
// inline
inline Size FittedBondDiscountCurve::numberOfBonds() const {
return bondHelpers_.size();
}
inline Date FittedBondDiscountCurve::maxDate() const {
calculate();
return maxDate_;
}
inline const FittedBondDiscountCurve::FittingMethod&
FittedBondDiscountCurve::fitResults() const {
calculate();
return *fittingMethod_;
}
inline void FittedBondDiscountCurve::update() {
TermStructure::update();
LazyObject::update();
}
inline void FittedBondDiscountCurve::setup() {
for (Size i=0; i<bondHelpers_.size(); ++i)
registerWith(bondHelpers_[i]);
}
inline DiscountFactor FittedBondDiscountCurve::discountImpl(Time t) const {
calculate();
return fittingMethod_->discountFunction(fittingMethod_->solution_, t);
}
inline Integer
FittedBondDiscountCurve::FittingMethod::numberOfIterations() const {
return numberOfIterations_;
}
inline
Real FittedBondDiscountCurve::FittingMethod::minimumCostValue() const {
return costValue_;
}
inline Array FittedBondDiscountCurve::FittingMethod::solution() const {
return solution_;
}
inline bool FittedBondDiscountCurve::FittingMethod::constrainAtZero() const {
return constrainAtZero_;
}
inline Array FittedBondDiscountCurve::FittingMethod::weights() const {
return weights_;
}
inline boost::shared_ptr<OptimizationMethod>
FittedBondDiscountCurve::FittingMethod::optimizationMethod() const {
return optimizationMethod_;
}
inline DiscountFactor
FittedBondDiscountCurve::FittingMethod::discount(const Array& x, Time t) const {
return discountFunction(x, t);
}
}
#endif
|