QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.38
Loading...
Searching...
No Matches
nonlinearfittingmethods.cpp
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) 2010 Alessandro Roveda
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
24#include <utility>
25
26namespace QuantLib {
27
29 bool constrainAtZero,
30 const Array& weights,
31 const ext::shared_ptr<OptimizationMethod>& optimizationMethod,
32 const Array& l2,
33 const Real minCutoffTime,
34 const Real maxCutoffTime,
35 const Size numCoeffs,
36 const Real fixedKappa,
37 Constraint constraint)
38 : FittedBondDiscountCurve::FittingMethod(constrainAtZero, weights, optimizationMethod, l2,
39 minCutoffTime, maxCutoffTime, std::move(constraint)),
40 numCoeffs_(numCoeffs), fixedKappa_(fixedKappa) {
41 QL_REQUIRE(ExponentialSplinesFitting::size() > 0, "At least 1 unconstrained coefficient required");
42 }
43
45 bool constrainAtZero,
46 const Array& weights,
47 const Array& l2, const Real minCutoffTime, const Real maxCutoffTime,
48 const Size numCoeffs, const Real fixedKappa,
49 Constraint constraint)
50 : ExponentialSplinesFitting(constrainAtZero, weights, {}, l2,
51 minCutoffTime, maxCutoffTime,
52 numCoeffs, fixedKappa, std::move(constraint)) {}
53
55 bool constrainAtZero,
56 const Size numCoeffs,
57 const Real fixedKappa,
58 const Array& weights,
59 Constraint constraint)
60 : ExponentialSplinesFitting(constrainAtZero, weights, {}, Array(),
61 0.0, QL_MAX_REAL,
62 numCoeffs, fixedKappa, std::move(constraint)) {}
63
64 std::unique_ptr<FittedBondDiscountCurve::FittingMethod>
66 return std::make_unique<ExponentialSplinesFitting>(*this);
67 }
68
71
72 return (fixedKappa_ != Null<Real>()) ? N-1 : N; //One fewer optimization parameters if kappa is fixed
73 }
74
76 Time t) const {
77 DiscountFactor d = 0.0;
78 Size N = size();
79 //Use the interal fixedKappa_ member if non-zero, otherwise take kappa from the passed x[] array
80 Real kappa = (fixedKappa_ != Null<Real>()) ? fixedKappa_: x[N-1];
81 Real coeff = 0;
82
83 if (!constrainAtZero_) {
84 for (Size i = 0; i < N - 1; ++i) {
85 d += x[i] * std::exp(-kappa * (i + 1) * t);
86 }
87 } else {
88 // notation:
89 // d(t) = coeff* exp(-kappa*1*t) + x[0]* exp(-kappa*2*t) +
90 // x[1]* exp(-kappa*3*t) + ..+ x[7]* exp(-kappa*9*t)
91 for (Size i = 0; i < N - 1; i++) {
92 d += x[i] * std::exp(-kappa * (i + 2) * t);
93 coeff += x[i];
94 }
95 coeff = 1.0 - coeff;
96 d += coeff * std::exp(-kappa * t);
97 }
98
99 return d;
100 }
101
102
104 const Array& weights,
105 const ext::shared_ptr<OptimizationMethod>& optimizationMethod,
106 const Array& l2,
107 const Real minCutoffTime,
108 const Real maxCutoffTime,
109 Constraint constraint)
110 : FittedBondDiscountCurve::FittingMethod(true, weights, optimizationMethod, l2,
111 minCutoffTime, maxCutoffTime, std::move(constraint)) {}
112
114 const Array& weights,
115 const Array& l2,
116 const Real minCutoffTime,
117 const Real maxCutoffTime,
118 Constraint constraint)
119 : NelsonSiegelFitting(weights, {}, l2,
120 minCutoffTime, maxCutoffTime, std::move(constraint)) {}
121
122 std::unique_ptr<FittedBondDiscountCurve::FittingMethod>
124 return std::make_unique<NelsonSiegelFitting>(*this);
125 }
126
128 return 4;
129 }
130
132 Time t) const {
133 Real kappa = x[size()-1];
134 Real zeroRate = x[0] + (x[1] + x[2])*
135 (1.0 - std::exp(-kappa*t))/
137 (x[2])*std::exp(-kappa*t);
138 DiscountFactor d = std::exp(-zeroRate * t) ;
139 return d;
140 }
141
142
144 const ext::shared_ptr<OptimizationMethod>& optimizationMethod,
145 const Array& l2,
146 const Real minCutoffTime,
147 const Real maxCutoffTime,
148 Constraint constraint)
149 : FittedBondDiscountCurve::FittingMethod(true, weights, optimizationMethod, l2,
150 minCutoffTime, maxCutoffTime, std::move(constraint)) {}
151
153 const Array& l2,
154 const Real minCutoffTime,
155 const Real maxCutoffTime,
156 Constraint constraint)
157 : SvenssonFitting(weights, {}, l2,
158 minCutoffTime, maxCutoffTime, std::move(constraint)) {}
159
160 std::unique_ptr<FittedBondDiscountCurve::FittingMethod>
162 return std::make_unique<SvenssonFitting>(*this);
163 }
164
166 return 6;
167 }
168
170 Time t) const {
171 Real kappa = x[size()-2];
172 Real kappa_1 = x[size()-1];
173
174 Real zeroRate = x[0] + (x[1] + x[2])*
175 (1.0 - std::exp(-kappa*t))/
177 (x[2])*std::exp(-kappa*t) +
178 x[3]* (((1.0 - std::exp(-kappa_1*t))/((kappa_1+QL_EPSILON)*(t+QL_EPSILON)))- std::exp(-kappa_1*t));
179 DiscountFactor d = std::exp(-zeroRate * t) ;
180 return d;
181 }
182
183
185 const std::vector<Time>& knots,
186 bool constrainAtZero,
187 const Array& weights,
188 const ext::shared_ptr<OptimizationMethod>& optimizationMethod,
189 const Array& l2,
190 const Real minCutoffTime,
191 const Real maxCutoffTime,
192 Constraint constraint)
193 : FittedBondDiscountCurve::FittingMethod(constrainAtZero, weights, optimizationMethod, l2,
194 minCutoffTime, maxCutoffTime, std::move(constraint)),
195 splines_(3, knots.size() - 5, knots) {
196
197 QL_REQUIRE(knots.size() >= 8,
198 "At least 8 knots are required" );
199 Size basisFunctions = knots.size() - 4;
200
201 if (constrainAtZero) {
202 size_ = basisFunctions-1;
203
204 // Note: A small but nonzero N_th basis function at t=0 may
205 // lead to an ill conditioned problem
206 N_ = 1;
207
208 QL_REQUIRE(std::abs(splines_(N_, 0.0)) > QL_EPSILON,
209 "N_th cubic B-spline must be nonzero at t=0");
210 } else {
211 size_ = basisFunctions;
212 N_ = 0;
213 }
214 }
215
217 const std::vector<Time>& knots,
218 bool constrainAtZero,
219 const Array& weights,
220 const Array& l2,
221 const Real minCutoffTime,
222 const Real maxCutoffTime,
223 Constraint constraint)
224 : CubicBSplinesFitting(knots, constrainAtZero, weights, {}, l2,
225 minCutoffTime, maxCutoffTime, std::move(constraint)) {}
226
228 return splines_(i,t);
229 }
230
231 std::unique_ptr<FittedBondDiscountCurve::FittingMethod>
233 return std::make_unique<CubicBSplinesFitting>(*this);
234 }
235
237 return size_;
238 }
239
241 Time t) const {
242 DiscountFactor d = 0.0;
243
244 if (!constrainAtZero_) {
245 for (Size i=0; i<size_; ++i) {
246 d += x[i] * splines_(i,t);
247 }
248 } else {
249 const Real T = 0.0;
250 Real sum = 0.0;
251 for (Size i=0; i<size_; ++i) {
252 if (i < N_) {
253 d += x[i] * splines_(i,t);
254 sum += x[i] * splines_(i,T);
255 } else {
256 d += x[i] * splines_(i+1,t);
257 sum += x[i] * splines_(i+1,T);
258 }
259 }
260 Real coeff = 1.0 - sum;
261 coeff /= splines_(N_,T);
262 d += coeff * splines_(N_,t);
263 }
264
265 return d;
266 }
267
268
270 Natural degree,
271 bool constrainAtZero,
272 const Array& weights,
273 const ext::shared_ptr<OptimizationMethod>& optimizationMethod,
274 const Array& l2,
275 const Real minCutoffTime,
276 const Real maxCutoffTime,
277 Constraint constraint)
278 : FittedBondDiscountCurve::FittingMethod(constrainAtZero, weights, optimizationMethod, l2,
279 minCutoffTime, maxCutoffTime, std::move(constraint)),
280 size_(constrainAtZero ? degree : degree + 1) {}
281
283 Natural degree,
284 bool constrainAtZero,
285 const Array& weights,
286 const Array& l2,
287 const Real minCutoffTime,
288 const Real maxCutoffTime,
289 Constraint constraint)
290 : SimplePolynomialFitting(degree, constrainAtZero, weights, {}, l2,
291 minCutoffTime, maxCutoffTime, std::move(constraint)) {}
292
293 std::unique_ptr<FittedBondDiscountCurve::FittingMethod>
295 return std::make_unique<SimplePolynomialFitting>(*this);
296 }
297
299 return size_;
300 }
301
303 Time t) const {
304 DiscountFactor d = 0.0;
305
306 if (!constrainAtZero_) {
307 for (Size i=0; i<size_; ++i)
308 d += x[i] * BernsteinPolynomial::get(i,i,t);
309 } else {
310 d = 1.0;
311 for (Size i=0; i<size_; ++i)
312 d += x[i] * BernsteinPolynomial::get(i+1,i+1,t);
313 }
314 return d;
315 }
316
317 SpreadFittingMethod::SpreadFittingMethod(const ext::shared_ptr<FittingMethod>& method,
318 Handle<YieldTermStructure> discountCurve,
319 const Real minCutoffTime,
320 const Real maxCutoffTime)
321 : FittedBondDiscountCurve::FittingMethod(
322 method != nullptr ? method->constrainAtZero() : true,
323 method != nullptr ? method->weights() : Array(),
324 method != nullptr ? method->optimizationMethod() : ext::shared_ptr<OptimizationMethod>(),
325 method != nullptr ? method->l2() : Array(),
326 minCutoffTime,
327 maxCutoffTime),
328 method_(method), discountingCurve_(std::move(discountCurve)) {
329 QL_REQUIRE(method, "Fitting method is empty");
330 QL_REQUIRE(!discountingCurve_.empty(), "Discounting curve cannot be empty");
331 }
332
333 std::unique_ptr<FittedBondDiscountCurve::FittingMethod>
335 return std::make_unique<SpreadFittingMethod>(*this);
336 }
337
339 return method_->size();
340 }
341
343 return method_->discount(x, t)*discountingCurve_->discount(t, true)/rebase_;
344 }
345
347 //In case discount curve has a different reference date,
348 //discount to this curve's reference date
349 if (curve_->referenceDate() != discountingCurve_->referenceDate()){
351 }
352 else{
353 rebase_ = 1.0;
354 }
355 //Call regular init
357 }
358}
359
Bernstein polynomials.
1-D array used in linear algebra.
Definition: array.hpp:52
static Real get(Natural i, Natural n, Real x)
Base constraint class.
Definition: constraint.hpp:35
CubicSpline B-splines fitting method.
std::unique_ptr< FittedBondDiscountCurve::FittingMethod > clone() const override
clone of the current object
Size size() const override
total number of coefficients to fit/solve for
Real basisFunction(Integer i, Time t) const
cubic B-spline basis functions
Natural N_
N_th basis function coefficient to solve for when d(0)=1.
DiscountFactor discountFunction(const Array &x, Time t) const override
discount function called by FittedBondDiscountCurve
CubicBSplinesFitting(const std::vector< Time > &knotVector, bool constrainAtZero=true, const Array &weights=Array(), const ext::shared_ptr< OptimizationMethod > &optimizationMethod={}, const Array &l2=Array(), Real minCutoffTime=0.0, Real maxCutoffTime=QL_MAX_REAL, Constraint constraint=NoConstraint())
Exponential-splines fitting method.
std::unique_ptr< FittedBondDiscountCurve::FittingMethod > clone() const override
clone of the current object
Size size() const override
total number of coefficients to fit/solve for
ExponentialSplinesFitting(bool constrainAtZero=true, const Array &weights=Array(), const ext::shared_ptr< OptimizationMethod > &optimizationMethod={}, const Array &l2=Array(), Real minCutoffTime=0.0, Real maxCutoffTime=QL_MAX_REAL, Size numCoeffs=9, Real fixedKappa=Null< Real >(), Constraint constraint=NoConstraint())
DiscountFactor discountFunction(const Array &x, Time t) const override
discount function called by FittedBondDiscountCurve
FittedBondDiscountCurve * curve_
internal reference to the FittedBondDiscountCurve instance
virtual void init()
rerun every time instruments/referenceDate changes
bool constrainAtZero() const
return whether there is a constraint at zero
bool constrainAtZero_
constrains discount function to unity at , if true
Discount curve fitted to a set of fixed-coupon bonds.
Shared handle to an observable.
Definition: handle.hpp:41
Nelson-Siegel fitting method.
std::unique_ptr< FittedBondDiscountCurve::FittingMethod > clone() const override
clone of the current object
Size size() const override
total number of coefficients to fit/solve for
NelsonSiegelFitting(const Array &weights=Array(), const ext::shared_ptr< OptimizationMethod > &optimizationMethod={}, const Array &l2=Array(), Real minCutoffTime=0.0, Real maxCutoffTime=QL_MAX_REAL, Constraint constraint=NoConstraint())
DiscountFactor discountFunction(const Array &x, Time t) const override
discount function called by FittedBondDiscountCurve
template class providing a null value for a given type.
Definition: null.hpp:59
Abstract class for constrained optimization method.
Definition: method.hpp:36
Simple polynomial fitting method.
std::unique_ptr< FittedBondDiscountCurve::FittingMethod > clone() const override
clone of the current object
SimplePolynomialFitting(Natural degree, bool constrainAtZero=true, const Array &weights=Array(), const ext::shared_ptr< OptimizationMethod > &optimizationMethod={}, const Array &l2=Array(), Real minCutoffTime=0.0, Real maxCutoffTime=QL_MAX_REAL, Constraint constraint=NoConstraint())
Size size() const override
total number of coefficients to fit/solve for
DiscountFactor discountFunction(const Array &x, Time t) const override
discount function called by FittedBondDiscountCurve
std::unique_ptr< FittedBondDiscountCurve::FittingMethod > clone() const override
clone of the current object
Size size() const override
total number of coefficients to fit/solve for
SpreadFittingMethod(const ext::shared_ptr< FittingMethod > &method, Handle< YieldTermStructure > discountCurve, Real minCutoffTime=0.0, Real maxCutoffTime=QL_MAX_REAL)
Handle< YieldTermStructure > discountingCurve_
ext::shared_ptr< FittingMethod > method_
void init() override
rerun every time instruments/referenceDate changes
DiscountFactor discountFunction(const Array &x, Time t) const override
discount function called by FittedBondDiscountCurve
std::unique_ptr< FittedBondDiscountCurve::FittingMethod > clone() const override
clone of the current object
Size size() const override
total number of coefficients to fit/solve for
SvenssonFitting(const Array &weights=Array(), const ext::shared_ptr< OptimizationMethod > &optimizationMethod={}, const Array &l2=Array(), Real minCutoffTime=0.0, Real maxCutoffTime=QL_MAX_REAL, Constraint constraint=NoConstraint())
DiscountFactor discountFunction(const Array &x, Time t) const override
discount function called by FittedBondDiscountCurve
virtual const Date & referenceDate() const
the date at which discount = 1.0 and/or variance = 0.0
const DefaultType & t
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
Date d
#define QL_MAX_REAL
Definition: qldefines.hpp:176
#define QL_EPSILON
Definition: qldefines.hpp:178
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
Real kappa
Definition: any.hpp:37
STL namespace.
nonlinear methods to fit a bond discount function
Size size_
Definition: pseudosqrt.cpp:77