• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lballabio / QuantLib / 19830875741

01 Dec 2025 05:03PM UTC coverage: 74.35% (+0.4%) from 73.914%
19830875741

Pull #2344

github

web-flow
Merge 313f6c36a into b3612efbd
Pull Request #2344: add multicurve bootstrap

111 of 125 new or added lines in 6 files covered. (88.8%)

413 existing lines in 27 files now uncovered.

57218 of 76958 relevant lines covered (74.35%)

8791764.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.25
/ql/termstructures/globalbootstrap.cpp
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2

3
/*
4
 Copyright (C) 2019 SoftSolutions! S.r.l.
5
 Copyright (C) 2025 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/levenbergmarquardt.hpp>
22
#include <ql/termstructures/globalbootstrap.hpp>
23

24
namespace QuantLib {
25

26
MultiCurveBootstrap::MultiCurveBootstrap(Real accuracy) {
2✔
27
    optimizer_ = ext::make_shared<LevenbergMarquardt>(accuracy, accuracy, accuracy);
2✔
28
    endCriteria_ = ext::make_shared<EndCriteria>(1000, 10, accuracy, accuracy, accuracy);
2✔
29
}
2✔
30

NEW
31
MultiCurveBootstrap::MultiCurveBootstrap(ext::shared_ptr<OptimizationMethod> optimizer,
×
NEW
32
                                         ext::shared_ptr<EndCriteria> endCriteria)
×
NEW
33
: optimizer_(std::move(optimizer)), endCriteria_(std::move(endCriteria)) {
×
NEW
34
    constexpr Real accuracy = 1E-10;
×
NEW
35
    if (optimizer_ == nullptr)
×
NEW
36
        optimizer_ = ext::make_shared<LevenbergMarquardt>(accuracy, accuracy, accuracy);
×
NEW
37
    if (endCriteria_ == nullptr)
×
NEW
38
        endCriteria_ = ext::make_shared<EndCriteria>(1000, 10, accuracy, accuracy, accuracy);
×
NEW
39
}
×
40

41
void MultiCurveBootstrap::add(const MultiCurveBootstrapContributor* c) {
3✔
42
    contributors_.push_back(c);
3✔
43
    c->setParentBootstrapper(shared_from_this());
3✔
44
}
3✔
45

46
void MultiCurveBootstrap::addObserver(Observer* o) {
1✔
47
    observers_.push_back(o);
1✔
48
}
1✔
49

50
void MultiCurveBootstrap::runMultiCurveBootstrap() {
2✔
51

52
    std::vector<Size> guessSizes;
53
    std::vector<Real> globalGuess;
54

55
    for (auto const& c : contributors_) {
5✔
56
        Array guess = c->setupCostFunction();
3✔
57
        globalGuess.insert(globalGuess.end(), guess.begin(), guess.end());
3✔
58
        guessSizes.push_back(guess.size());
3✔
59
    }
60

61
    auto fn = [this, &guessSizes](const Array& x) {
1,251✔
62
        // call the contributors' cost functions' set part
63

64
        std::size_t offset = 0;
65
        for (std::size_t c = 0; c < contributors_.size(); ++c) {
475✔
66
            Array tmp(guessSizes[c]);
301✔
67
            std::copy(std::next(x.begin(), offset), std::next(x.begin(), offset + guessSizes[c]),
301✔
68
                      tmp.begin());
69
            offset += guessSizes[c];
301✔
70
            contributors_[c]->setCostFunctionArgument(tmp);
301✔
71
        }
72

73
        // update observers
74
        for(auto o: observers_)
221✔
75
            o->update();
47✔
76

77
        // collect the contributors' result
78

79
        std::vector<Array> results;
80
        for (std::size_t c = 0; c < contributors_.size(); ++c) {
475✔
81
            results.push_back(contributors_[c]->evaluateCostFunction());
602✔
82
        }
83

84
        // concatenate the contributors' values and return the concatenation as the result
85

86
        std::size_t resultSize =
87
            std::accumulate(results.begin(), results.end(), 0,
88
                            [](std::size_t len, const Array& a) { return len + a.size(); });
301✔
89

90
        Array result(resultSize);
174✔
91

92
        offset = 0;
93
        for (auto const& r : results) {
475✔
94
            std::copy(r.begin(), r.end(), std::next(result.begin(), offset));
301✔
95
            offset += r.size();
301✔
96
        }
97

98
        return result;
174✔
99
    };
174✔
100

101
    SimpleCostFunction<decltype(fn)> costFunction(fn);
102
    NoConstraint noConstraint;
103
    Problem problem(costFunction, noConstraint, Array(globalGuess.begin(), globalGuess.end()));
2✔
104
    EndCriteria::Type endType = optimizer_->minimize(problem, *endCriteria_);
2✔
105

106
    QL_REQUIRE(
2✔
107
        EndCriteria::succeeded(endType),
108
        "global bootstrap failed to minimize to required accuracy (during multi curve bootstrap): "
109
            << endType);
110

111
    // set all contributors to valid
112

113
    for (auto const& c : contributors_)
5✔
114
        c->setToValid();
3✔
115
}
2✔
116

117
} // namespace QuantLib
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc