Coverage Report

Created: 2026-09-28 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/math/interpolations/abcdinterpolation.hpp
Line
Count
Source
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
 <https://www.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 : public Interpolation::Impl {
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
0
              error_(Null<Real>()), maxError_(Null<Real>()) {
54
0
                if (a_ != Null<Real>())
55
0
                    aIsFixed_ = aIsFixed;
56
0
                else a_ = -0.06;
57
0
                if (b_ != Null<Real>())
58
0
                    bIsFixed_ = bIsFixed;
59
0
                else b_ = 0.17;
60
0
                if (c_ != Null<Real>())
61
0
                    cIsFixed_ = cIsFixed;
62
0
                else c_ = 0.54;
63
0
                if (d_ != Null<Real>())
64
0
                    dIsFixed_ = dIsFixed;
65
0
                else d_ = 0.17;
66
67
0
                AbcdMathFunction::validate(a, b, c, d);
68
0
            }
69
70
            Real a_, b_, c_, d_;
71
            bool aIsFixed_ = false, bIsFixed_ = false, cIsFixed_ = false, dIsFixed_ = false;
72
            std::vector<Real> k_;
73
            Real error_, maxError_;
74
            EndCriteria::Type abcdEndCriteria_ = EndCriteria::None;
75
        };
76
77
        template <class I1, class I2>
78
        class AbcdInterpolationImpl final
79
            : public Interpolation::templateImpl<I1, I2, AbcdCoeffHolder> {
80
          public:
81
            AbcdInterpolationImpl(const I1& xBegin,
82
                                  const I1& xEnd,
83
                                  const I2& yBegin,
84
                                  Real a,
85
                                  Real b,
86
                                  Real c,
87
                                  Real d,
88
                                  bool aIsFixed,
89
                                  bool bIsFixed,
90
                                  bool cIsFixed,
91
                                  bool dIsFixed,
92
                                  bool vegaWeighted,
93
                                  ext::shared_ptr<EndCriteria> endCriteria,
94
                                  ext::shared_ptr<OptimizationMethod> optMethod)
95
0
            : Interpolation::templateImpl<I1, I2, AbcdCoeffHolder>(
96
0
                xBegin, xEnd, yBegin, 2, a, b, c, d, aIsFixed, bIsFixed, cIsFixed, dIsFixed),
97
0
              endCriteria_(std::move(endCriteria)), optMethod_(std::move(optMethod)),
98
0
              vegaWeighted_(vegaWeighted) {}
99
100
0
            void update() override {
101
0
                auto x = this->xBegin_;
102
0
                auto y = this->yBegin_;
103
0
                std::vector<Real> times, blackVols;
104
0
                for ( ; x!=this->xEnd_; ++x, ++y) {
105
0
                    times.push_back(*x);
106
0
                    blackVols.push_back(*y);
107
0
                }
108
0
                abcdCalibrator_ = ext::shared_ptr<AbcdCalibration>(
109
0
                    new AbcdCalibration(times, blackVols,
110
0
                                        this->a_, this->b_, this->c_, this->d_,
111
0
                                        this->aIsFixed_, this->bIsFixed_,
112
0
                                        this->cIsFixed_, this->dIsFixed_,
113
0
                                        vegaWeighted_,
114
0
                                        endCriteria_,
115
0
                                        optMethod_));
116
0
                abcdCalibrator_->compute();
117
0
                this->a_ = abcdCalibrator_->a();
118
0
                this->b_ = abcdCalibrator_->b();
119
0
                this->c_ = abcdCalibrator_->c();
120
0
                this->d_ = abcdCalibrator_->d();
121
0
                this->k_ = abcdCalibrator_->k(times, blackVols);
122
0
                this->error_ = abcdCalibrator_->error();
123
0
                this->maxError_ = abcdCalibrator_->maxError();
124
0
                this->abcdEndCriteria_ = abcdCalibrator_->endCriteria();
125
0
            }
126
0
            Real value(Real x) const override {
127
0
                QL_REQUIRE(x>=0.0, "time must be non negative: " <<
128
0
                                   x << " not allowed");
129
0
                return abcdCalibrator_->value(x);
130
0
            }
131
0
            Real primitive(Real) const override { QL_FAIL("Abcd primitive not implemented"); }
132
0
            Real derivative(Real) const override { QL_FAIL("Abcd derivative not implemented"); }
133
0
            Real secondDerivative(Real) const override {
134
0
                QL_FAIL("Abcd secondDerivative not implemented");
135
0
            }
136
            Real k(Time t) const {
137
                LinearInterpolation li(this->xBegin_, this->xEnd_, this->yBegin_);
138
                return li(t);
139
            }
140
141
          private:
142
            const ext::shared_ptr<EndCriteria> endCriteria_;
143
            const ext::shared_ptr<OptimizationMethod> optMethod_;
144
            bool vegaWeighted_;
145
            ext::shared_ptr<AbcdCalibration> abcdCalibrator_;
146
147
        };
