1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2025 Eugene Toder
Copyright (C) 2025 Peter Caspers
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<quantlib-dev@lists.sf.net>. The license is also available online at
<https://www.quantlib.org/license.shtml>.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
/*! \file multicurve.hpp
\brief utility class to manage multi curves
*/
#ifndef quantlib_multicurve_hpp
#define quantlib_multicurve_hpp
#include <ql/handle.hpp>
#include <ql/patterns/observable.hpp>
#include <ql/termstructures/globalbootstrap.hpp>
#include <ql/termstructures/yieldtermstructure.hpp>
#include <ql/utilities/null_deleter.hpp>
namespace QuantLib {
struct MultiCurveBootstrapProvider {
virtual ~MultiCurveBootstrapProvider() = default;
virtual const MultiCurveBootstrapContributor* multiCurveBootstrapContributor() const = 0;
};
/*! MultiCurve builds a set of curves that form a dependency cycle. MultiCurve builds such a
cycle of curves by using an optimizer specified by one of its constructors. The steps to set
up the member curves of the cycle is as follows:
1. Create empty relinkable handles to a YieldTermStructure to represent each member. We call
these handles 'internal', because they are used internally in the cycle, but not outside
the cycle.
2. Construct each member curve as a shared pointer, e.g. by calling
a) make_shared<PiecewiseYieldCurve<...>>
b) make_shared<ZeroSpreadedTermStructure>
Rate helpers in a) or the base curve in b) underlying the spreaded curve should use the
internal handles from 1. Curves using a bootstrapper as in a) must use a compatible
boostrap class like GlobalBootstrap.
3. Construct a MultiCurve instance. This must be a shared pointer.
4. Add the cycle members to the MultiCurve instance using addBootstrappedCurve() for curves
using a bootstrapper, as e.g. in a), resp. addNonBootstrappedCurve() for all other
curves, as e.g. in b).
Both methods take the internal handle of the curve from 1. and the shared pointer from 2
as an argument. The latter has to be moved into the function and can not be used
afterwards.
Both functions return an external handle to the curve which should be used to reference
the curve for all other purposes than the internal handle in 2.
The internal handle is linked to the relevant curve, but the ownership and observability
is removed to avoid cycles of shared pointers and notification cyclces.
The external handles are constructed with ownership information shared with the
MultiCurve instance, which ensures that all member curves are kept alive until none of
the curves and the MultiCurve instance itself is referenced by any alive object.
See the piecewise yield curve unit tests for examples. */
class MultiCurve : public Observer
#ifndef QL_ENABLE_THREAD_SAFE_OBSERVER_PATTERN
,
public ext::enable_shared_from_this<MultiCurve>
#endif
{
public:
explicit MultiCurve(Real accuracy);
explicit MultiCurve(const ext::shared_ptr<OptimizationMethod>& optimizer = nullptr,
const ext::shared_ptr<EndCriteria>& endCriteria = nullptr);
Handle<YieldTermStructure>
addBootstrappedCurve(RelinkableHandle<YieldTermStructure>& internalHandle,
ext::shared_ptr<YieldTermStructure>&& curve);
Handle<YieldTermStructure>
addNonBootstrappedCurve(RelinkableHandle<YieldTermStructure>& internalHandle,
ext::shared_ptr<YieldTermStructure>&& curve);
private:
Handle<YieldTermStructure> addCurve(RelinkableHandle<YieldTermStructure>& internalHandle,
ext::shared_ptr<YieldTermStructure>&& curve);
void update() override;
ext::shared_ptr<MultiCurveBootstrap> multiCurveBootstrap_;
std::vector<ext::shared_ptr<YieldTermStructure>> curves_;
};
}
#endif
|