CreditDefaultSwap::CreditDefaultSwap(Protection::Side side, Real notional, Rate upfront, Rate runningSpread, const Schedule& schedule, BusinessDayConvention convention, const DayCounter& dayCounter, bool settlesAccrual, bool paysAtDefaultTime, const Date& protectionStart, const Date& upfrontDate, const boost::shared_ptr<Claim>& claim) : side_(side), notional_(notional), upfront_(upfront), runningSpread_(runningSpread), settlesAccrual_(settlesAccrual), paysAtDefaultTime_(paysAtDefaultTime), claim_(claim), protectionStart_(protectionStart == Null<Date>() ? schedule[0] : protectionStart) { QL_REQUIRE(protectionStart_ <= schedule[0], "protection can not start after accrual"); leg_ = FixedRateLeg(schedule) .withNotionals(notional) .withCouponRates(runningSpread, dayCounter) .withPaymentAdjustment(convention); Date d = upfrontDate == Null<Date>() ? schedule[0] : upfrontDate; upfrontPayment_.reset(new SimpleCashFlow(notional*upfront, d)); QL_REQUIRE(upfrontPayment_->date() >= protectionStart_, "upfront can not be due before contract start"); if (!claim_) claim_ = boost::shared_ptr<Claim>(new FaceValueClaim); registerWith(claim_); }
FixedRateBond::FixedRateBond(Natural settlementDays, Real faceAmount, const Schedule& schedule, const std::vector<Rate>& coupons, const DayCounter& accrualDayCounter, BusinessDayConvention paymentConvention, Real redemption, const Date& issueDate, const Calendar& paymentCalendar) : Bond(settlementDays, paymentCalendar==Calendar() ? schedule.calendar() : paymentCalendar, issueDate), frequency_(schedule.tenor().frequency()), dayCounter_(accrualDayCounter) { maturityDate_ = schedule.endDate(); cashflows_ = FixedRateLeg(schedule) .withNotionals(faceAmount) .withCouponRates(coupons, accrualDayCounter) .withPaymentCalendar(calendar_) .withPaymentAdjustment(paymentConvention); addRedemptionsToCashflows(std::vector<Real>(1, redemption)); QL_ENSURE(!cashflows().empty(), "bond with no cashflows!"); QL_ENSURE(redemptions_.size() == 1, "multiple redemptions created"); }
AmortizingFixedRateBond::AmortizingFixedRateBond( Natural settlementDays, const Calendar& calendar, Real initialFaceAmount, const Date& startDate, const Period& bondTenor, const Frequency& sinkingFrequency, const Rate coupon, const DayCounter& accrualDayCounter, BusinessDayConvention paymentConvention, const Date& issueDate) : Bond(settlementDays, calendar, issueDate), frequency_(sinkingFrequency), dayCounter_(accrualDayCounter) { maturityDate_ = startDate + bondTenor; cashflows_ = FixedRateLeg(sinkingSchedule(startDate, bondTenor, sinkingFrequency, calendar)) .withNotionals(sinkingNotionals(bondTenor, sinkingFrequency, coupon, initialFaceAmount)) .withCouponRates(coupon, accrualDayCounter) .withPaymentAdjustment(paymentConvention); addRedemptionsToCashflows(); }
NthToDefault::NthToDefault( const boost::shared_ptr<Basket>& basket, Size n, Protection::Side side, const Schedule& premiumSchedule, Rate upfrontRate, Rate premiumRate, const DayCounter& dayCounter, Real nominal, bool settlePremiumAccrual ) : basket_(basket), n_(n), side_(side), nominal_(nominal), premiumSchedule_(premiumSchedule), premiumRate_(premiumRate), upfrontRate_(upfrontRate), dayCounter_(dayCounter), settlePremiumAccrual_(settlePremiumAccrual) { QL_REQUIRE(n_ <= basket_->size(), "NTD order provided is larger than the basket size."); // Basket inception must lie before contract protection start. QL_REQUIRE(basket->refDate() <= premiumSchedule.startDate(), //using the start date of the schedule might be wrong, think of the CDS rule "Basket did not exist before contract start."); premiumLeg_ = FixedRateLeg(premiumSchedule) .withNotionals(nominal) .withCouponRates(premiumRate, dayCounter) .withPaymentAdjustment(Unadjusted); registerWith(basket_); }
FixedRateBond::FixedRateBond(Natural settlementDays, const Calendar& calendar, Real faceAmount, const Date& startDate, const Date& maturityDate, const Period& tenor, const std::vector<Rate>& coupons, const DayCounter& accrualDayCounter, BusinessDayConvention accrualConvention, BusinessDayConvention paymentConvention, Real redemption, const Date& issueDate, const Date& stubDate, DateGeneration::Rule rule, bool endOfMonth, const Calendar& paymentCalendar) : Bond(settlementDays, paymentCalendar==Calendar() ? calendar : paymentCalendar, issueDate), frequency_(tenor.frequency()), dayCounter_(accrualDayCounter) { maturityDate_ = maturityDate; Date firstDate, nextToLastDate; switch (rule) { case DateGeneration::Backward: firstDate = Date(); nextToLastDate = stubDate; break; case DateGeneration::Forward: firstDate = stubDate; nextToLastDate = Date(); break; case DateGeneration::Zero: case DateGeneration::ThirdWednesday: case DateGeneration::Twentieth: case DateGeneration::TwentiethIMM: QL_FAIL("stub date (" << stubDate << ") not allowed with " << rule << " DateGeneration::Rule"); default: QL_FAIL("unknown DateGeneration::Rule (" << Integer(rule) << ")"); } Schedule schedule(startDate, maturityDate_, tenor, calendar, accrualConvention, accrualConvention, rule, endOfMonth, firstDate, nextToLastDate); cashflows_ = FixedRateLeg(schedule) .withNotionals(faceAmount) .withCouponRates(coupons, accrualDayCounter) .withPaymentCalendar(calendar_) .withPaymentAdjustment(paymentConvention); addRedemptionsToCashflows(std::vector<Real>(1, redemption)); QL_ENSURE(!cashflows().empty(), "bond with no cashflows!"); QL_ENSURE(redemptions_.size() == 1, "multiple redemptions created"); }
CreditDefaultSwap::CreditDefaultSwap(Protection::Side side, Real notional, Rate spread, const Schedule& schedule, BusinessDayConvention convention, const DayCounter& dayCounter, bool settlesAccrual, bool paysAtDefaultTime, const Date& protectionStart, const boost::shared_ptr<Claim>& claim, const DayCounter& lastPeriodDayCounter, const Natural standardCdsStartDelayDays, const Natural standardCdsUpfrontDelayDays) : side_(side), notional_(notional), upfront_(boost::none), runningSpread_(spread), settlesAccrual_(settlesAccrual), paysAtDefaultTime_(paysAtDefaultTime), claim_(claim), protectionStart_(protectionStart == Null<Date>() ? schedule[0] : protectionStart) { Date d = schedule[0]; try { if (schedule.rule() == DateGeneration::CDS) { // a standard CDS is identified // by the schedule rule Date evalDate = Settings::instance().evaluationDate(); if (protectionStart == Null<Date>()) protectionStart_ = evalDate + standardCdsStartDelayDays; // if // protection // start is // given it // is not set // here d = schedule.calendar().advance( evalDate, standardCdsUpfrontDelayDays * Days, schedule.businessDayConvention(), schedule.endOfMonth()); QL_REQUIRE(protectionStart_ >= schedule[0], "protection must start on or after " "accrual start for standard CDS"); } } catch (...) { QL_REQUIRE(protectionStart_ <= schedule[0], "protection can not start after accrual " "for non standard CDS"); } leg_ = FixedRateLeg(schedule) .withNotionals(notional) .withCouponRates(spread, dayCounter) .withPaymentAdjustment(convention) .withLastPeriodDayCounter(lastPeriodDayCounter); upfrontPayment_.reset(new SimpleCashFlow(0.0, d)); if (!claim_) claim_ = boost::shared_ptr<Claim>(new FaceValueClaim); registerWith(claim_); }
crosscurrencyswap::crosscurrencyswap( Type type, Currency fixedCurrency, Real fixedLegnominal, const Schedule& fixedSchedule, Rate fixedRate, const DayCounter& fixedDayCount, const boost::shared_ptr<IborIndex>& fixedIborIndex, Currency floatCurrency, Real floatLegnominal, const Schedule& floatSchedule, const boost::shared_ptr<IborIndex>& floatIborIndex, Spread spread, const DayCounter& floatingDayCount, boost::optional<BusinessDayConvention> paymentConvention) : Swap(2), type_(type), fixedCurrency_(fixedCurrency),Fixedlegnominal_(fixedLegnominal), fixedSchedule_(fixedSchedule), fixedRate_(fixedRate), fixedDayCount_(fixedDayCount), fixedIborIndex_(fixedIborIndex), floatCurrency_(floatCurrency), Floatlegnominal_(floatLegnominal), floatingSchedule_(floatSchedule), floatIborIndex_(floatIborIndex), spread_(spread), floatingDayCount_(floatingDayCount) { if (paymentConvention) paymentConvention_ = *paymentConvention; else paymentConvention_ = floatingSchedule_.businessDayConvention(); legs_[0] = FixedRateLeg(fixedSchedule_) .withNotionals(Fixedlegnominal_) .withCouponRates(fixedRate_, fixedDayCount_) .withPaymentAdjustment(paymentConvention_); legs_[1] = IborLeg(floatingSchedule_, floatIborIndex_) .withNotionals(Floatlegnominal_) .withPaymentDayCounter(floatingDayCount_) .withPaymentAdjustment(paymentConvention_) .withSpreads(spread_); for (Leg::const_iterator i = legs_[1].begin(); i < legs_[1].end(); ++i) registerWith(*i); switch (type_) { case Payer: payer_[0] = -1.0; payer_[1] = +1.0; break; case Receiver: payer_[0] = +1.0; payer_[1] = -1.0; break; default: QL_FAIL("Unknown Cross Currency Swap type"); } }
RepoCompoundingSwap::RepoCompoundingSwap( Type type, Real nominal, const Schedule& fixedSchedule, Rate fixedRate, const DayCounter& fixedDayCount, const Schedule& floatSchedule, const boost::shared_ptr<RepoChina>& iborIndex, Spread rateSpread, Spread couponSpread, const DayCounter& floatingDayCount, boost::optional<BusinessDayConvention> paymentConvention) : Swap(2), type_(type), nominal_(nominal), fixedSchedule_(fixedSchedule), fixedRate_(fixedRate), fixedDayCount_(fixedDayCount), floatingSchedule_(floatSchedule), iborIndex_(iborIndex), rateSpread_(rateSpread), couponSpread_(couponSpread), floatingDayCount_(floatingDayCount) { if (paymentConvention) paymentConvention_ = *paymentConvention; else paymentConvention_ = floatingSchedule_.businessDayConvention(); legs_[0] = FixedRateLeg(fixedSchedule_) .withNotionals(nominal_) .withCouponRates(fixedRate_, fixedDayCount_) .withPaymentAdjustment(paymentConvention_); legs_[1] = SubPeriodsCouponLeg(floatingSchedule_, iborIndex_) .withNotionals(nominal_) .withPaymentDayCounter(floatingDayCount_) .withPaymentAdjustment(paymentConvention_) .withRateSpreads(rateSpread_) .withCouponSpreads(couponSpread_); for (Leg::const_iterator i = legs_[1].begin(); i < legs_[1].end(); ++i) registerWith(*i); switch (type_) { case Payer: payer_[0] = -1.0; payer_[1] = +1.0; break; case Receiver: payer_[0] = +1.0; payer_[1] = -1.0; break; default: QL_FAIL("Unknown repo-compounding-swap type"); } }
OvernightIndexedSwap::OvernightIndexedSwap( Type type, Real nominal, const Schedule& schedule, Rate fixedRate, const DayCounter& fixedDC, const boost::shared_ptr<OvernightIndex>& overnightIndex, Spread spread) : Swap(2), type_(type), nominal_(nominal), paymentFrequency_(schedule.tenor().frequency()), //schedule_(schedule), fixedRate_(fixedRate), fixedDC_(fixedDC), overnightIndex_(overnightIndex), spread_(spread) { if (fixedDC_==DayCounter()) fixedDC_ = overnightIndex_->dayCounter(); legs_[0] = FixedRateLeg(schedule) .withNotionals(nominal_) .withCouponRates(fixedRate_, fixedDC_); legs_[1] = OvernightLeg(schedule, overnightIndex_) .withNotionals(nominal_) .withSpreads(spread_); for (Size j=0; j<2; ++j) { for (Leg::iterator i = legs_[j].begin(); i!= legs_[j].end(); ++i) registerWith(*i); } switch (type_) { case Payer: payer_[0] = -1.0; payer_[1] = +1.0; break; case Receiver: payer_[0] = +1.0; payer_[1] = -1.0; break; default: QL_FAIL("Unknown overnight-swap type"); } }
CallableFixedRateBond::CallableFixedRateBond( Natural settlementDays, Real faceAmount, const Schedule& schedule, const std::vector<Rate>& coupons, const DayCounter& accrualDayCounter, BusinessDayConvention paymentConvention, Real redemption, const Date& issueDate, const CallabilitySchedule& putCallSchedule) : CallableBond(settlementDays, schedule, accrualDayCounter, issueDate, putCallSchedule) { frequency_ = schedule.tenor().frequency(); bool isZeroCouponBond = (coupons.size() == 1 && close(coupons[0], 0.0)); if (!isZeroCouponBond) { cashflows_ = FixedRateLeg(schedule) .withNotionals(faceAmount) .withCouponRates(coupons, accrualDayCounter) .withPaymentAdjustment(paymentConvention); addRedemptionsToCashflows(std::vector<Real>(1, redemption)); } else { Date redemptionDate = calendar_.adjust(maturityDate_, paymentConvention); setSingleRedemption(faceAmount, redemption, redemptionDate); } // used for impliedVolatility() calculation boost::shared_ptr<SimpleQuote> dummyVolQuote(new SimpleQuote(0.)); blackVolQuote_.linkTo(dummyVolQuote); blackEngine_ = boost::shared_ptr<PricingEngine>( new BlackCallableFixedRateBondEngine(blackVolQuote_, blackDiscountCurve_)); }
AmortizingFixedRateBond::AmortizingFixedRateBond( Natural settlementDays, const std::vector<Real>& notionals, const Schedule& schedule, const std::vector<Rate>& coupons, const DayCounter& accrualDayCounter, BusinessDayConvention paymentConvention, const Date& issueDate) : Bond(settlementDays, schedule.calendar(), issueDate), frequency_(schedule.tenor().frequency()), dayCounter_(accrualDayCounter) { maturityDate_ = schedule.endDate(); cashflows_ = FixedRateLeg(schedule) .withNotionals(notionals) .withCouponRates(coupons, accrualDayCounter) .withPaymentAdjustment(paymentConvention); addRedemptionsToCashflows(); QL_ENSURE(!cashflows().empty(), "bond with no cashflows!"); }
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MidPointCDOEngine::calculate() const { Date today = Settings::instance().evaluationDate(); results_.premiumValue = 0.0; results_.upfrontPremiumValue = 0.0; results_.protectionValue = 0.0; results_.expectedTrancheLoss.clear(); // set remainingBasket_, results_.remainingNotional, // vector results_.expectedTrancheLoss for all schedule dates initialize(); const vector<Date>& dates = arguments_.schedule.dates(); if (dates.front() > today) results_.upfrontPremiumValue = arguments_.upfrontRate * results_.remainingNotional; vector<boost::shared_ptr<CashFlow> > premiumLeg = FixedRateLeg(arguments_.schedule) .withCouponRates(arguments_.runningRate, arguments_.dayCounter) .withPaymentAdjustment(arguments_.paymentConvention) .withNotionals(1.0); Real e1 = 0; if (dates[0] > today) e1 = expectedTrancheLoss (dates[0]); for (Size i = 0; i < premiumLeg.size(); i++) { boost::shared_ptr<Coupon> coupon = boost::dynamic_pointer_cast<Coupon>(premiumLeg[i]); Date paymentDate = coupon->date(); Date startDate = std::max(coupon->accrualStartDate(), arguments_.yieldTS->referenceDate()); Date endDate = coupon->accrualEndDate(); Date defaultDate = startDate + (endDate-startDate)/2; if (paymentDate <= today) continue; Real e2 = expectedTrancheLoss(paymentDate); results_.premiumValue += (results_.remainingNotional - e2) * coupon->amount() * arguments_.yieldTS->discount(paymentDate); Real discount = arguments_.yieldTS->discount(defaultDate); results_.premiumValue += coupon->accruedAmount(defaultDate) * discount * (e2 - e1); results_.protectionValue += discount * (e2 - e1); e1 = e2; } if (arguments_.side == Protection::Buyer) { results_.protectionValue *= -1; results_.premiumValue *= -1; results_.upfrontPremiumValue *= -1; } results_.value = results_.premiumValue - results_.protectionValue + results_.upfrontPremiumValue; results_.errorEstimate = Null<Real>(); }
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void MonteCarloCDOEngine2::calculate() const { Date today = Settings::instance().evaluationDate(); results_.protectionValue = 0.0; results_.premiumValue = 0.0; results_.expectedTrancheLoss.clear(); // set remainingBasket_, results_.remainingNotional, initialize(); const vector<Date>& dates = arguments_.schedule.dates(); if (dates.front() > today) results_.upfrontPremiumValue = arguments_.upfrontRate * results_.remainingNotional; Real tmax = ActualActual().yearFraction(today, dates.back()); //Real tmin = ActualActual().yearFraction(today, dates.front()); QL_REQUIRE(tmax >= 0, "tmax < 0"); vector<boost::shared_ptr<CashFlow> > premiumLeg = FixedRateLeg(arguments_.schedule) .withNotionals(1.0) .withCouponRates(arguments_.runningRate, arguments_.dayCounter) .withPaymentAdjustment(arguments_.paymentConvention); boost::shared_ptr<Pool> pool = remainingBasket_->pool(); vector<Real> premiumValue(samples_, 0.0); vector<Real> protectionValue(samples_, 0.0); vector<Real> value(samples_, 0.0); vector<Real> fairPremium(samples_, 0.0); vector<vector<Real> > cumulativeTrancheLoss(samples_, vector<Real>()); for (Size i = 0; i < samples_; i++) { //================================ /****************************************************************** * (1) Compute default times ******************************************************************/ rdm_->nextSequence(tmax); /****************************************************************** * (2) Cumulative tranche loss to schedule dates ******************************************************************/ cumulativeTrancheLoss[i].resize(dates.size(), 0.0); remainingBasket_->updateScenarioLoss(); for (Size k = 0; k < dates.size(); k++) cumulativeTrancheLoss[i][k] = remainingBasket_->scenarioTrancheLoss(dates[k]); /***************************************************************** * (3) Contribution of this scenario to the protection leg * - Loop through all incremental tranche loss events between * start and end date * - Pay and discount these increments as they occur *****************************************************************/ vector<Loss> increments = remainingBasket_->scenarioIncrementalTrancheLosses(dates.front(), dates.back()); for (Size k = 0; k < increments.size(); k++) protectionValue[i] += increments[k].amount * arguments_.yieldTS->discount(increments[k].time); /***************************************************************** * (4) Contribution of this scenario to the premium leg * - Loop through all coupon periods * - Pay coupon at period end on effective notional * - Effective notional: * - Start with remaining notional minus cumulative loss * on the tranche until period start =: N * - Reduce N for each loss in the period by subtracting the * the incremental tranche loss weighted with the time * to period end *****************************************************************/ for (Size j = 0; j < premiumLeg.size(); j++) { boost::shared_ptr<Coupon> coupon = boost::dynamic_pointer_cast<Coupon>(premiumLeg[j]); Date startDate = std::max(coupon->accrualStartDate(), arguments_.yieldTS->referenceDate()); Date endDate = coupon->accrualEndDate(); Date paymentDate = coupon->date(); if (paymentDate <= today) continue; Real t1 = ActualActual().yearFraction(today, startDate); Real t2 = ActualActual().yearFraction(today, endDate); Real PL = cumulativeTrancheLoss[i][j]; Real N = results_.remainingNotional - PL; for (Size k = 0; k < increments.size(); k++) { Real t = increments[k].time; if (t <= t1) continue; if (t >= t2) break; N -= (t2-t) / (t2-t1) * increments[k].amount; } Real discount = arguments_.yieldTS->discount(paymentDate); premiumValue[i] += N * coupon->amount() * discount; } /***************** * Aggregate *****************/ results_.premiumValue += premiumValue[i]; results_.protectionValue += protectionValue[i]; value[i] = premiumValue[i] - protectionValue[i] + results_.upfrontPremiumValue; for (Size k = 0; k < dates.size(); k++) results_.expectedTrancheLoss[k] += cumulativeTrancheLoss[i][k]; /* cout.setf (ios::fixed, ios::floatfield); cout << setprecision(0); for (Size k = 0; k < dates.size(); k++) cout << setw(3) << cumulativeTrancheLoss[i][k] << " "; cout << endl; cout << setprecision(2); for (Size k = 0; k < pool->size(); k++) { const string name = pool->names()[k]; Real t = pool->getTime(name); if (t < 6) cout << setw(10) << name << " " << setw(5) << t << endl; } */ } // end of loop over samples ========================================== /***************************************** * Expected values, normalize, switch sign *****************************************/ results_.premiumValue /= samples_; results_.protectionValue /= samples_; for (Size k = 0; k < dates.size(); k++) results_.expectedTrancheLoss[k] /= samples_; if (arguments_.side == Protection::Buyer) { results_.protectionValue *= -1; results_.premiumValue *= -1; results_.upfrontPremiumValue *= -1; } results_.value = results_.premiumValue - results_.protectionValue + results_.upfrontPremiumValue; /************************************************* * Error estimates - NPV *************************************************/ Real avg = 0.0; Real var = 0.0; for (Size i = 0; i < samples_; i++) { var += value[i] * value[i]; avg += value[i]; } avg /= samples_; var /= samples_; results_.errorEstimate = sqrt(var - avg * avg); /***************************************************** * Error estimates - fair premium * http://math.nyu.edu/~atm262/files/spring06/ircm/cdo *****************************************************/ /* Real x = 0.0, xx = 0.0, y = 0.0, yy = 0.0, xy = 0.0; for (Size i = 0; i < samples_; i++) { Real dx = protectionValue[i] - results_.upfrontPremiumValue; Real dy = premiumValue[i]; x += dx; xx += dx * dx; y += dy; yy += dy * dy; xy += dx * dy; } x /= samples_; y /= samples_; xx /= samples_; yy /= samples_; xy /= samples_; Real v = x*x/(y*y) * (xx/(x*x) + yy/(y*y) - 2.0 * xy/(x*y)); Real stdFairPremium = sqrt(v) * arguments_.runningRate; */ }
void NonstandardSwap::init() { QL_REQUIRE(fixedNominal_.size() == fixedRate_.size(), "Fixed nominal size (" << fixedNominal_.size() << ") does not match fixed rate size (" << fixedRate_.size() << ")"); QL_REQUIRE(fixedNominal_.size() == fixedSchedule_.size() - 1, "Fixed nominal size (" << fixedNominal_.size() << ") does not match schedule size (" << fixedSchedule_.size() << ") - 1"); QL_REQUIRE(floatingNominal_.size() == floatingSchedule_.size() - 1, "Floating nominal size (" << floatingNominal_.size() << ") does not match schedule size (" << floatingSchedule_.size() << ") - 1"); QL_REQUIRE(floatingNominal_.size() == spread_.size(), "Floating nominal size (" << floatingNominal_.size() << ") does not match spread size (" << spread_.size() << ")"); QL_REQUIRE(floatingNominal_.size() == gearing_.size(), "Floating nominal size (" << floatingNominal_.size() << ") does not match gearing size (" << gearing_.size() << ")"); // if the gearing is zero then the ibor leg will be set up with fixed // coupons which makes trouble here in this context. We therefore use // a dirty trick and enforce the gearing to be non zero. for (Size i = 0; i < gearing_.size(); ++i) { if (close(gearing_[i], 0.0)) gearing_[i] = QL_EPSILON; } legs_[0] = FixedRateLeg(fixedSchedule_) .withNotionals(fixedNominal_) .withCouponRates(fixedRate_, fixedDayCount_) .withPaymentAdjustment(paymentConvention_); legs_[1] = IborLeg(floatingSchedule_, iborIndex_) .withNotionals(floatingNominal_) .withPaymentDayCounter(floatingDayCount_) .withPaymentAdjustment(paymentConvention_) .withSpreads(spread_) .withGearings(gearing_); if (intermediateCapitalExchange_) { for (Size i = 0; i < legs_[0].size() - 1; i++) { Real cap = fixedNominal_[i + 1] - fixedNominal_[i]; if (!close(cap, 0.0)) { std::vector<boost::shared_ptr<CashFlow> >::iterator it1 = legs_[0].begin(); std::advance(it1, i + 1); legs_[0].insert( it1, boost::shared_ptr<CashFlow>( new Redemption(cap, legs_[0][i]->date()))); std::vector<Real>::iterator it2 = fixedNominal_.begin(); std::advance(it2, i + 1); fixedNominal_.insert(it2, fixedNominal_[i]); i++; } } for (Size i = 0; i < legs_[1].size() - 1; i++) { Real cap = floatingNominal_[i + 1] - floatingNominal_[i]; if (!close(cap, 0.0)) { std::vector<boost::shared_ptr<CashFlow> >::iterator it1 = legs_[1].begin(); std::advance(it1, i + 1); legs_[1].insert( it1, boost::shared_ptr<CashFlow>( new Redemption(cap, legs_[1][i]->date()))); std::vector<Real>::iterator it2 = floatingNominal_.begin(); std::advance(it2, i + 1); floatingNominal_.insert(it2, floatingNominal_[i]); i++; } } } if (finalCapitalExchange_) { legs_[0].push_back(boost::shared_ptr<CashFlow>( new Redemption(fixedNominal_.back(), legs_[0].back()->date()))); fixedNominal_.push_back(fixedNominal_.back()); fixedRate_.push_back(0.0); legs_[1].push_back(boost::shared_ptr<CashFlow>(new Redemption( floatingNominal_.back(), legs_[1].back()->date()))); floatingNominal_.push_back(floatingNominal_.back()); } for (Leg::const_iterator i = legs_[1].begin(); i < legs_[1].end(); ++i) registerWith(*i); switch (type_) { case VanillaSwap::Payer: payer_[0] = -1.0; payer_[1] = +1.0; break; case VanillaSwap::Receiver: payer_[0] = +1.0; payer_[1] = -1.0; break; default: QL_FAIL("Unknown nonstandard-swap type"); } }