Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/models/model.cpp
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) 2001, 2002, 2003 Sadruddin Rejeb
5
 Copyright (C) 2013, 2015 Peter Caspers
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
 <http://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
#include <ql/math/optimization/problem.hpp>
22
#include <ql/math/optimization/projectedconstraint.hpp>
23
#include <ql/math/optimization/projection.hpp>
24
#include <ql/models/model.hpp>
25
#include <ql/utilities/null_deleter.hpp>
26
#include <utility>
27
28
using std::vector;
29
30
namespace QuantLib {
31
32
    CalibratedModel::CalibratedModel(Size nArguments)
33
0
    : arguments_(nArguments), constraint_(new PrivateConstraint(arguments_)) {}
Unexecuted instantiation: QuantLib::CalibratedModel::CalibratedModel(unsigned long)
Unexecuted instantiation: QuantLib::CalibratedModel::CalibratedModel(unsigned long)
34
35
    class CalibratedModel::CalibrationFunction : public CostFunction {
36
      public:
37
        CalibrationFunction(CalibratedModel* model,
38
                            const vector<ext::shared_ptr<CalibrationHelper> >& h,
39
                            vector<Real> weights,
40
                            const Projection& projection)
41
0
        : model_(model, null_deleter()), instruments_(h), weights_(std::move(weights)),
42
0
          projection_(projection) {}
43
44
0
        ~CalibrationFunction() override = default;
45
46
0
        Real value(const Array& params) const override {
47
0
            model_->setParams(projection_.include(params));
48
0
            Real value = 0.0;
49
0
            for (Size i=0; i<instruments_.size(); i++) {
50
0
                Real diff = instruments_[i]->calibrationError();
51
0
                value += diff*diff*weights_[i];
52
0
            }
53
0
            return std::sqrt(value);
54
0
        }
55
56
0
        Array values(const Array& params) const override {
57
0
            model_->setParams(projection_.include(params));
58
0
            Array values(instruments_.size());
59
0
            for (Size i=0; i<instruments_.size(); i++) {
60
0
                values[i] = instruments_[i]->calibrationError()
61
0
                           *std::sqrt(weights_[i]);
62
0
            }
63
0
            return values;
64
0
        }
65
66
0
        Real finiteDifferenceEpsilon() const override { return 1e-6; }
67
68
      private:
69
        ext::shared_ptr<CalibratedModel> model_;
70
        const vector<ext::shared_ptr<CalibrationHelper> >& instruments_;
71
        vector<Real> weights_;
72
        const Projection projection_;
73
    };
74
75
    void CalibratedModel::calibrate(
76
            const vector<ext::shared_ptr<CalibrationHelper> >& instruments,
77
            OptimizationMethod& method,
78
            const EndCriteria& endCriteria,
79
            const Constraint& additionalConstraint,
80
            const vector<Real>& weights,
81
0
            const vector<bool>& fixParameters) {
82
83
0
        QL_REQUIRE(!instruments.empty(), "no instruments provided");
84
85
0
        Constraint c;
86
0
        if (additionalConstraint.empty())
87
0
            c = *constraint_;
88
0
        else
89
0
            c = CompositeConstraint(*constraint_,additionalConstraint);
90
91
0
        QL_REQUIRE(weights.empty() || weights.size() == instruments.size(),
92
0
                   "mismatch between number of instruments (" <<
93
0
                   instruments.size() << ") and weights (" <<
94
0
                   weights.size() << ")");
95
0
        vector<Real> w =
96
0
            weights.empty() ? vector<Real>(instruments.size(), 1.0): weights;
97
98
0
        Array prms = params();
99
0
        QL_REQUIRE(fixParameters.empty() || fixParameters.size() == prms.size(),
100
0
                   "mismatch between number of parameters (" <<
101
0
                   prms.size() << ") and fixed-parameter specs (" <<
102
0
                   fixParameters.size() << ")");
103
0
        vector<bool> all(prms.size(), false);
104
0
        Projection proj(prms, !fixParameters.empty() ? fixParameters : all);
105
0
        CalibrationFunction f(this,instruments,w,proj);
106
0
        ProjectedConstraint pc(c,proj);
107
0
        Problem prob(f, pc, proj.project(prms));
108
0
        shortRateEndCriteria_ = method.minimize(prob, endCriteria);
109
0
        Array result(prob.currentValue());
110
0
        setParams(proj.include(result));
111
0
        problemValues_ = prob.values(result);
112
0
        functionEvaluation_ = prob.functionEvaluation();
113
114
0
        notifyObservers();
115
0
    }
116
117
    Real CalibratedModel::value(
118
                const Array& params,
119
0
                const vector<ext::shared_ptr<CalibrationHelper> >& instruments) {
120
0
        vector<Real> w = vector<Real>(instruments.size(), 1.0);
121
0
        Projection p(params);
122
0
        CalibrationFunction f(this, instruments, w, p);
123
0
        return f.value(params);
124
0
    }
125
126
0
    Array CalibratedModel::params() const {
127
0
        Size size=0;
128
0
        for (const auto& argument : arguments_)
129
0
            size += argument.size();
130
0
        Array params(size);
131
0
        for (Size i=0, k=0; i<arguments_.size(); ++i) {
132
0
            for (Size j=0; j<arguments_[i].size(); ++j, ++k)
133
0
                params[k] = arguments_[i].params()[j];
134
0
        }
135
0
        return params;
136
0
    }
137
138
0
    void CalibratedModel::setParams(const Array& params) {
139
0
        Array::const_iterator p = params.begin();
140
0
        for (auto& argument : arguments_) {
141
0
            for (Size j = 0; j < argument.size(); ++j, ++p) {
142
0
                QL_REQUIRE(p!=params.end(),"parameter array too small");
143
0
                argument.setParam(j, *p);
144
0
            }
145
0
        }
146
0
        QL_REQUIRE(p==params.end(),"parameter array too big!");
147
0
        generateArguments();
148
0
        notifyObservers();
149
0
    }
150
151
    ShortRateModel::ShortRateModel(Size nArguments)
152
0
    : CalibratedModel(nArguments) {}
153
154
}