24#ifndef quantlib_global_bootstrap_hpp
25#define quantlib_global_bootstrap_hpp
75 typedef typename Curve::traits_type
Traits;
77 typedef std::function<
Array(
const std::vector<Time>&,
const std::vector<Real>&)>
82 ext::shared_ptr<OptimizationMethod> optimizer =
nullptr,
83 ext::shared_ptr<EndCriteria> endCriteria =
nullptr);
84 GlobalBootstrap(std::vector<ext::shared_ptr<typename Traits::helper> > additionalHelpers,
85 std::function<std::vector<Date>()> additionalDates,
88 ext::shared_ptr<OptimizationMethod> optimizer =
nullptr,
89 ext::shared_ptr<EndCriteria> endCriteria =
nullptr,
90 ext::shared_ptr<AdditionalBootstrapVariables> additionalVariables =
nullptr);
91 GlobalBootstrap(std::vector<ext::shared_ptr<typename Traits::helper> > additionalHelpers,
92 std::function<std::vector<Date>()> additionalDates,
93 std::function<
Array()> additionalPenalties,
95 ext::shared_ptr<OptimizationMethod> optimizer =
nullptr,
96 ext::shared_ptr<EndCriteria> endCriteria =
nullptr,
97 ext::shared_ptr<AdditionalBootstrapVariables> additionalVariables =
nullptr);
98 void setup(Curve *ts);
118template <
class Curve>
121 ext::shared_ptr<OptimizationMethod> optimizer,
122 ext::shared_ptr<EndCriteria> endCriteria)
123: ts_(nullptr), accuracy_(accuracy), optimizer_(
std::move(optimizer)),
124 endCriteria_(
std::move(endCriteria)) {}
126template <
class Curve>
128 std::vector<ext::shared_ptr<typename Traits::helper> > additionalHelpers,
129 std::function<std::vector<Date>()> additionalDates,
132 ext::shared_ptr<OptimizationMethod> optimizer,
133 ext::shared_ptr<EndCriteria> endCriteria,
134 ext::shared_ptr<AdditionalBootstrapVariables> additionalVariables)
135: ts_(nullptr), accuracy_(accuracy), optimizer_(
std::move(optimizer)),
136 endCriteria_(
std::move(endCriteria)), additionalHelpers_(
std::move(additionalHelpers)),
137 additionalDates_(
std::move(additionalDates)), additionalPenalties_(
std::move(additionalPenalties)),
138 additionalVariables_(
std::move(additionalVariables)) {}
140template <
class Curve>
142 std::vector<ext::shared_ptr<typename Traits::helper> > additionalHelpers,
143 std::function<std::vector<Date>()> additionalDates,
144 std::function<
Array()> additionalPenalties,
146 ext::shared_ptr<OptimizationMethod> optimizer,
147 ext::shared_ptr<EndCriteria> endCriteria,
148 ext::shared_ptr<AdditionalBootstrapVariables> additionalVariables)
151 ? [
f=
std::move(additionalPenalties)](const
std::vector<
Time>&, const
std::vector<
Real>&) {
154 : AdditionalPenalties(),
155 accuracy, std::move(optimizer), std::move(endCriteria),
156 std::move(additionalVariables)) {}
160 for (
Size j = 0; j < ts_->instruments_.size(); ++j)
161 ts_->registerWithObservables(ts_->instruments_[j]);
162 for (
Size j = 0; j < additionalHelpers_.size(); ++j)
163 ts_->registerWithObservables(additionalHelpers_[j]);
166 Real accuracy = accuracy_ !=
Null<Real>() ? accuracy_ : ts_->accuracy_;
168 optimizer_ = ext::make_shared<LevenbergMarquardt>(accuracy, accuracy, accuracy);
171 endCriteria_ = ext::make_shared<EndCriteria>(1000, 10, accuracy, accuracy, accuracy);
185 const Date firstDate = Traits::initialDate(ts_);
188 if (!ts_->instruments_.empty()) {
189 while (firstHelper_ < ts_->instruments_.size() && ts_->instruments_[firstHelper_]->pillarDate() <= firstDate)
192 numberHelpers_ = ts_->instruments_.size() - firstHelper_;
195 firstAdditionalHelper_ = 0;
196 if (!additionalHelpers_.empty()) {
197 while (firstAdditionalHelper_ < additionalHelpers_.size() &&
198 additionalHelpers_[firstAdditionalHelper_]->pillarDate() <= firstDate)
199 ++firstAdditionalHelper_;
201 numberAdditionalHelpers_ = additionalHelpers_.size() - firstAdditionalHelper_;
204 std::vector<Date> additionalDates;
205 if (additionalDates_)
206 additionalDates = additionalDates_();
207 if (!additionalDates.empty()) {
208 additionalDates.erase(
209 std::remove_if(additionalDates.begin(), additionalDates.end(),
210 [=](
const Date& date) { return date <= firstDate; }),
211 additionalDates.end()
214 const Size numberAdditionalDates = additionalDates.size();
216 QL_REQUIRE(numberHelpers_ + numberAdditionalDates >= Interpolator::requiredPoints - 1,
217 "not enough alive instruments (" << numberHelpers_ <<
") + additional dates (" << numberAdditionalDates
218 <<
") = " << numberHelpers_ + numberAdditionalDates <<
" provided, "
219 << Interpolator::requiredPoints - 1 <<
" required");
222 std::vector<Date> &dates = ts_->dates_;
223 std::vector<Time> × = ts_->times_;
227 dates.push_back(firstDate);
228 for (
Size j = 0; j < numberHelpers_; ++j)
229 dates.push_back(ts_->instruments_[firstHelper_ + j]->pillarDate());
230 dates.insert(dates.end(), additionalDates.begin(), additionalDates.end());
231 std::sort(dates.begin(), dates.end());
232 auto it = std::unique(dates.begin(), dates.end());
233 QL_REQUIRE(it == dates.end(),
"duplicate dates among alive instruments and additional dates");
237 for (
auto& date : dates)
238 times.push_back(ts_->timeFromReference(date));
241 Date maxDate = dates.back();
242 for (
Size j = 0; j < numberHelpers_; ++j) {
243 maxDate = std::max(ts_->instruments_[firstHelper_ + j]->latestRelevantDate(), maxDate);
245 ts_->maxDate_ = maxDate;
248 if (!validCurve_ || ts_->data_.size() != dates.size()) {
252 ts_->data_ = std::vector<Real>(dates.size(), Traits::initialValue(ts_));
265 if (!initialized_ || ts_->moving_)
269 for (
Size j = 0; j < numberHelpers_; ++j) {
270 const ext::shared_ptr<typename Traits::helper> &helper = ts_->instruments_[firstHelper_ + j];
273 <<
" instrument (maturity: " << helper->maturityDate()
274 <<
", pillar: " << helper->pillarDate() <<
") has an invalid quote");
278 helper->setTermStructure(
const_cast<Curve *
>(ts_));
282 for (
Size j = 0; j < numberAdditionalHelpers_; ++j) {
283 const ext::shared_ptr<typename Traits::helper> &helper = additionalHelpers_[firstAdditionalHelper_ + j];
285 <<
" additional instrument (maturity: " << helper->maturityDate()
286 <<
") has an invalid quote");
287 helper->setTermStructure(
const_cast<Curve *
>(ts_));
292 ts_->interpolation_ =
293 ts_->interpolator_.interpolate(ts_->times_.begin(), ts_->times_.end(), ts_->data_.begin());
298 const Size numberPillars = ts_->times_.size() - 1;
299 Array additionalGuesses;
300 if (additionalVariables_) {
301 additionalGuesses = additionalVariables_->initialize(validCurve_);
303 Array guess(numberPillars + additionalGuesses.
size());
304 for (
Size i = 0; i < numberPillars; ++i) {
307 Traits::updateGuess(ts_->data_, Traits::guess(i + 1, ts_, validCurve_, 0), i + 1);
308 guess[i] = Traits::transformInverse(ts_->data_[i + 1], i + 1, ts_);
310 std::copy(additionalGuesses.
begin(), additionalGuesses.
end(), guess.
begin() + numberPillars);
316 for (
Size i = 0; i < numberPillars; ++i) {
317 Traits::updateGuess(ts_->data_, Traits::transformDirect(x[i], i + 1, ts_), i + 1);
319 ts_->interpolation_.update();
320 if (additionalVariables_) {
321 additionalVariables_->update(
Array(x.
begin() + numberPillars, x.
end()));
324 Array additionalErrors;
325 if (additionalPenalties_) {
326 additionalErrors = additionalPenalties_(ts_->times_, ts_->data_);
328 Array result(numberHelpers_ + additionalErrors.
size());
329 std::transform(ts_->instruments_.begin() + firstHelper_, ts_->instruments_.end(),
331 [](
const auto& helper) { return helper->quoteError(); });
332 std::copy(additionalErrors.
begin(), additionalErrors.
end(),
333 result.
begin() + numberHelpers_);
339 Problem problem(cost, noConstraint, guess);
346 "global bootstrap failed to minimize to required accuracy: " << endType);
base helper class used for bootstrapping
virtual Array initialize(bool validData)=0
virtual ~AdditionalBootstrapVariables()=default
virtual void update(const Array &x)=0
1-D array used in linear algebra.
const_iterator end() const
Size size() const
dimension of the array
const_iterator begin() const
static bool succeeded(EndCriteria::Type ecType)
ext::shared_ptr< EndCriteria > endCriteria_
GlobalBootstrap(Real accuracy=Null< Real >(), ext::shared_ptr< OptimizationMethod > optimizer=nullptr, ext::shared_ptr< EndCriteria > endCriteria=nullptr)
Size numberAdditionalHelpers_
std::function< std::vector< Date >()> additionalDates_
ext::shared_ptr< AdditionalBootstrapVariables > additionalVariables_
Curve::interpolator_type Interpolator
ext::shared_ptr< OptimizationMethod > optimizer_
std::function< Array(const std::vector< Time > &, const std::vector< Real > &)> AdditionalPenalties
Curve::traits_type Traits
AdditionalPenalties additionalPenalties_
Size firstAdditionalHelper_
std::vector< ext::shared_ptr< typename Traits::helper > > additionalHelpers_
template class providing a null value for a given type.
Constrained optimization problem.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Maps function, bind and cref to either the boost or std implementation.
detail::ordinal_holder ordinal(Size)
outputs naturals as 1st, 2nd, 3rd...
Real Time
continuous quantity with 1-year units
std::size_t Size
size of a container
Levenberg-Marquardt optimization method.
linear interpolation between discrete points