/src/quantlib/ql/math/interpolations/abcdinterpolation.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2007 Ferdinando Ametrano |
5 | | Copyright (C) 2007 Cristina Duminuco |
6 | | Copyright (C) 2007 Giorgio Facchinetti |
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 abcdinterpolation.hpp |
23 | | \brief Abcd interpolation interpolation between discrete points |
24 | | */ |
25 | | |
26 | | #ifndef quantlib_abcd_interpolation_hpp |
27 | | #define quantlib_abcd_interpolation_hpp |
28 | | |
29 | | #include <ql/math/interpolation.hpp> |
30 | | #include <ql/math/interpolations/linearinterpolation.hpp> |
31 | | #include <ql/termstructures/volatility/abcd.hpp> |
32 | | #include <ql/termstructures/volatility/abcdcalibration.hpp> |
33 | | #include <utility> |
34 | | |
35 | | namespace QuantLib { |
36 | | |
37 | | class EndCriteria; |
38 | | class OptimizationMethod; |
39 | | |
40 | | namespace detail { |
41 | | |
42 | | class AbcdCoeffHolder { |
43 | | public: |
44 | | AbcdCoeffHolder(Real a, |
45 | | Real b, |
46 | | Real c, |
47 | | Real d, |
48 | | bool aIsFixed, |
49 | | bool bIsFixed, |
50 | | bool cIsFixed, |
51 | | bool dIsFixed) |
52 | 0 | : a_(a), b_(b), c_(c), d_(d), |
53 | | |
54 | 0 | error_(Null<Real>()), maxError_(Null<Real>()) { |
55 | 0 | if (a_ != Null<Real>()) |
56 | 0 | aIsFixed_ = aIsFixed; |
57 | 0 | else a_ = -0.06; |
58 | 0 | if (b_ != Null<Real>()) |
59 | 0 | bIsFixed_ = bIsFixed; |
60 | 0 | else b_ = 0.17; |
61 | 0 | if (c_ != Null<Real>()) |
62 | 0 | cIsFixed_ = cIsFixed; |
63 | 0 | else c_ = 0.54; |
64 | 0 | if (d_ != Null<Real>()) |
65 | 0 | dIsFixed_ = dIsFixed; |
66 | 0 | else d_ = 0.17; |
67 | |
|
68 | 0 | AbcdMathFunction::validate(a, b, c, d); |
69 | 0 | } |
70 | 0 | virtual ~AbcdCoeffHolder() = default; |
71 | | Real a_, b_, c_, d_; |
72 | | bool aIsFixed_ = false, bIsFixed_ = false, cIsFixed_ = false, dIsFixed_ = false; |
73 | | std::vector<Real> k_; |
74 | | Real error_, maxError_; |
75 | | EndCriteria::Type abcdEndCriteria_ = EndCriteria::None; |
76 | | }; |
77 | | |
78 | | template <class I1, class I2> |
79 | | class AbcdInterpolationImpl final : public Interpolation::templateImpl<I1,I2>, |
80 | | public AbcdCoeffHolder { |
81 | | public: |
82 | | AbcdInterpolationImpl(const I1& xBegin, |
83 | | const I1& xEnd, |
84 | | const I2& yBegin, |
85 | | Real a, |
86 | | Real b, |
87 | | Real c, |
88 | | Real d, |
89 | | bool aIsFixed, |
90 | | bool bIsFixed, |
91 | | bool cIsFixed, |
92 | | bool dIsFixed, |
93 | | bool vegaWeighted, |
94 | | ext::shared_ptr<EndCriteria> endCriteria, |
95 | | ext::shared_ptr<OptimizationMethod> optMethod) |
96 | 0 | : Interpolation::templateImpl<I1, I2>(xBegin, xEnd, yBegin), |
97 | 0 | AbcdCoeffHolder(a, b, c, d, aIsFixed, bIsFixed, cIsFixed, dIsFixed), |
98 | 0 | endCriteria_(std::move(endCriteria)), optMethod_(std::move(optMethod)), |
99 | 0 | vegaWeighted_(vegaWeighted) {} |
100 | | |
101 | 0 | void update() override { |
102 | 0 | auto x = this->xBegin_; |
103 | 0 | auto y = this->yBegin_; |
104 | 0 | std::vector<Real> times, blackVols; |
105 | 0 | for ( ; x!=this->xEnd_; ++x, ++y) { |
106 | 0 | times.push_back(*x); |
107 | 0 | blackVols.push_back(*y); |
108 | 0 | } |
109 | 0 | abcdCalibrator_ = ext::shared_ptr<AbcdCalibration>( |
110 | 0 | new AbcdCalibration(times, blackVols, |
111 | 0 | a_, b_, c_, d_, |
112 | 0 | aIsFixed_, bIsFixed_, |
113 | 0 | cIsFixed_, dIsFixed_, |
114 | 0 | vegaWeighted_, |
115 | 0 | endCriteria_, |
116 | 0 | optMethod_)); |
117 | 0 | abcdCalibrator_->compute(); |
118 | 0 | a_ = abcdCalibrator_->a(); |
119 | 0 | b_ = abcdCalibrator_->b(); |
120 | 0 | c_ = abcdCalibrator_->c(); |
121 | 0 | d_ = abcdCalibrator_->d(); |
122 | 0 | k_ = abcdCalibrator_->k(times, blackVols); |
123 | 0 | error_ = abcdCalibrator_->error(); |
124 | 0 | maxError_ = abcdCalibrator_->maxError(); |
125 | 0 | abcdEndCriteria_ = abcdCalibrator_->endCriteria(); |
126 | 0 | } |
127 | 0 | Real value(Real x) const override { |
128 | 0 | QL_REQUIRE(x>=0.0, "time must be non negative: " << |
129 | 0 | x << " not allowed"); |
130 | 0 | return abcdCalibrator_->value(x); |
131 | 0 | } |
132 | 0 | Real primitive(Real) const override { QL_FAIL("Abcd primitive not implemented"); } |
133 | 0 | Real derivative(Real) const override { QL_FAIL("Abcd derivative not implemented"); } |
134 | 0 | Real secondDerivative(Real) const override { |
135 | 0 | QL_FAIL("Abcd secondDerivative not implemented"); |
136 | 0 | } |
137 | | Real k(Time t) const { |
138 | | LinearInterpolation li(this->xBegin_, this->xEnd_, this->yBegin_); |
139 | | return li(t); |
140 | | } |
141 | | |
142 | | private: |
143 | | const ext::shared_ptr<EndCriteria> endCriteria_; |
144 | | const ext::shared_ptr<OptimizationMethod> optMethod_; |
145 | | bool vegaWeighted_; |
146 | | ext::shared_ptr<AbcdCalibration> abcdCalibrator_; |
147 | | |
148 | | }; |
149 | | |
150 | | } |
151 | | |
152 | | //! %Abcd interpolation between discrete points. |
153 | | /*! \ingroup interpolations |
154 | | \warning See the Interpolation class for information about the |
155 | | required lifetime of the underlying data. |
156 | | */ |
157 | | class AbcdInterpolation : public Interpolation { |
158 | | public: |
159 | | /*! Constructor */ |
160 | | template <class I1, class I2> |
161 | | AbcdInterpolation(const I1& xBegin, // x = times |
162 | | const I1& xEnd, |
163 | | const I2& yBegin, // y = volatilities |
164 | | Real a = -0.06, |
165 | | Real b = 0.17, |
166 | | Real c = 0.54, |
167 | | Real d = 0.17, |
168 | | bool aIsFixed = false, |
169 | | bool bIsFixed = false, |
170 | | bool cIsFixed = false, |
171 | | bool dIsFixed = false, |
172 | | bool vegaWeighted = false, |
173 | | const ext::shared_ptr<EndCriteria>& endCriteria |
174 | | = ext::shared_ptr<EndCriteria>(), |
175 | | const ext::shared_ptr<OptimizationMethod>& optMethod |
176 | 0 | = ext::shared_ptr<OptimizationMethod>()) { |
177 | |
|
178 | 0 | impl_ = ext::shared_ptr<Interpolation::Impl>(new |
179 | 0 | detail::AbcdInterpolationImpl<I1,I2>(xBegin, xEnd, yBegin, |
180 | 0 | a, b, c, d, |
181 | 0 | aIsFixed, bIsFixed, |
182 | 0 | cIsFixed, dIsFixed, |
183 | 0 | vegaWeighted, |
184 | 0 | endCriteria, |
185 | 0 | optMethod)); |
186 | 0 | impl_->update(); |
187 | 0 | } |
188 | | //! \name Inspectors |
189 | | //@{ |
190 | 0 | Real a() const { return coeffs().a_; } |
191 | 0 | Real b() const { return coeffs().b_; } |
192 | 0 | Real c() const { return coeffs().c_; } |
193 | 0 | Real d() const { return coeffs().d_; } |
194 | 0 | std::vector<Real> k() const { return coeffs().k_; } |
195 | 0 | Real rmsError() const { return coeffs().error_; } |
196 | 0 | Real maxError() const { return coeffs().maxError_; } |
197 | 0 | EndCriteria::Type endCriteria(){ return coeffs().abcdEndCriteria_; } |
198 | | template <class I1> |
199 | 0 | Real k(Time t, const I1& xBegin, const I1& xEnd) const { |
200 | 0 | LinearInterpolation li(xBegin, xEnd, (coeffs().k_).begin()); |
201 | 0 | return li(t); |
202 | 0 | } |
203 | | private: |
204 | 0 | const detail::AbcdCoeffHolder& coeffs() const { |
205 | 0 | return *dynamic_cast<detail::AbcdCoeffHolder*>(impl_.get()); |
206 | 0 | } |
207 | | }; |
208 | | |
209 | | //! %Abcd interpolation factory and traits |
210 | | /*! \ingroup interpolations */ |
211 | | class Abcd { |
212 | | public: |
213 | | Abcd(Real a, |
214 | | Real b, |
215 | | Real c, |
216 | | Real d, |
217 | | bool aIsFixed, |
218 | | bool bIsFixed, |
219 | | bool cIsFixed, |
220 | | bool dIsFixed, |
221 | | bool vegaWeighted = false, |
222 | | ext::shared_ptr<EndCriteria> endCriteria = ext::shared_ptr<EndCriteria>(), |
223 | | ext::shared_ptr<OptimizationMethod> optMethod = ext::shared_ptr<OptimizationMethod>()) |
224 | | : a_(a), b_(b), c_(c), d_(d), aIsFixed_(aIsFixed), bIsFixed_(bIsFixed), cIsFixed_(cIsFixed), |
225 | | dIsFixed_(dIsFixed), vegaWeighted_(vegaWeighted), endCriteria_(std::move(endCriteria)), |
226 | 0 | optMethod_(std::move(optMethod)) {} |
227 | | template <class I1, class I2> |
228 | | Interpolation interpolate(const I1& xBegin, const I1& xEnd, |
229 | | const I2& yBegin) const { |
230 | | return AbcdInterpolation(xBegin, xEnd, yBegin, |
231 | | a_, b_, c_, d_, |
232 | | aIsFixed_, bIsFixed_, |
233 | | cIsFixed_, dIsFixed_, |
234 | | vegaWeighted_, |
235 | | endCriteria_, optMethod_); |
236 | | } |
237 | | static const bool global = true; |
238 | | private: |
239 | | Real a_, b_, c_, d_; |
240 | | bool aIsFixed_, bIsFixed_, cIsFixed_, dIsFixed_; |
241 | | bool vegaWeighted_; |
242 | | const ext::shared_ptr<EndCriteria> endCriteria_; |
243 | | const ext::shared_ptr<OptimizationMethod> optMethod_; |
244 | | }; |
245 | | |
246 | | } |
247 | | |
248 | | #endif |