Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
quadraticinterpolation.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2021 Skandinaviska Enskilda Banken AB (publ)
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7 ORE is free software: you can redistribute it and/or modify it
8 under the terms of the Modified BSD License. You should have received a
9 copy of the license along with this program.
10 The license is also available online at <http://opensourcerisk.org>
11 This program is distributed on the basis that it will form a useful
12 contribution to risk analytics and model standardisation, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
15 */
16
17 /*! \file quadraticinterpolation.hpp
18 \brief quadratic interpolation between discrete points
19 */
20
21 #ifndef quantext_quadratic_interpolation_hpp
22 #define quantext_quadratic_interpolation_hpp
23
24 #include <ql/math/interpolation.hpp>
25 #include <ql/math/matrix.hpp>
26 #include <vector>
27
28 namespace QuantExt {
29 using namespace QuantLib;
30
31 namespace detail {
32 template<class I1, class I2> class QuadraticInterpolationImpl;
33 }
34
35 //! %Quadratic interpolation between discrete points
36 /*! \ingroup interpolations
37 \warning See the Interpolation class for information about the
38 required lifetime of the underlying data.
39 */
40 class QuadraticInterpolation : public Interpolation {
41 public:
42 /*! \pre the \f$ x \f$ values must be sorted. */
43 template <class I1, class I2>
44 QuadraticInterpolation(const I1& xBegin, const I1& xEnd,
45 const I2& yBegin,
46 Real x_mul = 1, Real x_offset = 0,
47 Real y_mul = 1, Real y_offset = 0,
48 Size skip = 0) {
49 impl_ = ext::shared_ptr<Interpolation::Impl>(new
51 xBegin + skip, xEnd, yBegin + skip,
52 x_mul, x_offset, y_mul, y_offset));
53 impl_->update();
54 }
55 template <class I1, class I2>
56 std::vector<Real> lambdas() const {
57 ext::shared_ptr<detail::QuadraticInterpolationImpl<I1,I2> > p =
58 ext::dynamic_pointer_cast<
60 QL_REQUIRE(p, "unable to cast impl to "
61 "QuadraticInterpolationImpl<I1,I2>");
62 return p->lambdas();
63 }
64 };
65
66 //! %Quadratic-interpolation factory and traits
67 /*! \ingroup interpolations */
68 class Quadratic {
69 public:
70 Quadratic(Real x_mul = 1, Real x_offset = 0,
71 Real y_mul = 1, Real y_offset = 0,
72 Size skip = 0)
73 : x_mul_(x_mul), x_offset_(x_offset),
74 y_mul_(y_mul), y_offset_(y_offset),
75 skip_(skip) {}
76 template <class I1, class I2>
77 Interpolation interpolate(const I1& xBegin, const I1& xEnd,
78 const I2& yBegin) const {
80 xBegin, xEnd, yBegin,
82 }
83 template <class I1, class I2>
84 QuantLib::ext::shared_ptr<QuadraticInterpolation> interpolatePtr(
85 const I1& xBegin, const I1& xEnd,
86 const I2& yBegin) const {
87 return QuantLib::ext::make_shared<QuadraticInterpolation>(
88 xBegin, xEnd, yBegin,
90 }
91 static const bool global = false;
92 static const Size requiredPoints = 1;
93 Real x_mul_;
95 Real y_mul_;
97 Size skip_;
98 };
99
100 namespace detail {
101
102 template <class I1, class I2>
104 : public Interpolation::templateImpl<I1,I2> {
105 public:
106 QuadraticInterpolationImpl(const I1& xBegin, const I1& xEnd,
107 const I2& yBegin,
108 Real x_mul = 1,
109 Real x_offset = 0,
110 Real y_mul = 1,
111 Real y_offset = 0)
112 : Interpolation::templateImpl<I1,I2>(xBegin, xEnd, yBegin,
113 Quadratic::requiredPoints),
114 n_(static_cast<int>(xEnd-xBegin)),
115 x_mul_(x_mul), x_offset_(x_offset),
116 y_mul_(y_mul), y_offset_(y_offset),
117 x_(std::vector<Real>(n_)),
118 y_(std::vector<Real>(n_+1)),
119 lambdas_(std::vector<Real>(n_)) {}
120 std::vector<Real> lambdas() const {
121 return lambdas_;
122 }
123 void update() override {
124
125 for(Size i=0; i < n_; ++i) {
126 x_[i] = this->xBegin_[i] * x_mul_ + x_offset_;
127 y_[i] = this->yBegin_[i] * y_mul_ + y_offset_;
128 }
129 y_[n_] = 0;
130
131 // Return if x <= 0 or y = 0
132 // Error will be thrown when calling value or
133 // derivative functions
134 for(Size i=0; i < n_; ++i) {
135 if(x_[i] <= 0 || QuantLib::close_enough(y_[i], 0.0)) {
136 p_ = Null<Real>();
137 return;
138 }
139 }
140
141 Matrix q(n_+1, n_+1, 0.0);
142 for(Size i=0; i<n_; ++i) {
143 q[i][0] = q[n_][i+1] = x_[i];
144
145 for(Size j=0; j<i; ++j) {
146 q[i][j+1] += std::pow(x_[i] - x_[j], 3) / 6.0;
147 }
148 Time t = -std::pow(x_[i], 3) / 6.0;
149 for(Size j=1; j<n_+1; ++j) {
150 q[i][j] += t;
151 }
152 }
153 Matrix q_inv = QuantLib::inverse(q);
154 Array l(y_.begin(), y_.end());
155
156 Array lambdaArray = q_inv * l;
157 lambdas_ = std::vector<Real>(lambdaArray.begin(),
158 lambdaArray.end());
159
160 p_ = 0;
161 for(Size i=1; i < n_+1; ++i) {
162 p_ += lambdaArray[i];
163 }
164 }
165 Real value(Real x) const override {
166 QL_REQUIRE(p_ != Null<Real>(), "failed to calibrate lambda");
167 x = x * x_mul_ + x_offset_;
168 Real l = lambdas_[0] * x;
169 Real b = 0;
170 for (Size i=0; i<n_ && x_[i]<x; ++i) {
171 b += lambdas_[i+1] * std::pow(x - x_[i], 3);
172 }
173 l += (b - p_ * std::pow(x, 3)) / 6.0;
174 return (l - y_offset_) / y_mul_;
175 }
176 Real primitive(Real x) const override {
177 QL_FAIL("QuadraticInterpolation primitive is not implemented");
178 }
179 Real derivative(Real x) const override {
180 QL_REQUIRE(p_ != 0.0, "failed to calibrate lambda");
181 x = x * x_mul_ + x_offset_;
182 Real l = lambdas_[0];
183 Real b = 0;
184 for (Size i=0; i<n_ && x_[i]<x; ++i) {
185 b += lambdas_[i+1] * std::pow(x - x_[i], 2);
186 }
187 l += (b - p_ * std::pow(x, 2)) / 2.0;
188 return l / y_mul_;
189 }
190 Real secondDerivative(Real x) const override {
191 QL_REQUIRE(p_ != 0.0, "failed to calibrate lambda");
192 x = x * x_mul_ + x_offset_;
193 Real l = 0;
194 Real b = 0;
195 for (Size i=0; i<n_ && x_[i]<x; ++i) {
196 b += lambdas_[i+1] * (x - x_[i]);
197 }
198 l += (b - p_* x);
199 return l / y_mul_;;
200 }
201 private:
202 const Size n_;
203 Real p_;
204 Real x_mul_;
206 Real y_mul_;
208 std::vector<Real> x_;
209 std::vector<Real> y_;
210 std::vector<Real> lambdas_;
211 };
212
213 }
214
215 }
216
217 #endif
Quadratic-interpolation factory and traits
Quadratic(Real x_mul=1, Real x_offset=0, Real y_mul=1, Real y_offset=0, Size skip=0)
static const Size requiredPoints
QuantLib::ext::shared_ptr< QuadraticInterpolation > interpolatePtr(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
Interpolation interpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
Quadratic interpolation between discrete points
std::vector< Real > lambdas() const
QuadraticInterpolation(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, Real x_mul=1, Real x_offset=0, Real y_mul=1, Real y_offset=0, Size skip=0)
QuadraticInterpolationImpl(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, Real x_mul=1, Real x_offset=0, Real y_mul=1, Real y_offset=0)