148
149
    }
150
151
    //! %Abcd interpolation between discrete points.
152
    /*! \ingroup interpolations
153
        \warning See the Interpolation class for information about the
154
                 required lifetime of the underlying data.
155
    */
156
    class AbcdInterpolation : public Interpolation {
157
      public:
158
        /*! Constructor */
159
        template <class I1, class I2>
160
        AbcdInterpolation(const I1& xBegin,  // x = times
161
                          const I1& xEnd,
162
                          const I2& yBegin,  // y = volatilities
163
                          Real a = -0.06,
164
                          Real b =  0.17,
165
                          Real c =  0.54,
166
                          Real d =  0.17,
167
                          bool aIsFixed = false,
168
                          bool bIsFixed = false,
169
                          bool cIsFixed = false,
170
                          bool dIsFixed = false,
171
                          bool vegaWeighted = false,
172
                          const ext::shared_ptr<EndCriteria>& endCriteria
173
                              = ext::shared_ptr<EndCriteria>(),
174
                          const ext::shared_ptr<OptimizationMethod>& optMethod
175
                              = ext::shared_ptr<OptimizationMethod>(),
176
0
                          bool update = true) {
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
            if (update)
187
0
                impl_->update();
188
0
        }
189
        //! \name Inspectors
190
        //@{
191
0
        Real a() const { return coeffs().a_; }
192
0
        Real b() const { return coeffs().b_; }
193
0
        Real c() const { return coeffs().c_; }
194
0
        Real d() const { return coeffs().d_; }
195
0
        std::vector<Real> k() const { return coeffs().k_; }
196
0
        Real rmsError() const { return coeffs().error_; }
197
0
        Real maxError() const { return coeffs().maxError_; }
198
0
        EndCriteria::Type endCriteria(){ return coeffs().abcdEndCriteria_; }
199
        template <class I1>
200
0
        Real k(Time t, const I1& xBegin, const I1& xEnd) const {
201
0
            LinearInterpolation li(xBegin, xEnd, (coeffs().k_).begin());
202
0
            return li(t);
203
0
        }
204
      private:
205
0
        const detail::AbcdCoeffHolder& coeffs() const {
206
          // NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast)
207
0
          return *static_cast<detail::AbcdCoeffHolder*>(impl_.get());
208
0
        }
209
    };
210
211
    //! %Abcd interpolation factory and traits
212
    /*! \ingroup interpolations */
213
    class Abcd {
214
      public:
215
        Abcd(Real a,
216
             Real b,
217
             Real c,
218
             Real d,
219
             bool aIsFixed,
220
             bool bIsFixed,
221
             bool cIsFixed,
222
             bool dIsFixed,
223
             bool vegaWeighted = false,
224
             ext::shared_ptr<EndCriteria> endCriteria = ext::shared_ptr<EndCriteria>(),
225
             ext::shared_ptr<OptimizationMethod> optMethod = ext::shared_ptr<OptimizationMethod>())
226
        : a_(a), b_(b), c_(c), d_(d), aIsFixed_(aIsFixed), bIsFixed_(bIsFixed), cIsFixed_(cIsFixed),
227
          dIsFixed_(dIsFixed), vegaWeighted_(vegaWeighted), endCriteria_(std::move(endCriteria)),
228
0
          optMethod_(std::move(optMethod)) {}
229
        template <class I1, class I2>
230
        Interpolation interpolate(const I1& xBegin, const I1& xEnd,
231
                                  const I2& yBegin, bool update = true) const {
232
            return AbcdInterpolation(xBegin, xEnd, yBegin,
233
                                     a_, b_, c_, d_,
234
                                     aIsFixed_, bIsFixed_,
235
                                     cIsFixed_, dIsFixed_,
236
                                     vegaWeighted_,
237
                                     endCriteria_, optMethod_, update);
238
        }
239
        static const bool global = true;
240
        static const Size requiredPoints = 2;
241
      private:
242
        Real a_, b_, c_, d_;
243
        bool aIsFixed_, bIsFixed_, cIsFixed_, dIsFixed_;
244
        bool vegaWeighted_;
245
        const ext::shared_ptr<EndCriteria> endCriteria_;
246
        const ext::shared_ptr<OptimizationMethod> optMethod_;
247
    };
248
249
}
250
251
#endif