207 {
208
209
210
211
212
213
216
217
219 const QuantLib::ext::shared_ptr<typename Traits::helper>&
helper =
ts_->instruments_[j];
220
221
222 QL_REQUIRE(
helper->quote()->isValid(), QuantLib::io::ordinal(j + 1)
223 <<
" instrument (maturity: " <<
helper->maturityDate()
224 <<
", pillar: " <<
helper->pillarDate() <<
") has an invalid quote");
225
226
227
228
229 helper->setTermStructure(
const_cast<Curve*
>(
ts_));
230 }
231
232 const std::vector<QuantLib::Time>& times =
ts_->times_;
233 const std::vector<QuantLib::Real>& data =
ts_->data_;
234 QuantLib::Real accuracy =
accuracy_ != QuantLib::Null<QuantLib::Real>() ?
accuracy_ :
ts_->accuracy_;
236
237 QuantLib::Size maxIterations = Traits::maxIterations() - 1;
238
239
241
242 for (QuantLib::Size iteration = 0;; ++iteration) {
244
245 std::vector<QuantLib::Real> minValues(
alive_, QuantLib::Null<QuantLib::Real>());
246 std::vector<QuantLib::Real> maxValues(
alive_, QuantLib::Null<QuantLib::Real>());
247 std::vector<QuantLib::Size> attempts(
alive_, 1);
248
249 for (QuantLib::Size i = 1; i <=
alive_; ++i) {
250
251
252 if (minValues[i - 1] == QuantLib::Null<QuantLib::Real>()) {
254 } else {
255 minValues[i - 1] =
257 }
258 if (maxValues[i - 1] == QuantLib::Null<QuantLib::Real>()) {
260 } else {
261 maxValues[i - 1] =
263 }
265
266
267 if (guess >= maxValues[i - 1])
268 guess = maxValues[i - 1] - (maxValues[i - 1] - minValues[i - 1]) / 5.0;
269 else if (guess <= minValues[i - 1])
270 guess = minValues[i - 1] + (maxValues[i - 1] - minValues[i - 1]) / 5.0;
271
272
273 if (!validData) {
274 try {
275
276 ts_->interpolation_ =
277 ts_->interpolator_.interpolate(times.begin(), times.begin() + i + 1, data.begin());
278 } catch (...) {
279 if (!Interpolator::global)
280 throw;
281
282
283
284 ts_->interpolation_ =
285 QuantLib::Linear().interpolate(times.begin(), times.begin() + i + 1, data.begin());
286 }
287 ts_->interpolation_.update();
288 }
289
290 try {
291 if (validData)
292 solver_.solve(*
errors_[i], accuracy, guess, minValues[i - 1], maxValues[i - 1]);
293 else
295 } catch (std::exception& e) {
297
298
299
300
301
302
305 return;
306 }
307
308
309
311 attempts[i - 1]++;
312 i--;
313 continue;
314 }
315
317
320
321
322
323 ts_->interpolation_.update();
324 } else {
325 QL_FAIL(QuantLib::io::ordinal(iteration + 1)
326 << " iteration: failed "
327 "at "
328 << QuantLib::io::ordinal(i)
329 << " alive instrument, "
330 "pillar "
332 <<
errors_[i]->
helper()->maturityDate() <<
", reference date " <<
ts_->dates_[0] <<
": "
333 << e.what());
334 }
335 }
336 }
337
339 break;
340
341
342 QuantLib::Real change = std::fabs(data[1] -
previousData_[1]);
343 for (QuantLib::Size i = 2; i <=
alive_; ++i)
344 change = std::max(change, std::fabs(data[i] -
previousData_[i]));
345
346 if (change <= globalAccuracy || change <= accuracy)
347 break;
348
349
350 if (iteration == maxIterations) {
352 break;
353 } else {
354 QL_FAIL("convergence not reached after " << iteration << " iterations; last improvement " << change
355 << ", required accuracy "
356 << std::max(globalAccuracy, accuracy));
357 }
358 }
359
360 validData = true;
361 }
362
364}
QuantLib::Brent firstSolver_
QuantLib::FiniteDifferenceNewtonSafe solver_
std::vector< QuantLib::Real > previousData_
std::vector< QuantLib::ext::shared_ptr< QuantLib::BootstrapError< Curve > > > errors_
QuantLib::Real dontThrowFallback(const QuantLib::BootstrapError< Curve > &error, QuantLib::Real xMin, QuantLib::Real xMax, QuantLib::Size steps)
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper