Coverage Report

Created: 2025-09-04 07:11

/src/quantlib/ql/models/volatility/garch.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) 2006 Joseph Wang
5
 Copyright (C) 2012 Liquidnet Holdings, Inc.
6
7
 This file is part of QuantLib, a free-software/open-source library
8
 for financial quantitative analysts and developers - http://quantlib.org/
9
10
 QuantLib is free software: you can redistribute it and/or modify it
11
 under the terms of the QuantLib license.  You should have received a
12
 copy of the license along with this program; if not, please email
13
 <quantlib-dev@lists.sf.net>. The license is also available online at
14
 <https://www.quantlib.org/license.shtml>.
15
16
 This program is distributed in the hope that it will be useful, but WITHOUT
17
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 FOR A PARTICULAR PURPOSE.  See the license for more details.
19
*/
20
21
/*! \file garch.hpp
22
    \brief GARCH volatility model
23
*/
24
25
#ifndef quantlib_garch_volatility_model_hpp
26
#define quantlib_garch_volatility_model_hpp
27
28
#include <ql/volatilitymodel.hpp>
29
#include <ql/math/optimization/problem.hpp>
30
#include <ql/math/optimization/constraint.hpp>
31
#include <vector>
32
33
namespace QuantLib {
34
35
    //! GARCH volatility model
36
    /*! Volatilities are assumed to be expressed on an annual basis.
37
    */
38
    class Garch11 : public VolatilityCompositor {
39
      public:
40
        typedef TimeSeries<Volatility> time_series;
41
42
        enum Mode {
43
            MomentMatchingGuess,   /*!< The initial guess is a moment
44
                                        matching estimates for
45
                                        mean(r2), acf(0), and acf(1). */
46
            GammaGuess,            /*!< The initial guess is an
47
                                        estimate of gamma based on the
48
                                        property:
49
                                        acf(i+1) = gamma*acf(i) for i > 1. */
50
            BestOfTwo,             /*!< The best of the two above modes */
51
            DoubleOptimization     /*!< Double optimization */
52
        };
53
54
        //! \name Constructors
55
        //@{
56
        Garch11(Real a, Real b, Real vl)
57
        : alpha_(a), beta_(b), gamma_(1 - a - b),
58
0
          vl_(vl), logLikelihood_(0), mode_(BestOfTwo) {}
59
60
        Garch11(const time_series& qs, Mode mode = BestOfTwo)
61
0
        : alpha_(0), beta_(0), vl_(0), logLikelihood_(0), mode_(mode) {
62
0
            calibrate(qs);
63
0
        };
64
        //@}
65
66
        //! \name Inspectors
67
        //@{
68
0
        Real alpha() const { return alpha_; }
69
0
        Real beta() const { return beta_; }
70
0
        Real omega() const { return vl_ * gamma_; }
71
0
        Real ltVol() const { return vl_; }
72
0
        Real logLikelihood() const { return logLikelihood_; }
73
0
        Mode mode() const { return mode_; }
74
        //@}
75
76
        //! \name VolatilityCompositor interface
77
        //@{
78
0
        time_series calculate(const time_series& quoteSeries) override {
79
0
            return calculate(quoteSeries, alpha(), beta(), omega());
80
0
        }
81
0
        void calibrate(const time_series& quoteSeries) override {
82
0
            const auto values = quoteSeries.values();
83
0
            calibrate(values.cbegin(), values.cend());
84
0
        }
85
        //@}
86
87
        //! \name Additional interface
88
        //@{
89
        static time_series calculate(const time_series& quoteSeries,
90
                                     Real alpha, Real beta, Real omega);
91
92
        void calibrate(const time_series& quoteSeries,
93
                       OptimizationMethod& method,
94
0
                       const EndCriteria& endCriteria) {
95
0
            const auto values = quoteSeries.values();
96
0
            calibrate(values.cbegin(), values.cend(),
97
0
                      method, endCriteria);
98
0
        }
99
100
        void calibrate(const time_series& quoteSeries,
101
                       OptimizationMethod& method,
102
                       const EndCriteria& endCriteria,
103
0
                       const Array& initialGuess) {
104
0
            const auto values = quoteSeries.values();
105
0
            calibrate(values.cbegin(), values.cend(),
106
0
                      method, endCriteria, initialGuess);
107
0
        }
108
109
        template <typename ForwardIterator>
110
0
        void calibrate(ForwardIterator begin, ForwardIterator end) {
111
0
            std::vector<Volatility> r2;
112
0
            Real mean_r2 = to_r2(begin, end, r2);
113
0
            ext::shared_ptr<Problem> p =
114
0
                calibrate_r2(mode_, r2, mean_r2, alpha_, beta_, vl_);
115
0
            gamma_ = 1 - alpha_ - beta_;
116
0
            vl_ /= gamma_;
117
0
            logLikelihood_ = p ? -p->functionValue() :
118
0
                                 -costFunction(begin, end);
119
0
        }
120
121
        template <typename ForwardIterator>
122
        void calibrate(ForwardIterator begin, ForwardIterator end,
123
                       OptimizationMethod& method,
124
0
                       EndCriteria endCriteria) {
125
0
            std::vector<Volatility> r2;
126
0
            Real mean_r2 = to_r2(begin, end, r2);
127
0
            ext::shared_ptr<Problem> p =
128
0
                calibrate_r2(mode_, r2, mean_r2, method,
129
0
                             endCriteria, alpha_, beta_, vl_);
130
0
            gamma_ = 1 - alpha_ - beta_;
131
0
            vl_ /= gamma_;
132
0
            logLikelihood_ = p ? -p->functionValue() :
133
0
                                 -costFunction(begin, end);
134
0
        }
135
136
        template <typename ForwardIterator>
137
        void calibrate(ForwardIterator begin, ForwardIterator end,
138
                       OptimizationMethod& method,
139
                       EndCriteria endCriteria,
140
0
                       const Array& initialGuess) {
141
0
            std::vector<Volatility> r2;
142
0
            to_r2(begin, end, r2);
143
0
            ext::shared_ptr<Problem> p =
144
0
                calibrate_r2(r2, method, endCriteria, initialGuess,
145
0
                             alpha_, beta_, vl_);
146
0
            gamma_ = 1 - alpha_ - beta_;
147
0
            vl_ /= gamma_;
148
0
            logLikelihood_ = p ? -p->functionValue() :
149
0
                                 -costFunction(begin, end);
150
0
        }
151
152
0
        Real forecast(Real r, Real sigma2) const {
153
0
            return gamma_* vl_ + alpha_ * r * r + beta_ * sigma2;
154
0
        }
155
156
        // a helper for calculation of r^2 and <r^2>
157
        template <typename InputIterator>
158
        static Real to_r2(InputIterator begin, InputIterator end,
159
0
                          std::vector<Volatility>& r2) {
160
0
            Real u2(0.0), mean_r2(0.0), w(1.0);
161
0
            for (; begin != end; ++begin) {
162
0
                u2 = *begin; u2 *= u2;
163
0
                mean_r2 = (1.0 - w) * mean_r2 + w * u2;
164
0
                r2.push_back(u2);
165
0
                w /= (w + 1.0);
166
0
            }
167
0
            return mean_r2;
168
0
        }
169
170
        /*! calibrates GARCH for r^2 */
171
        static ext::shared_ptr<Problem> calibrate_r2(
172
                                        Mode mode,
173
                                        const std::vector<Volatility>& r2,
174
                                        Real mean_r2,
175
                                        Real& alpha,
176
                                        Real& beta,
177
                                        Real& omega);
178
179
        /*! calibrates GARCH for r^2 with user-defined optimization
180
            method and end criteria */
181
        static ext::shared_ptr<Problem> calibrate_r2(
182
                                        Mode mode,
183
                                        const std::vector<Volatility>& r2,
184
                                        Real mean_r2,
185
                                        OptimizationMethod& method,
186
                                        const EndCriteria& endCriteria,
187
                                        Real& alpha,
188
                                        Real& beta,
189
                                        Real& omega);
190
191
        /*! calibrates GARCH for r^2 with user-defined optimization
192
            method, end criteria and initial guess */
193
        static ext::shared_ptr<Problem> calibrate_r2(
194
                                        const std::vector<Volatility>& r2,
195
                                        Real mean_r2,
196
                                        OptimizationMethod& method,
197
                                        const EndCriteria& endCriteria,
198
                                        const Array& initialGuess,
199
                                        Real& alpha,
200
                                        Real& beta,
201
                                        Real& omega);
202
203
        /*! calibrates GARCH for r^2 with user-defined optimization
204
            method, end criteria and initial guess */
205
        static ext::shared_ptr<Problem> calibrate_r2(
206
                                        const std::vector<Volatility> &r2,
207
                                        OptimizationMethod& method,
208
                                        const EndCriteria& endCriteria,
209
                                        const Array& initialGuess,
210
                                        Real& alpha,
211
                                        Real& beta,
212
                                        Real& omega);
213
214
        /*! calibrates GARCH for r^2 with user-defined optimization
215
            method, end criteria, constraints and initial guess */
216
        static ext::shared_ptr<Problem> calibrate_r2(
217
                                        const std::vector<Volatility>& r2,
218
                                        Real mean_r2,
219
                                        OptimizationMethod& method,
220
                                        Constraint& constraints,
221
                                        const EndCriteria& endCriteria,
222
                                        const Array& initialGuess,
223
                                        Real& alpha,
224
                                        Real& beta,
225
                                        Real& omega);
226
227
        static ext::shared_ptr<Problem> calibrate_r2(
228
                                        const std::vector<Volatility> &r2,
229
                                        OptimizationMethod& method,
230
                                        Constraint& constraints,
231
                                        const EndCriteria& endCriteria,
232
                                        const Array& initialGuess,
233
                                        Real& alpha,
234
                                        Real& beta,
235
                                        Real& omega);
236
237
        template<class InputIterator>
238
        static Real costFunction(InputIterator begin, InputIterator end,
239
0
                                 Real alpha, Real beta, Real omega) {
240
0
            Real retval(0.0);
241
0
            Real u2(0.0), sigma2(0.0);
242
0
            Size N = 0;
243
0
            for (; begin != end; ++begin, ++N) {
244
0
                sigma2 = omega + alpha * u2 + beta * sigma2;
245
0
                u2 = *begin; u2 *= u2;
246
0
                retval += std::log(sigma2) + u2 / sigma2;
247
0
            }
248
0
            return N > 0 ? Real(retval / (2*N)) : 0.0;
249
0
        }
250
        //@}
251
      private:
252
        Real alpha_, beta_, gamma_, vl_;
253
        Real logLikelihood_;
254
        Mode mode_;
255
256
        template<class InputIterator>
257
0
        Real costFunction(InputIterator begin, InputIterator end) const {
258
0
            return costFunction(begin, end, alpha(), beta(), omega());
259
0
        }
260
    };
261
262
}
263
264
265
#endif