OvernightIndexedCoupon::OvernightIndexedCoupon( const Date& paymentDate, Real nominal, const Date& startDate, const Date& endDate, const shared_ptr<OvernightIndex>& overnightIndex, Real gearing, Spread spread, const Date& refPeriodStart, const Date& refPeriodEnd, const DayCounter& dayCounter) : FloatingRateCoupon(paymentDate, nominal, startDate, endDate, overnightIndex->fixingDays(), overnightIndex, gearing, spread, refPeriodStart, refPeriodEnd, dayCounter, false) { // value dates Schedule sch = MakeSchedule() .from(startDate) .to(endDate) .withTenor(1*Days) .withCalendar(overnightIndex->fixingCalendar()) .withConvention(overnightIndex->businessDayConvention()) .backwards(); valueDates_ = sch.dates(); QL_ENSURE(valueDates_.size()>=2, "degenerate schedule"); // fixing dates n_ = valueDates_.size()-1; if (overnightIndex->fixingDays()==0) { fixingDates_ = vector<Date>(valueDates_.begin(), valueDates_.end()-1); } else { fixingDates_.resize(n_); for (Size i=0; i<n_; ++i) fixingDates_[i] = overnightIndex->fixingDate(valueDates_[i]); } // accrual (compounding) periods dt_.resize(n_); const DayCounter& dc = overnightIndex->dayCounter(); for (Size i=0; i<n_; ++i) dt_[i] = dc.yearFraction(valueDates_[i], valueDates_[i+1]); setPricer(shared_ptr<FloatingRateCouponPricer>(new OvernightIndexedCouponPricer)); }
SyntheticCDO::SyntheticCDO (const boost::shared_ptr<Basket> basket, Protection::Side side, const Schedule& schedule, Rate upfrontRate, Rate runningRate, const DayCounter& dayCounter, BusinessDayConvention paymentConvention, const Handle<YieldTermStructure>& yieldTS) : basket_(basket), side_(side), schedule_(schedule), upfrontRate_(upfrontRate), runningRate_(runningRate), dayCounter_(dayCounter), paymentConvention_(paymentConvention), yieldTS_(yieldTS) { QL_REQUIRE (basket->names().size() > 0, "basket is empty"); registerWith (yieldTS_); const boost::shared_ptr<Pool> pool = basket->pool(); Date today = Settings::instance().evaluationDate(); // register with probabilities if the corresponding issuer is // alive under this name contractual conditions for (Size i = 0; i < basket->names().size(); i++) { if(!pool->get(basket->names()[i]). defaultedBetween(schedule.dates()[0], today, basket->defaultKeys()[i])) registerWith(pool->get(basket->names()[i]). defaultProbability(basket->defaultKeys()[i])); // To do: the basket could do this last line on its own without so much // travelling, update its interface? some RR models depend on the // probabilities and they will be registered with them. Strictly // speaking the basket does not need directly to be registered // with the probs. /* we used to be registering with Issuers which are not observables. However this might be what we want: Issuer registration might give us registration with probabilities and with creditEvents at the same time. */ } // register with recoveries: registerWith(basket_); }
CallableBond::CallableBond(Natural settlementDays, const Schedule& schedule, const DayCounter& paymentDayCounter, const Date& issueDate, const CallabilitySchedule& putCallSchedule) : Bond(settlementDays, schedule.calendar(), issueDate), paymentDayCounter_(paymentDayCounter), putCallSchedule_(putCallSchedule) { maturityDate_ = schedule.dates().back(); if (!putCallSchedule_.empty()) { Date finalOptionDate = Date::minDate(); for (Size i=0; i<putCallSchedule_.size();++i) { finalOptionDate=std::max(finalOptionDate, putCallSchedule_[i]->date()); } QL_REQUIRE(finalOptionDate <= maturityDate_ , "Bond cannot mature before last call/put date"); } // derived classes must set cashflows_ and frequency_ }
void LgmSwaptionEngineAD::calculate() const { // collect data needed for core computation routine QL_REQUIRE(arguments_.settlementType == Settlement::Physical, "cash-settled swaptions not yet implemented ..."); Date settlement = model_->termStructure()->referenceDate(); if (arguments_.exercise->dates().back() <= settlement) { // swaption is expired, possibly generated swap is not // valued results_.value = 0.0; return; } int idxMax = static_cast<int>(arguments_.exercise->dates().size()) - 1; int minIdxAlive = static_cast<int>( std::upper_bound(arguments_.exercise->dates().begin(), arguments_.exercise->dates().end(), settlement) - arguments_.exercise->dates().begin()); VanillaSwap swap = *arguments_.swap; int callput = arguments_.type == VanillaSwap::Payer ? 1 : -1; Schedule fixedSchedule = swap.fixedSchedule(); Schedule floatSchedule = swap.floatingSchedule(); Date expiry0; std::vector<int> fix_startidxes, float_startidxes; std::vector<Date> expiryDates; for (int idx = minIdxAlive; idx <= idxMax; ++idx) { expiry0 = arguments_.exercise->dates()[idx]; expiryDates.push_back(expiry0); Size j1 = std::upper_bound(fixedSchedule.dates().begin(), fixedSchedule.dates().end(), expiry0 - 1) - fixedSchedule.dates().begin(); Size k1 = std::upper_bound(floatSchedule.dates().begin(), floatSchedule.dates().end(), expiry0 - 1) - floatSchedule.dates().begin(); fix_startidxes.push_back(j1); float_startidxes.push_back(k1); } std::vector<double> float_mults, index_acctimes, float_spreads, fix_cpn; std::vector<Date> floatt1Dates, floatt2Dates, floattpDates; std::vector<Date> fixtpDates; for (Size i = 0; i < arguments_.floatingFixingDates.size(); ++i) { float_mults.push_back(arguments_.nominal * arguments_.floatingAccrualTimes[i]); float_spreads.push_back(arguments_.floatingSpreads[i]); boost::shared_ptr<IborIndex> index = arguments_.swap->iborIndex(); Date d1 = index->valueDate(arguments_.floatingFixingDates[i]); Date d2 = index->maturityDate(d1); double acctime = index->dayCounter().yearFraction(d1, d2, d1, d2); floatt1Dates.push_back(d1); floatt2Dates.push_back(d2); floattpDates.push_back(arguments_.floatingPayDates[i]); index_acctimes.push_back(acctime); } for (Size i = 0; i < arguments_.fixedCoupons.size(); ++i) { fix_cpn.push_back(arguments_.fixedCoupons[i]); fixtpDates.push_back(arguments_.fixedPayDates[i]); } // join all dates and fill index vectors std::vector<Date> allDates; std::vector<double> allTimes; // with settlement as first entry ! std::vector<int> expiries, floatt1s, floatt2s, floattps, fixtps; std::vector<double> modpar; allDates.reserve(expiryDates.size() + floatt1Dates.size() + floatt2Dates.size() + floattpDates.size() + fixtpDates.size()); allTimes.reserve(allDates.size()); modpar.reserve(3 * allDates.size()); allDates.push_back(settlement); allDates.insert(allDates.end(), expiryDates.begin(), expiryDates.end()); allDates.insert(allDates.end(), floatt1Dates.begin(), floatt1Dates.end()); allDates.insert(allDates.end(), floatt2Dates.begin(), floatt2Dates.end()); allDates.insert(allDates.end(), floattpDates.begin(), floattpDates.end()); allDates.insert(allDates.end(), fixtpDates.begin(), fixtpDates.end()); std::sort(allDates.begin(), allDates.end()); allDates.erase(unique(allDates.begin(), allDates.end()), allDates.end()); for (Size i = 0; i < allDates.size(); ++i) { allTimes.push_back( model_->termStructure()->timeFromReference(allDates[i])); } for (Size i = 0; i < allDates.size(); ++i) { modpar.push_back(model_->parametrization()->H(allTimes[i])); } for (Size i = 0; i < allDates.size(); ++i) { modpar.push_back(model_->parametrization()->zeta(allTimes[i])); } for (Size i = 0; i < allDates.size(); ++i) { modpar.push_back(model_->termStructure()->discount(allTimes[i])); } for (Size i = 0; i < expiryDates.size(); ++i) { expiries.push_back( std::find(allDates.begin(), allDates.end(), expiryDates[i]) - allDates.begin()); } for (Size i = 0; i < floatt1Dates.size(); ++i) { floatt1s.push_back( std::find(allDates.begin(), allDates.end(), floatt1Dates[i]) - allDates.begin()); } for (Size i = 0; i < floatt2Dates.size(); ++i) { floatt2s.push_back( std::find(allDates.begin(), allDates.end(), floatt2Dates[i]) - allDates.begin()); } for (Size i = 0; i < floattpDates.size(); ++i) { floattps.push_back( std::find(allDates.begin(), allDates.end(), floattpDates[i]) - allDates.begin()); } for (Size i = 0; i < fixtpDates.size(); ++i) { fixtps.push_back( std::find(allDates.begin(), allDates.end(), fixtpDates[i]) - allDates.begin()); } // call core computation routine and set results int ntimes = allTimes.size(); int nexpiries = expiries.size(); int nfloats = floatt1s.size(); int nfixs = fix_cpn.size(); double res = 0.0; std::vector<Real> dres(3*ntimes); int integration_pts = integrationPoints_; double std_devs = stddevs_; lgm_swaption_engine_ad_(&ntimes, &allTimes[0], &modpar[0], &nexpiries, &expiries[0], &callput, &nfloats, &float_startidxes[0], &float_mults[0], &index_acctimes[0], &float_spreads[0], &floatt1s[0], &floatt2s[0], &floattps[0], &fix_startidxes[0], &nfixs, &fix_cpn[0], &fixtps[0], &integration_pts, &std_devs, &res, &dres[0]); results_.value = res; std::vector<Real> H_sensitivity(dres.begin(),dres.begin()+ntimes); std::vector<Real> zeta_sensitivity(dres.begin()+ntimes,dres.begin()+2*ntimes); std::vector<Real> discount_sensitivity(dres.begin()+2*ntimes,dres.begin()+3*ntimes); results_.additionalResults["sensitivityTimes"] = allTimes; results_.additionalResults["sensitivityH"] = H_sensitivity; results_.additionalResults["sensitivityZeta"] = zeta_sensitivity; results_.additionalResults["sensitivityDiscount"] = discount_sensitivity; }
void Gaussian1dNonstandardSwaptionEngine::calculate() const { QL_REQUIRE(arguments_.settlementType == Settlement::Physical, "cash-settled swaptions not yet implemented ..."); Date settlement = model_->termStructure()->referenceDate(); if (arguments_.exercise->dates().back() <= settlement) { // swaption is expired, possibly generated swap is not // valued results_.value = 0.0; return; } boost::shared_ptr<RebatedExercise> rebatedExercise = boost::dynamic_pointer_cast<RebatedExercise>(arguments_.exercise); int idx = arguments_.exercise->dates().size() - 1; int minIdxAlive = static_cast<int>( std::upper_bound(arguments_.exercise->dates().begin(), arguments_.exercise->dates().end(), settlement) - arguments_.exercise->dates().begin()); NonstandardSwap swap = *arguments_.swap; Option::Type type = arguments_.type == VanillaSwap::Payer ? Option::Call : Option::Put; Schedule schedule = swap.fixedSchedule(); Schedule floatSchedule = swap.floatingSchedule(); Array npv0(2 * integrationPoints_ + 1, 0.0), npv1(2 * integrationPoints_ + 1, 0.0); Array z = model_->yGrid(stddevs_, integrationPoints_); Array p(z.size(), 0.0); // for probability computation std::vector<Array> npvp0, npvp1; if (probabilities_ != None) { for (Size i = 0; i < static_cast<Size>(idx - minIdxAlive + 2); ++i) { Array npvTmp0(2 * integrationPoints_ + 1, 0.0); Array npvTmp1(2 * integrationPoints_ + 1, 0.0); npvp0.push_back(npvTmp0); npvp1.push_back(npvTmp1); } } // end probabkility computation Date expiry1 = Null<Date>(), expiry0; Time expiry1Time = Null<Real>(), expiry0Time; do { if (idx == minIdxAlive - 1) expiry0 = settlement; else expiry0 = arguments_.exercise->dates()[idx]; expiry0Time = std::max( model_->termStructure()->timeFromReference(expiry0), 0.0); Size j1 = std::upper_bound(schedule.dates().begin(), schedule.dates().end(), expiry0 - 1) - schedule.dates().begin(); Size k1 = std::upper_bound(floatSchedule.dates().begin(), floatSchedule.dates().end(), expiry0 - 1) - floatSchedule.dates().begin(); // todo add openmp support later on (as in gaussian1dswaptionengine) for (Size k = 0; k < (expiry0 > settlement ? npv0.size() : 1); k++) { Real price = 0.0; if (expiry1Time != Null<Real>()) { Real zSpreadDf = oas_.empty() ? 1.0 : std::exp(-oas_->value() * (expiry1Time - expiry0Time)); Array yg = model_->yGrid(stddevs_, integrationPoints_, expiry1Time, expiry0Time, expiry0 > settlement ? z[k] : 0.0); CubicInterpolation payoff0( z.begin(), z.end(), npv1.begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); for (Size i = 0; i < yg.size(); i++) { p[i] = payoff0(yg[i], true); } CubicInterpolation payoff1( z.begin(), z.end(), p.begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); for (Size i = 0; i < z.size() - 1; i++) { price += model_->gaussianShiftedPolynomialIntegral( 0.0, payoff1.cCoefficients()[i], payoff1.bCoefficients()[i], payoff1.aCoefficients()[i], p[i], z[i], z[i], z[i + 1]) * zSpreadDf; } if (extrapolatePayoff_) { if (flatPayoffExtrapolation_) { price += model_->gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0) * zSpreadDf; price += model_->gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[0], z[0], -100.0, z[0]) * zSpreadDf; } else { if (type == Option::Call) price += model_->gaussianShiftedPolynomialIntegral( 0.0, payoff1.cCoefficients()[z.size() - 2], payoff1.bCoefficients()[z.size() - 2], payoff1.aCoefficients()[z.size() - 2], p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0) * zSpreadDf; if (type == Option::Put) price += model_->gaussianShiftedPolynomialIntegral( 0.0, payoff1.cCoefficients()[0], payoff1.bCoefficients()[0], payoff1.aCoefficients()[0], p[0], z[0], -100.0, z[0]) * zSpreadDf; } } } npv0[k] = price; // for probability computation if (probabilities_ != None) { for (Size m = 0; m < npvp0.size(); m++) { Real price = 0.0; if (expiry1Time != Null<Real>()) { Real zSpreadDf = oas_.empty() ? 1.0 : std::exp(-oas_->value() * (expiry1Time - expiry0Time)); Array yg = model_->yGrid( stddevs_, integrationPoints_, expiry1Time, expiry0Time, expiry0 > settlement ? z[k] : 0.0); CubicInterpolation payoff0( z.begin(), z.end(), npvp1[m].begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); for (Size i = 0; i < yg.size(); i++) { p[i] = payoff0(yg[i], true); } CubicInterpolation payoff1( z.begin(), z.end(), p.begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); for (Size i = 0; i < z.size() - 1; i++) { price += model_->gaussianShiftedPolynomialIntegral( 0.0, payoff1.cCoefficients()[i], payoff1.bCoefficients()[i], payoff1.aCoefficients()[i], p[i], z[i], z[i], z[i + 1]) * zSpreadDf; } if (extrapolatePayoff_) { if (flatPayoffExtrapolation_) { price += model_ ->gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0) * zSpreadDf; price += model_ ->gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[0], z[0], -100.0, z[0]) * zSpreadDf; } else { if (type == Option::Call) price += model_ ->gaussianShiftedPolynomialIntegral( 0.0, payoff1.cCoefficients() [z.size() - 2], payoff1.bCoefficients() [z.size() - 2], payoff1.aCoefficients() [z.size() - 2], p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0) * zSpreadDf; if (type == Option::Put) price += model_ ->gaussianShiftedPolynomialIntegral( 0.0, payoff1 .cCoefficients()[0], payoff1 .bCoefficients()[0], payoff1 .aCoefficients()[0], p[0], z[0], -100.0, z[0]) * zSpreadDf; } } } npvp0[m][k] = price; } } // end probability computation if (expiry0 > settlement) { Real floatingLegNpv = 0.0; for (Size l = k1; l < arguments_.floatingCoupons.size(); l++) { Real zSpreadDf = oas_.empty() ? 1.0 : std::exp( -oas_->value() * (model_->termStructure() ->dayCounter() .yearFraction( expiry0, arguments_ .floatingPayDates[l]))); Real amount; if (arguments_.floatingIsRedemptionFlow[l]) amount = arguments_.floatingCoupons[l]; else amount = arguments_.floatingNominal[l] * arguments_.floatingAccrualTimes[l] * (arguments_.floatingGearings[l] * model_->forwardRate( arguments_.floatingFixingDates[l], expiry0, z[k], arguments_.swap->iborIndex()) + arguments_.floatingSpreads[l]); floatingLegNpv += amount * model_->zerobond(arguments_.floatingPayDates[l], expiry0, z[k], discountCurve_) * zSpreadDf; } Real fixedLegNpv = 0.0; for (Size l = j1; l < arguments_.fixedCoupons.size(); l++) { Real zSpreadDf = oas_.empty() ? 1.0 : std::exp( -oas_->value() * (model_->termStructure() ->dayCounter() .yearFraction( expiry0, arguments_.fixedPayDates[l]))); fixedLegNpv += arguments_.fixedCoupons[l] * model_->zerobond(arguments_.fixedPayDates[l], expiry0, z[k], discountCurve_) * zSpreadDf; } Real rebate = 0.0; Real zSpreadDf = 1.0; Date rebateDate = expiry0; if (rebatedExercise != NULL) { rebate = rebatedExercise->rebate(idx); rebateDate = rebatedExercise->rebatePaymentDate(idx); zSpreadDf = oas_.empty() ? 1.0 : std::exp( -oas_->value() * (model_->termStructure() ->dayCounter() .yearFraction(expiry0, rebateDate))); } Real exerciseValue = ((type == Option::Call ? 1.0 : -1.0) * (floatingLegNpv - fixedLegNpv) + rebate * model_->zerobond(rebateDate, expiry0, z[k], discountCurve_) * zSpreadDf) / model_->numeraire(expiry0Time, z[k], discountCurve_); // for probability computation if (probabilities_ != None) { if (idx == static_cast<int>( arguments_.exercise->dates().size()) - 1) // if true we are at the latest date, // so we init // the no call probability npvp0.back()[k] = probabilities_ == Naive ? 1.0 : 1.0 / (model_->zerobond(expiry0Time, 0.0, 0.0, discountCurve_) * model_->numeraire(expiry0, z[k], discountCurve_)); if (exerciseValue >= npv0[k]) { npvp0[idx - minIdxAlive][k] = probabilities_ == Naive ? 1.0 : 1.0 / (model_->zerobond(expiry0Time, 0.0, 0.0, discountCurve_) * model_->numeraire(expiry0Time, z[k], discountCurve_)); for (Size ii = idx - minIdxAlive + 1; ii < npvp0.size(); ii++) npvp0[ii][k] = 0.0; } } // end probability computation npv0[k] = std::max(npv0[k], exerciseValue); } } npv1.swap(npv0); // for probability computation if (probabilities_ != None) { for (Size i = 0; i < npvp0.size(); i++) npvp1[i].swap(npvp0[i]); } // end probability computation expiry1 = expiry0; expiry1Time = expiry0Time; } while (--idx >= minIdxAlive - 1); results_.value = npv1[0] * model_->numeraire(0.0, 0.0, discountCurve_); // for probability computation if (probabilities_ != None) { std::vector<Real> prob(npvp0.size()); for (Size i = 0; i < npvp0.size(); i++) { prob[i] = npvp1[i][0] * (probabilities_ == Naive ? 1.0 : model_->numeraire(0.0, 0.0, discountCurve_)); } results_.additionalResults["probabilities"] = prob; } // end probability computation }
void Gaussian1dSwaptionEngine::calculate() const { QL_REQUIRE(arguments_.settlementType == Settlement::Physical, "cash-settled swaptions not yet implemented ..."); Date settlement = model_->termStructure()->referenceDate(); if (arguments_.exercise->dates().back() <= settlement) { // swaption is expired, possibly generated swap is not // valued results_.value = 0.0; return; } int idx = static_cast<int>(arguments_.exercise->dates().size()) - 1; int minIdxAlive = static_cast<int>( std::upper_bound(arguments_.exercise->dates().begin(), arguments_.exercise->dates().end(), settlement) - arguments_.exercise->dates().begin()); VanillaSwap swap = *arguments_.swap; Option::Type type = arguments_.type == VanillaSwap::Payer ? Option::Call : Option::Put; Schedule fixedSchedule = swap.fixedSchedule(); Schedule floatSchedule = swap.floatingSchedule(); Array npv0(2 * integrationPoints_ + 1, 0.0), npv1(2 * integrationPoints_ + 1, 0.0); Array z = model_->yGrid(stddevs_, integrationPoints_); Array p(z.size(), 0.0); Date expiry1 = Null<Date>(), expiry0; Time expiry1Time = Null<Real>(), expiry0Time; do { if (idx == minIdxAlive - 1) expiry0 = settlement; else expiry0 = arguments_.exercise->dates()[idx]; expiry0Time = std::max( model_->termStructure()->timeFromReference(expiry0), 0.0); Size j1 = std::upper_bound(fixedSchedule.dates().begin(), fixedSchedule.dates().end(), expiry0 - 1) - fixedSchedule.dates().begin(); Size k1 = std::upper_bound(floatSchedule.dates().begin(), floatSchedule.dates().end(), expiry0 - 1) - floatSchedule.dates().begin(); // a lazy object is not thread safe, neither is the caching // in gsrprocess. therefore we trigger computations here such // that neither lazy object recalculation nor write access // during caching occurs in the parallized loop below. // this is known to work for the gsr and markov functional // model implementations of Gaussian1dModel #ifdef _OPENMP if (expiry0 > settlement) { for (Size l = k1; l < arguments_.floatingCoupons.size(); l++) { model_->forwardRate(arguments_.floatingFixingDates[l], expiry0, 0.0, arguments_.swap->iborIndex()); model_->zerobond(arguments_.floatingPayDates[l], expiry0, 0.0, discountCurve_); } for (Size l = j1; l < arguments_.fixedCoupons.size(); l++) { model_->zerobond(arguments_.fixedPayDates[l], expiry0, 0.0, discountCurve_); } model_->numeraire(expiry0Time, 0.0, discountCurve_); } #endif #pragma omp parallel for default(shared) firstprivate(p) if(expiry0>settlement) for (Size k = 0; k < (expiry0 > settlement ? npv0.size() : 1); k++) { Real price = 0.0; if (expiry1Time != Null<Real>()) { Array yg = model_->yGrid(stddevs_, integrationPoints_, expiry1Time, expiry0Time, expiry0 > settlement ? z[k] : 0.0); CubicInterpolation payoff0( z.begin(), z.end(), npv1.begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); for (Size i = 0; i < yg.size(); i++) { p[i] = payoff0(yg[i], true); } CubicInterpolation payoff1( z.begin(), z.end(), p.begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); for (Size i = 0; i < z.size() - 1; i++) { price += model_->gaussianShiftedPolynomialIntegral( 0.0, payoff1.cCoefficients()[i], payoff1.bCoefficients()[i], payoff1.aCoefficients()[i], p[i], z[i], z[i], z[i + 1]); } if (extrapolatePayoff_) { if (flatPayoffExtrapolation_) { price += model_->gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0); price += model_->gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[0], z[0], -100.0, z[0]); } else { if (type == Option::Call) price += model_->gaussianShiftedPolynomialIntegral( 0.0, payoff1.cCoefficients()[z.size() - 2], payoff1.bCoefficients()[z.size() - 2], payoff1.aCoefficients()[z.size() - 2], p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0); if (type == Option::Put) price += model_->gaussianShiftedPolynomialIntegral( 0.0, payoff1.cCoefficients()[0], payoff1.bCoefficients()[0], payoff1.aCoefficients()[0], p[0], z[0], -100.0, z[0]); } } } npv0[k] = price; if (expiry0 > settlement) { Real floatingLegNpv = 0.0; for (Size l = k1; l < arguments_.floatingCoupons.size(); l++) { floatingLegNpv += arguments_.nominal * arguments_.floatingAccrualTimes[l] * (arguments_.floatingSpreads[l] + model_->forwardRate( arguments_.floatingFixingDates[l], expiry0, z[k], arguments_.swap->iborIndex())) * model_->zerobond(arguments_.floatingPayDates[l], expiry0, z[k], discountCurve_); } Real fixedLegNpv = 0.0; for (Size l = j1; l < arguments_.fixedCoupons.size(); l++) { fixedLegNpv += arguments_.fixedCoupons[l] * model_->zerobond(arguments_.fixedPayDates[l], expiry0, z[k], discountCurve_); } npv0[k] = std::max(npv0[k], (type == Option::Call ? 1.0 : -1.0) * (floatingLegNpv - fixedLegNpv) / model_->numeraire(expiry0Time, z[k], discountCurve_)); } } npv1.swap(npv0); expiry1 = expiry0; expiry1Time = expiry0Time; } while (--idx >= minIdxAlive - 1); results_.value = npv1[0] * model_->numeraire(0.0, 0.0, discountCurve_); }