QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.38
Loading...
Searching...
No Matches
fittedbonddiscountcurve.hpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2007 Allen Kuo
5 Copyright (C) 2009 Ferdinando Ametrano
6 Copyright (C) 2015 Andres Hernandez
7
8 This file is part of QuantLib, a free-software/open-source library
9 for financial quantitative analysts and developers - http://quantlib.org/
10
11 QuantLib is free software: you can redistribute it and/or modify it
12 under the terms of the QuantLib license. You should have received a
13 copy of the license along with this program; if not, please email
14 <quantlib-dev@lists.sf.net>. The license is also available online at
15 <http://quantlib.org/license.shtml>.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the license for more details.
20*/
21
22/*! \file fittedbonddiscountcurve.hpp
23 \brief discount curve fitted to a set of bonds
24*/
25
26#ifndef quantlib_fitted_bond_discount_curve_hpp
27#define quantlib_fitted_bond_discount_curve_hpp
28
32#include <ql/math/array.hpp>
35
36namespace QuantLib {
37
38 //! Discount curve fitted to a set of fixed-coupon bonds
39 /*! This class fits a discount function \f$ d(t) \f$ over a set of
40 bonds, using a user defined fitting method. The discount
41 function is fit in such a way so that all cashflows of all
42 input bonds, when discounted using \f$ d(t) \f$, will
43 reproduce the set of input bond prices in an optimized
44 sense. Minimized price errors are weighted by the inverse of
45 their respective bond duration.
46
47 The FittedBondDiscountCurve class acts as a generic wrapper,
48 while its inner class FittingMethod provides the
49 implementation details. Developers thus need only derive new
50 fitting methods from the latter.
51
52 \warning The method can be slow if there are many bonds to
53 fit. Speed also depends on the particular choice of
54 fitting method chosen and its convergence properties
55 under optimization. See also todo list for
56 BondDiscountCurveFittingMethod.
57
58 \todo refactor the bond helper class so that it is pure
59 virtual and returns a generic bond or its cash
60 flows. Derived classes would include helpers for
61 fixed-rate and zero-coupon bonds. In this way, both
62 bonds and bills can be used to fit a discount curve
63 using the exact same machinery. At present, only
64 fixed-coupon bonds are supported. An even better way to
65 move forward might be to get rate helpers to return
66 cashflows, in which case this class could be used to fit
67 any set of cash flows, not just bonds.
68
69 \todo add more fitting diagnostics: smoothness, standard
70 deviation, student-t test, etc. Generic smoothness
71 method may be useful for smoothing splines fitting. See
72 Fisher, M., D. Nychka and D. Zervos: "Fitting the term
73 structure of interest rates with smoothing splines."
74 Board of Governors of the Federal Reserve System,
75 Federal Resere Board Working Paper, 95-1.
76
77 \todo add extrapolation routines
78
79 \ingroup yieldtermstructures
80 */
82 public LazyObject {
83 public:
84 class FittingMethod;
85
86 //! \name Constructors
87 //@{
88 //! reference date based on current evaluation date
90 const Calendar& calendar,
91 std::vector<ext::shared_ptr<BondHelper> > bonds,
93 const FittingMethod& fittingMethod,
94 Real accuracy = 1.0e-10,
95 Size maxEvaluations = 10000,
96 Array guess = Array(),
97 Real simplexLambda = 1.0,
98 Size maxStationaryStateIterations = 100);
99
100 //! curve reference date fixed for life of curve
102 std::vector<ext::shared_ptr<BondHelper> > bonds,
103 const DayCounter& dayCounter,
104 const FittingMethod& fittingMethod,
105 Real accuracy = 1.0e-10,
106 Size maxEvaluations = 10000,
107 Array guess = Array(),
108 Real simplexLambda = 1.0,
109 Size maxStationaryStateIterations = 100);
110
111 //! don't fit, use precalculated parameters
113 const Calendar& calendar,
114 const FittingMethod& fittingMethod,
115 Array parameters,
117 const DayCounter& dayCounter);
118
119 //! don't fit, use precalculated parameters
121 const FittingMethod& fittingMethod,
122 Array parameters,
124 const DayCounter& dayCounter);
125 //@}
126
127 //! \name Inspectors
128 //@{
129 //! total number of bonds used to fit the yield curve
130 Size numberOfBonds() const;
131 //! the latest date for which the curve can return values
132 Date maxDate() const override;
133 //! class holding the results of the fit
134 const FittingMethod& fitResults() const;
135 //@}
136
137 //! \name Other utilities
138 //@{
139 /*! This allows to try out multiple guesses and avoid local minima */
140 void resetGuess(const Array& guess);
141 //@}
142
143 //! \name Observer interface
144 //@{
145 void update() override;
146 //@}
147
148 private:
149 void setup();
150 void performCalculations() const override;
151 DiscountFactor discountImpl(Time) const override;
152 // target accuracy level to be used in the optimization routine
154 // max number of evaluations to be used in the optimization routine
156 // sets the scale in the (Simplex) optimization routine
158 // max number of evaluations where no improvement to solution is made
160 // a guess solution may be passed into the constructor to speed calcs
162 mutable Date maxDate_;
163 std::vector<ext::shared_ptr<BondHelper> > bondHelpers_;
165 };
166
167
168 //! Base fitting method used to construct a fitted bond discount curve
169 /*! This base class provides the specific methodology/strategy
170 used to construct a FittedBondDiscountCurve. Derived classes
171 need only define the virtual function discountFunction() based
172 on the particular fitting method to be implemented, as well as
173 size(), the number of variables to be solved for/optimized. The
174 generic fitting methodology implemented here can be termed
175 nonlinear, in contrast to (typically faster, computationally)
176 linear fitting method.
177
178 Optional parameters for FittingMethod include an Array of
179 weights, which will be used as weights to each bond. If not given
180 or empty, then the bonds will be weighted by inverse duration
181
182 An optional Array may be provided as an L2 regularizor in this case
183 a L2 (gaussian) penalty is applied to each parameter starting from the
184 initial guess. This is the same as giving a Gaussian prior on the parameters
185
186 \todo derive the special-case class LinearFittingMethods from
187 FittingMethod. A linear fitting to a set of basis
188 functions \f$ b_i(t) \f$ is any fitting of the form
189 \f[
190 d(t) = \sum_{i=0} c_i b_i(t)
191 \f]
192 i.e., linear in the unknown coefficients \f$ c_i
193 \f$. Such a fitting can be reduced to a linear algebra
194 problem \f$ Ax = b \f$, and for large numbers of bonds,
195 would typically be much faster computationally than the
196 generic non-linear fitting method.
197
198 \warning some parameters to the Simplex optimization method
199 may need to be tweaked internally to the class,
200 depending on the fitting method used, in order to get
201 proper/reasonable/faster convergence.
202 */
205 // internal class
206 class FittingCost;
207 public:
208 virtual ~FittingMethod() = default;
209 //! total number of coefficients to fit/solve for
210 virtual Size size() const = 0;
211 //! output array of results of optimization problem
212 Array solution() const;
213 //! final number of iterations used in the optimization problem
215 //! final value of cost function after optimization
216 Real minimumCostValue() const;
217 //! error code of the optimization
219 //! clone of the current object
220 virtual std::unique_ptr<FittingMethod> clone() const = 0;
221 //! return whether there is a constraint at zero
222 bool constrainAtZero() const;
223 //! return weights being used
224 Array weights() const;
225 //! return l2 penalties being used
226 Array l2() const;
227 //! return optimization method being used
228 ext::shared_ptr<OptimizationMethod> optimizationMethod() const;
229 //! return optimization contraint
230 const Constraint& constraint() const;
231 //! open discountFunction to public
232 DiscountFactor discount(const Array& x, Time t) const;
233 protected:
234 //! constructors
235 FittingMethod(bool constrainAtZero = true,
236 const Array& weights = Array(),
237 ext::shared_ptr<OptimizationMethod> optimizationMethod =
238 ext::shared_ptr<OptimizationMethod>(),
239 Array l2 = Array(),
240 Real minCutoffTime = 0.0,
241 Real maxCutoffTime = QL_MAX_REAL,
243 //! rerun every time instruments/referenceDate changes
244 virtual void init();
245 //! discount function called by FittedBondDiscountCurve
247 Time t) const = 0;
248
249 //! constrains discount function to unity at \f$ T=0 \f$, if true
251 //! internal reference to the FittedBondDiscountCurve instance
253 //! solution array found from optimization, set in calculate()
255 //! optional guess solution to be passed into constructor.
256 /*! The idea is to use a previous solution as a guess solution to
257 the discount curve, in an attempt to speed up calculations.
258 */
260 //! base class sets this cost function used in the optimization routine
261 ext::shared_ptr<FittingCost> costFunction_;
262 private:
263 // curve optimization called here- adjust optimization parameters here
264 void calculate();
265 // array of normalized (duration) weights, one for each bond helper
267 // array of l2 penalties one for each parameter
269 // whether or not the weights should be calculated internally
271 // total number of iterations used in the optimization routine
272 // (possibly including gradient evaluations)
274 // final value for the minimized cost function
276 // error code returned by OptimizationMethod::minimize()
278 // optimization method to be used, if none provided use Simplex
279 ext::shared_ptr<OptimizationMethod> optimizationMethod_;
280 // optimization constraint, if none provided use NoConstraint
282 // flat extrapolation of instantaneous forward before / after cutoff
284 };
285
286 // inline
287
289 return bondHelpers_.size();
290 }
291
293 calculate();
294 return maxDate_;
295 }
296
299 calculate();
300 return *fittingMethod_;
301 }
302
306 }
307
309 for (auto& bondHelper : bondHelpers_)
310 registerWith(bondHelper);
311 }
312
314 calculate();
315 return fittingMethod_->discount(fittingMethod_->solution_, t);
316 }
317
318 inline Integer
320 return numberOfIterations_;
321 }
322
323 inline
325 return costValue_;
326 }
327
328 inline
330 return errorCode_;
331 }
332
334 return solution_;
335 }
336
338 return constrainAtZero_;
339 }
340
342 return weights_;
343 }
344
346 return l2_;
347 }
348
349 inline ext::shared_ptr<OptimizationMethod>
351 return optimizationMethod_;
352 }
353
355 return constraint_;
356 }
357
359 if (t < minCutoffTime_) {
360 // flat fwd extrapolation before min cutoff time
361 return std::exp(std::log(discountFunction(x, minCutoffTime_)) / minCutoffTime_ * t);
362 } else if (t > maxCutoffTime_) {
363 // flat fwd extrapolation after max cutoff time
364 return discountFunction(x, maxCutoffTime_) *
365 std::exp((std::log(discountFunction(x, maxCutoffTime_ + 1E-4)) -
366 std::log(discountFunction(x, maxCutoffTime_))) *
367 1E4 * (t - maxCutoffTime_));
368 } else {
369 return discountFunction(x, t);
370 }
371 }
372}
373
374#endif
1-D array used in linear algebra.
bond rate helpers
1-D array used in linear algebra.
Definition: array.hpp:52
calendar class
Definition: calendar.hpp:61
cloning proxy to an underlying object
Definition: clone.hpp:40
Base constraint class.
Definition: constraint.hpp:35
Concrete date class.
Definition: date.hpp:125
day counter class
Definition: daycounter.hpp:44
Base fitting method used to construct a fitted bond discount curve.
FittedBondDiscountCurve * curve_
internal reference to the FittedBondDiscountCurve instance
virtual void init()
rerun every time instruments/referenceDate changes
virtual Size size() const =0
total number of coefficients to fit/solve for
const Constraint & constraint() const
return optimization contraint
Array guessSolution_
optional guess solution to be passed into constructor.
ext::shared_ptr< OptimizationMethod > optimizationMethod_
bool constrainAtZero() const
return whether there is a constraint at zero
Real minimumCostValue() const
final value of cost function after optimization
Integer numberOfIterations() const
final number of iterations used in the optimization problem
Array solution_
solution array found from optimization, set in calculate()
bool constrainAtZero_
constrains discount function to unity at , if true
virtual std::unique_ptr< FittingMethod > clone() const =0
clone of the current object
virtual DiscountFactor discountFunction(const Array &x, Time t) const =0
discount function called by FittedBondDiscountCurve
EndCriteria::Type errorCode() const
error code of the optimization
Array l2() const
return l2 penalties being used
ext::shared_ptr< OptimizationMethod > optimizationMethod() const
return optimization method being used
ext::shared_ptr< FittingCost > costFunction_
base class sets this cost function used in the optimization routine
DiscountFactor discount(const Array &x, Time t) const
open discountFunction to public
Array solution() const
output array of results of optimization problem
Discount curve fitted to a set of fixed-coupon bonds.
const FittingMethod & fitResults() const
class holding the results of the fit
std::vector< ext::shared_ptr< BondHelper > > bondHelpers_
DiscountFactor discountImpl(Time) const override
discount factor calculation
Date maxDate() const override
the latest date for which the curve can return values
Size numberOfBonds() const
total number of bonds used to fit the yield curve
Framework for calculation on demand and result caching.
Definition: lazyobject.hpp:35
virtual void calculate() const
Definition: lazyobject.hpp:253
void update() override
Definition: lazyobject.hpp:188
No constraint.
Definition: constraint.hpp:79
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:226
virtual Natural settlementDays() const
the settlementDays used for reference date calculation
virtual const Date & referenceDate() const
the date at which discount = 1.0 and/or variance = 0.0
virtual Calendar calendar() const
the calendar used for reference and/or option date calculation
virtual DayCounter dayCounter() const
the day counter used for date/time conversion
Interest-rate term structure.
cloning proxy to an underlying object
Abstract constraint class.
const DefaultType & t
#define QL_MAX_REAL
Definition: qldefines.hpp:176
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
unsigned QL_INTEGER Natural
positive integer
Definition: types.hpp:43
QL_INTEGER Integer
integer number
Definition: types.hpp:35
std::size_t Size
size of a container
Definition: types.hpp:58
framework for calculation on demand and result caching
Abstract optimization method class.
Definition: any.hpp:37