const Real Gaussian1dModel::forwardRate(const Date &fixing, const Date &referenceDate, const Real y, boost::shared_ptr<IborIndex> iborIdx) const { QL_REQUIRE(iborIdx != NULL, "no ibor index given"); calculate(); if (fixing <= (evaluationDate_ + (enforcesTodaysHistoricFixings_ ? 0 : -1))) return iborIdx->fixing(fixing); Handle<YieldTermStructure> yts = iborIdx->forwardingTermStructure(); // might be empty, then use // model curve Date valueDate = iborIdx->valueDate(fixing); Date endDate = iborIdx->fixingCalendar().advance( valueDate, iborIdx->tenor(), iborIdx->businessDayConvention(), iborIdx->endOfMonth()); // FIXME Here we should use the calculation date calendar ? Real dcf = iborIdx->dayCounter().yearFraction(valueDate, endDate); return (zerobond(valueDate, referenceDate, y, yts) - zerobond(endDate, referenceDate, y, yts)) / (dcf * zerobond(endDate, referenceDate, y, yts)); }
const Real Gaussian1dModel::swapRate(const Date &fixing, const Period &tenor, const Date &referenceDate, const Real y, boost::shared_ptr<SwapIndex> swapIdx) const { QL_REQUIRE(swapIdx != NULL, "no swap index given"); calculate(); if (fixing <= (evaluationDate_ + (enforcesTodaysHistoricFixings_ ? 0 : -1))) return swapIdx->fixing(fixing); Handle<YieldTermStructure> ytsf = swapIdx->iborIndex()->forwardingTermStructure(); Handle<YieldTermStructure> ytsd = swapIdx->discountingTermStructure(); // either might be empty, then // use model curve Schedule sched, floatSched; boost::shared_ptr<VanillaSwap> underlying = underlyingSwap(swapIdx, fixing, tenor); sched = underlying->fixedSchedule(); boost::shared_ptr<OvernightIndexedSwapIndex> oisIdx = boost::dynamic_pointer_cast<OvernightIndexedSwapIndex>(swapIdx); if (oisIdx != NULL) { floatSched = sched; } else { floatSched = underlying->floatingSchedule(); } Real annuity = swapAnnuity(fixing, tenor, referenceDate, y, swapIdx); // should be fine for // overnightindexed swap indices as // well Rate floatleg = 0.0; if (ytsf.empty() && ytsd.empty()) { // simple 100-formula can be used // only in one curve setup floatleg = (zerobond(sched.dates().front(), referenceDate, y) - zerobond(sched.calendar().adjust( sched.dates().back(), underlying->paymentConvention()), referenceDate, y)); } else { for (Size i = 1; i < floatSched.size(); i++) { floatleg += (zerobond(floatSched[i - 1], referenceDate, y, ytsf) / zerobond(floatSched[i], referenceDate, y, ytsf) - 1.0) * zerobond( floatSched.calendar().adjust( floatSched[i], underlying->paymentConvention()), referenceDate, y, ytsd); } } return floatleg / annuity; }
const Real Gaussian1dModel::swapAnnuity(const Date &fixing, const Period &tenor, const Date &referenceDate, const Real y, boost::shared_ptr<SwapIndex> swapIdx) const { QL_REQUIRE(swapIdx != NULL, "no swap index given"); calculate(); Handle<YieldTermStructure> ytsd = swapIdx->discountingTermStructure(); // might be empty, then use // model curve boost::shared_ptr<VanillaSwap> underlying = underlyingSwap(swapIdx, fixing, tenor); Schedule sched = underlying->fixedSchedule(); Real annuity = 0.0; for (unsigned int j = 1; j < sched.size(); j++) { annuity += zerobond(sched.calendar().adjust( sched.date(j), underlying->paymentConvention()), referenceDate, y, ytsd) * swapIdx->dayCounter().yearFraction(sched.date(j - 1), sched.date(j)); } return annuity; }
Real Qg1dLocalVolModel::zerobond(const Date &maturity, const Date &referenceDate, const Real x, const Real y, const Handle<YieldTermStructure> &yts) { return zerobond(termStructure()->timeFromReference(maturity), termStructure()->timeFromReference(referenceDate), x, y, yts); }
const Real Gsr::numeraireImpl(const Time t, const Real y, const Handle<YieldTermStructure> &yts) const { calculate(); boost::shared_ptr<GsrProcess> p = boost::dynamic_pointer_cast<GsrProcess>(stateProcess_); if (t == 0) return yts.empty() ? this->termStructure()->discount( p->getForwardMeasureTime(), true) : yts->discount(p->getForwardMeasureTime()); return zerobond(p->getForwardMeasureTime(), t, y, yts); }
void Qg1dLocalVolModel::swapRate_d0_d1_d2( const Real T0, const Real t, const std::vector<Real> &fixedTimes, const std::vector<Real> &taus, const Real x, const Real y, const Handle<YieldTermStructure> &yts, Real &result_d0, Real &result_d1, Real &result_d2, const bool compute_d0, const bool compute_d1, const bool compute_d2) const { Real a = 0.0, sum = 0.0, sum2 = 0.0; for (Size i = 0; i < fixedTimes.size(); ++i) { Real tmp = taus[i] * zerobond(fixedTimes[i], t, x, y, yts); a += tmp; if (compute_d1 || compute_d2) { Real g = G(t, fixedTimes[i]); sum += tmp * g; if (compute_d2) sum2 += tmp * g * g; } } Real Tn = fixedTimes.back(); Real z0 = zerobond(T0, t, x, y, yts); Real zn = zerobond(Tn, t, x, y, yts); Real g0 = 0.0, gn = 0.0; // avoid maybe-uninitialized warnings if (compute_d2 || compute_d1) { g0 = G(t, T0); gn = G(t, Tn); } if (compute_d0 || compute_d2) result_d0 = (z0 - zn) / a; if (compute_d1 || compute_d2) result_d1 = (-g0 * z0 + gn * zn) / a + (z0 - zn) / (a * a) * sum; if (compute_d2) result_d2 = ((g0 * g0 * z0 - gn * gn * zn) * a + (gn * zn - g0 * z0) * sum + (result_d1 * sum - result_d0 * sum2) * a + result_d0 * sum * sum) / (a * a); }
const Real Gaussian1dModel::zerobondOption( const Option::Type &type, const Date &expiry, const Date &valueDate, const Date &maturity, const Rate strike, const Date &referenceDate, const Real y, const Handle<YieldTermStructure> &yts, const Real yStdDevs, const Size yGridPoints, const bool extrapolatePayoff, const bool flatPayoffExtrapolation) const { calculate(); Time fixingTime = termStructure()->timeFromReference(expiry); Time referenceTime = referenceDate == Null<Date>() ? 0.0 : termStructure()->timeFromReference(referenceDate); Array yg = yGrid(yStdDevs, yGridPoints, fixingTime, referenceTime, y); Array z = yGrid(yStdDevs, yGridPoints); Array p(yg.size()); for (Size i = 0; i < yg.size(); i++) { Real expValDsc = zerobond(valueDate, expiry, yg[i], yts); Real discount = zerobond(maturity, expiry, yg[i], yts) / expValDsc; p[i] = std::max((type == Option::Call ? 1.0 : -1.0) * (discount - strike), 0.0) / numeraire(fixingTime, yg[i], yts) * expValDsc; } CubicInterpolation payoff( z.begin(), z.end(), p.begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); Real price = 0.0; for (Size i = 0; i < z.size() - 1; i++) { price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[i], payoff.bCoefficients()[i], payoff.aCoefficients()[i], p[i], z[i], z[i], z[i + 1]); } if (extrapolatePayoff) { if (flatPayoffExtrapolation) { price += gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0); price += gaussianShiftedPolynomialIntegral(0.0, 0.0, 0.0, 0.0, p[0], z[0], -100.0, z[0]); } else { if (type == Option::Call) price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[z.size() - 2], payoff.bCoefficients()[z.size() - 2], payoff.aCoefficients()[z.size() - 2], p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0); if (type == Option::Put) price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[0], payoff.bCoefficients()[0], payoff.aCoefficients()[0], p[0], z[0], -100.0, z[0]); } } return numeraire(referenceTime, y, yts) * price; }