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; }
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"); }
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_); }
//------------------------------------------------------------------------ RiskyFloatingBond::RiskyFloatingBond( std::string name, Currency ccy, Real recoveryRate, Handle<DefaultProbabilityTermStructure> defaultTS, Schedule schedule, boost::shared_ptr<IborIndex> index, Integer fixingDays, Real spread, std::vector<Real> notionals, Handle<YieldTermStructure> yieldTS, Natural settlementDays) : RiskyBond(name, ccy, recoveryRate, defaultTS, yieldTS, settlementDays, schedule.calendar()), schedule_(schedule), index_(index), fixingDays_(fixingDays), spread_(spread), notionals_(notionals) { // FIXME: Take paymentConvention into account std::vector<Date> dates = schedule_.dates(); Real previousNotional = notionals_.front(); for (Size i = 1; i < dates.size(); i++) { Real currentNotional = (i < notionals_.size() ? notionals_[i] : notionals_.back()); boost::shared_ptr<CashFlow> interest (new IborCoupon(dates[i], previousNotional, dates[i-1], dates[i], fixingDays_, index_, 1.0, spread_)); boost::shared_ptr<CashFlow> amortization(new AmortizingPayment(previousNotional - currentNotional, dates[i])); previousNotional = currentNotional; leg_.push_back(interest); interestLeg_.push_back(interest); if (amortization->amount() != 0){ leg_.push_back(amortization); redemptionLeg_.push_back(amortization); } } boost::shared_ptr<CashFlow> redemption(new Redemption(previousNotional, schedule_.dates().back())); leg_.push_back(redemption); redemptionLeg_.push_back(redemption); boost::shared_ptr<IborCouponPricer> fictitiousPricer(new BlackIborCouponPricer(Handle<OptionletVolatilityStructure>())); setCouponPricer(leg_,fictitiousPricer); }
//------------------------------------------------------------------------ RiskyFixedBond::RiskyFixedBond( const std::string& name, const Currency& ccy, Real recoveryRate, const Handle<DefaultProbabilityTermStructure>& defaultTS, const Schedule& schedule, Real rate, const DayCounter& dayCounter, BusinessDayConvention paymentConvention, const std::vector<Real>& notionals, const Handle<YieldTermStructure>& yieldTS, Natural settlementDays) : RiskyBond(name, ccy, recoveryRate, defaultTS, yieldTS, settlementDays, schedule.calendar()), schedule_(schedule), rate_(rate), dayCounter_(dayCounter), // paymentConvention_(paymentConvention), notionals_(notionals) { // FIXME: Take paymentConvention into account std::vector<Date> dates = schedule_.dates(); Real previousNotional = notionals_.front(); for (Size i = 1; i < dates.size(); i++) { Real currentNotional = (i < notionals_.size() ? notionals_[i] : notionals_.back()); boost::shared_ptr<CashFlow> interest (new FixedRateCoupon(dates[i], previousNotional, rate_, dayCounter_, dates[i-1], dates[i])); boost::shared_ptr<CashFlow> amortization(new AmortizingPayment(previousNotional - currentNotional, dates[i])); previousNotional = currentNotional; leg_.push_back(interest); interestLeg_.push_back(interest); if (amortization->amount() != 0){ leg_.push_back(amortization); redemptionLeg_.push_back(amortization); } } boost::shared_ptr<CashFlow> redemption(new Redemption(previousNotional, schedule_.dates().back())); leg_.push_back(redemption); redemptionLeg_.push_back(redemption); }
CPIBond::CPIBond(Natural settlementDays, Real faceAmount, bool growthOnly, Real baseCPI, const Period& observationLag, const boost::shared_ptr<ZeroInflationIndex>& cpiIndex, CPI::InterpolationType observationInterpolation, const Schedule& schedule, const std::vector<Rate>& fixedRate, const DayCounter& accrualDayCounter, BusinessDayConvention paymentConvention, const Date& issueDate) : Bond(settlementDays, schedule.calendar(), issueDate), frequency_(schedule.tenor().frequency()), dayCounter_(accrualDayCounter), growthOnly_(growthOnly), baseCPI_(baseCPI), observationLag_(observationLag), cpiIndex_(cpiIndex), observationInterpolation_(observationInterpolation) { maturityDate_ = schedule.endDate(); // a CPIleg know about zero legs and inclusion of base inflation notional cashflows_ = CPILeg(schedule, cpiIndex_, baseCPI_, observationLag_) .withNotionals(faceAmount) .withFixedRates(fixedRate) .withPaymentDayCounter(accrualDayCounter) .withPaymentAdjustment(paymentConvention) .withObservationInterpolation(observationInterpolation_) .withSubtractInflationNominal(growthOnly_); registerWith(cpiIndex_); Leg::const_iterator i; for (i = cashflows_.begin(); i < cashflows_.end(); ++i) { registerWith(*i); } };
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_ }
FloatingCatBond::FloatingCatBond( Natural settlementDays, Real faceAmount, const Schedule& schedule, const boost::shared_ptr<IborIndex>& iborIndex, const DayCounter& paymentDayCounter, boost::shared_ptr<NotionalRisk> notionalRisk, BusinessDayConvention paymentConvention, Natural fixingDays, const std::vector<Real>& gearings, const std::vector<Spread>& spreads, const std::vector<Rate>& caps, const std::vector<Rate>& floors, bool inArrears, Real redemption, const Date& issueDate) : CatBond(settlementDays, schedule.calendar(), issueDate, notionalRisk) { maturityDate_ = schedule.endDate(); cashflows_ = IborLeg(schedule, iborIndex) .withNotionals(faceAmount) .withPaymentDayCounter(paymentDayCounter) .withPaymentAdjustment(paymentConvention) .withFixingDays(fixingDays) .withGearings(gearings) .withSpreads(spreads) .withCaps(caps) .withFloors(floors) .inArrears(inArrears); addRedemptionsToCashflows(std::vector<Real>(1, redemption)); QL_ENSURE(!cashflows().empty(), "bond with no cashflows!"); QL_ENSURE(redemptions_.size() == 1, "multiple redemptions created"); registerWith(iborIndex); }
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!"); }
AssetSwap::AssetSwap(bool payBondCoupon, const shared_ptr<Bond>& bond, Real bondCleanPrice, const shared_ptr<IborIndex>& iborIndex, Spread spread, const Schedule& floatSchedule, const DayCounter& floatingDayCounter, bool parSwap) : Swap(2), bond_(bond), bondCleanPrice_(bondCleanPrice), nonParRepayment_(100), spread_(spread), parSwap_(parSwap) { Schedule schedule = floatSchedule; if (floatSchedule.empty()) schedule = Schedule(bond_->settlementDate(), bond_->maturityDate(), iborIndex->tenor(), iborIndex->fixingCalendar(), iborIndex->businessDayConvention(), iborIndex->businessDayConvention(), DateGeneration::Backward, false); // endOfMonth // the following might become an input parameter BusinessDayConvention paymentAdjustment = Following; Date finalDate = schedule.calendar().adjust( schedule.endDate(), paymentAdjustment); Date adjBondMaturityDate = schedule.calendar().adjust( bond_->maturityDate(), paymentAdjustment); QL_REQUIRE(finalDate==adjBondMaturityDate, "adjusted schedule end date (" << finalDate << ") must be equal to adjusted bond maturity date (" << adjBondMaturityDate << ")"); // bondCleanPrice must be the (forward) clean price // at the floating schedule start date upfrontDate_ = schedule.startDate(); Real dirtyPrice = bondCleanPrice_ + bond_->accruedAmount(upfrontDate_); Real notional = bond_->notional(upfrontDate_); /* In the market asset swap, the bond is purchased in return for payment of the full price. The notional of the floating leg is then scaled by the full price. */ if (!parSwap_) notional *= dirtyPrice/100.0; if (floatingDayCounter==DayCounter()) legs_[1] = IborLeg(schedule, iborIndex) .withNotionals(notional) .withPaymentAdjustment(paymentAdjustment) .withSpreads(spread); else legs_[1] = IborLeg(schedule, iborIndex) .withNotionals(notional) .withPaymentDayCounter(floatingDayCounter) .withPaymentAdjustment(paymentAdjustment) .withSpreads(spread); for (Leg::const_iterator i=legs_[1].begin(); i<legs_[1].end(); ++i) registerWith(*i); const Leg& bondLeg = bond_->cashflows(); for (Leg::const_iterator i=bondLeg.begin(); i<bondLeg.end(); ++i) { // whatever might be the choice for the discounting engine // bond flows on upfrontDate_ must be discarded bool upfrontDateBondFlows = false; if (!(*i)->hasOccurred(upfrontDate_, upfrontDateBondFlows)) legs_[0].push_back(*i); } QL_REQUIRE(!legs_[0].empty(), "empty bond leg to start with"); // special flows if (parSwap_) { // upfront on the floating leg Real upfront = (dirtyPrice-100.0)/100.0*notional; shared_ptr<CashFlow> upfrontCashFlow(new SimpleCashFlow(upfront, upfrontDate_)); legs_[1].insert(legs_[1].begin(), upfrontCashFlow); // backpayment on the floating leg // (accounts for non-par redemption, if any) Real backPayment = notional; shared_ptr<CashFlow> backPaymentCashFlow(new SimpleCashFlow(backPayment, finalDate)); legs_[1].push_back(backPaymentCashFlow); } else { // final notional exchange shared_ptr<CashFlow> finalCashFlow(new SimpleCashFlow(notional, finalDate)); legs_[1].push_back(finalCashFlow); } QL_REQUIRE(!legs_[0].empty(), "empty bond leg"); for (Leg::const_iterator i=legs_[0].begin(); i<legs_[0].end(); ++i) registerWith(*i); if (payBondCoupon) { payer_[0]=-1.0; payer_[1]=+1.0; } else { payer_[0]=+1.0; payer_[1]=-1.0; } }
FixedRateLeg::FixedRateLeg(const Schedule& schedule) : schedule_(schedule), paymentCalendar_(schedule.calendar()), paymentAdjustment_(Following), paymentLag_(0) {}