Coverage Report

Created: 2025-08-11 06:28

/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