📄 piecewiseyieldcurve.hpp
字号:
inline const std::vector<Date>& PiecewiseYieldCurve<C,I>::dates() const {
calculate();
return this->dates_;
}
template <class C, class I>
inline Date PiecewiseYieldCurve<C,I>::maxDate() const {
calculate();
return this->dates_.back();
}
template <class C, class I>
inline const std::vector<Time>& PiecewiseYieldCurve<C,I>::times() const {
calculate();
return this->times_;
}
template <class C, class I>
inline std::vector<std::pair<Date,Real> >
PiecewiseYieldCurve<C,I>::nodes() const {
calculate();
return base_curve::nodes();
}
template <class C, class I>
inline void PiecewiseYieldCurve<C,I>::update() {
base_curve::update();
LazyObject::update();
}
template <class C, class I>
inline DiscountFactor PiecewiseYieldCurve<C,I>::discountImpl(Time t)
const {
calculate();
return base_curve::discountImpl(t);
}
// template definitions
template <class C, class I>
PiecewiseYieldCurve<C,I>::PiecewiseYieldCurve(
const Date& referenceDate,
const std::vector<boost::shared_ptr<RateHelper> >& instruments,
const DayCounter& dayCounter, Real accuracy,
const I& interpolator)
: base_curve(referenceDate, dayCounter, interpolator),
instruments_(instruments), accuracy_(accuracy) {
checkInstruments();
}
template <class C, class I>
PiecewiseYieldCurve<C,I>::PiecewiseYieldCurve(
Natural settlementDays,
const Calendar& calendar,
const std::vector<boost::shared_ptr<RateHelper> >& instruments,
const DayCounter& dayCounter, Real accuracy,
const I& interpolator)
: base_curve(settlementDays, calendar, dayCounter, interpolator),
instruments_(instruments), accuracy_(accuracy) {
checkInstruments();
}
template <class C, class I>
void PiecewiseYieldCurve<C,I>::checkInstruments() {
QL_REQUIRE(!instruments_.empty(), "no instrument given");
// sort rate helpers
for (Size i=0; i<instruments_.size(); i++)
instruments_[i]->setTermStructure(this);
std::sort(instruments_.begin(),instruments_.end(),
detail::RateHelperSorter());
// check that there is no instruments with the same maturity
for (Size i=1; i<instruments_.size(); i++) {
Date m1 = instruments_[i-1]->latestDate(),
m2 = instruments_[i]->latestDate();
QL_REQUIRE(m1 != m2,
"two instruments have the same maturity ("<< m1 <<")");
}
for (Size i=0; i<instruments_.size(); i++)
registerWith(instruments_[i]);
}
template <class C, class I>
void PiecewiseYieldCurve<C,I>::performCalculations() const
{
// check that there is no instruments with invalid quote
for (Size i=0; i<instruments_.size(); i++)
QL_REQUIRE(instruments_[i]->referenceQuote()!=Null<Real>(),
"instrument with null price");
// setup vectors
Size n = instruments_.size();
for (Size i=0; i<n; i++) {
// don't try this at home!
instruments_[i]->setTermStructure(
const_cast<PiecewiseYieldCurve<C,I>*>(this));
}
this->dates_ = std::vector<Date>(n+1);
this->times_ = std::vector<Time>(n+1);
this->data_ = std::vector<Real>(n+1);
this->dates_[0] = this->referenceDate();
this->times_[0] = 0.0;
this->data_[0] = C::initialValue();
for (Size i=0; i<n; i++) {
this->dates_[i+1] = instruments_[i]->latestDate();
this->times_[i+1] = this->timeFromReference(this->dates_[i+1]);
this->data_[i+1] = this->data_[i];
}
Brent solver;
Size maxIterations = 25;
// bootstrapping loop
for (Size iteration = 0; ; iteration++) {
std::vector<Real> previousData = this->data_;
for (Size i=1; i<n+1; i++) {
if (iteration == 0) {
// extend interpolation a point at a time
if (I::global && i < 2) {
// not enough points for splines
this->interpolation_ = Linear().interpolate(
this->times_.begin(),
this->times_.begin()+i+1,
this->data_.begin());
} else {
this->interpolation_ = this->interpolator_.interpolate(
this->times_.begin(),
this->times_.begin()+i+1,
this->data_.begin());
}
}
this->interpolation_.update();
boost::shared_ptr<RateHelper> instrument = instruments_[i-1];
Real guess;
if (iteration > 0) {
// use perturbed value from previous loop
guess = 0.99*this->data_[i];
} else if (i > 1) {
// extrapolate
guess = C::guess(this,this->dates_[i]);
} else {
guess = C::initialGuess();
}
// bracket
Real min = C::minValueAfter(i, this->data_);
Real max = C::maxValueAfter(i, this->data_);
if (guess <= min || guess >= max)
guess = (min+max)/2.0;
try {
this->data_[i] =
solver.solve(ObjectiveFunction(this, instrument, i),
accuracy_, guess, min, max);
} catch (std::exception& e) {
QL_FAIL("could not bootstrap the " << io::ordinal(i) <<
" instrument, maturity " << this->dates_[i] <<
"\n error message: " << e.what());
}
}
// check exit conditions
if (!I::global)
break; // no need for convergence loop
Real improvement = 0.0;
for (Size i=1; i<n+1; i++)
improvement += std::abs(this->data_[i]-previousData[i]);
if (improvement <= n*accuracy_) // convergence reached
break;
if (iteration > maxIterations)
QL_FAIL("convergence not reached after "
<< maxIterations << " iterations");
}
}
#ifndef __DOXYGEN__
template <class C, class I>
PiecewiseYieldCurve<C,I>::ObjectiveFunction::ObjectiveFunction(
const PiecewiseYieldCurve<C,I>* curve,
const boost::shared_ptr<RateHelper>& rateHelper,
Size segment)
: curve_(curve), rateHelper_(rateHelper), segment_(segment) {}
template <class C, class I>
Real PiecewiseYieldCurve<C,I>::ObjectiveFunction::operator()(Real guess)
const {
C::updateGuess(curve_->data_, guess, segment_);
curve_->interpolation_.update();
return rateHelper_->quoteError();
}
#endif
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -