std::vector<boost::shared_ptr<CashFlow> > RiskyBond::expectedCashflows() { std::vector<boost::shared_ptr<CashFlow> > expected; std::vector<boost::shared_ptr<CashFlow> > cf = cashflows(); Date today = Settings::instance().evaluationDate(); Date npvDate = calendar_.advance(today, settlementDays_, Days); Date d1 = effectiveDate(); for (Size i = 0; i < cf.size(); i++) { Date d2 = cf[i]->date(); if (d2 > npvDate) { d1 = max(npvDate, d1); Date defaultDate = d1 + (d2-d1)/2; Real coupon = cf[i]->amount() * defaultTS_->survivalProbability(d2); Real recovery = notional(defaultDate) * recoveryRate_ * (defaultTS_->survivalProbability(d1) -defaultTS_->survivalProbability(d2)); boost::shared_ptr<CashFlow> flow1(new SimpleCashFlow(coupon, d2)); expected.push_back(flow1); boost::shared_ptr<CashFlow> flow2(new SimpleCashFlow(recovery, defaultDate)); expected.push_back(flow2); } d1 = d2; } return expected; }
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"); }
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"); }
void CallableFixedRateBond::setupArguments( PricingEngine::arguments* args) const { Bond::setupArguments(args); CallableBond::arguments* arguments = dynamic_cast<CallableBond::arguments*>(args); QL_REQUIRE(arguments != 0, "no arguments given"); Date settlement = arguments->settlementDate; arguments->redemption = redemption()->amount(); arguments->redemptionDate = redemption()->date(); const Leg& cfs = cashflows(); arguments->couponDates.clear(); arguments->couponDates.reserve(cfs.size()-1); arguments->couponAmounts.clear(); arguments->couponAmounts.reserve(cfs.size()-1); for (Size i=0; i<cfs.size()-1; i++) { if (!cfs[i]->hasOccurred(settlement, false)) { arguments->couponDates.push_back(cfs[i]->date()); arguments->couponAmounts.push_back(cfs[i]->amount()); } } arguments->callabilityPrices.clear(); arguments->callabilityDates.clear(); arguments->callabilityPrices.reserve(putCallSchedule_.size()); arguments->callabilityDates.reserve(putCallSchedule_.size()); arguments->paymentDayCounter = paymentDayCounter_; arguments->frequency = frequency_; arguments->putCallSchedule = putCallSchedule_; for (Size i=0; i<putCallSchedule_.size(); i++) { if (!putCallSchedule_[i]->hasOccurred(settlement, false)) { arguments->callabilityDates.push_back( putCallSchedule_[i]->date()); arguments->callabilityPrices.push_back( putCallSchedule_[i]->price().amount()); if (putCallSchedule_[i]->price().type()== Callability::Price::Clean) { /* calling accrued() forces accrued interest to be zero if future option date is also coupon date, so that dirty price = clean price. Use here because callability is always applied before coupon in the tree engine. */ arguments->callabilityPrices.back() += this->accrued(putCallSchedule_[i]->date()); } } } }
Real RiskyBond::totalFutureFlows() const { Date today = Settings::instance().evaluationDate(); Real flow = 0; std::vector<boost::shared_ptr<CashFlow> > cf = cashflows(); for (Size i = 0; i < cf.size(); i++) { if (cf[i]->date() > today) flow += cf[i]->amount(); } return flow; }
Real RiskyBond::totalFutureFlows() const { Date today = Settings::instance().evaluationDate(); Date npvDate = calendar_.advance(today, settlementDays_, Days); Real flow = 0; std::vector<boost::shared_ptr<CashFlow> > cf = cashflows(); for (Size i = 0; i < cf.size(); i++) { if (cf[i]->date() > npvDate) flow += cf[i]->amount(); } return flow; }
Real RiskyBond::riskfreeNPV() const { Date today = Settings::instance().evaluationDate(); Real npv = 0; std::vector<boost::shared_ptr<CashFlow> > cf = cashflows(); for (Size i = 0; i < cf.size(); i++) { Date d2 = cf[i]->date(); if (d2 > today) npv += cf[i]->amount() * yieldTS()->discount(d2); } return npv; }
void RiskyBond::performCalculations() const { NPV_ = 0; Date today = Settings::instance().evaluationDate(); std::vector<boost::shared_ptr<CashFlow> > cf = cashflows(); Date d1 = effectiveDate(); for (Size i = 0; i < cf.size(); i++) { Date d2 = cf[i]->date(); if (d2 > today) { d1 = max(today , d1); Date defaultDate = d1 + (d2-d1)/2; // Mid-Point Rule Real coupon = cf[i]->amount() * defaultTS_->survivalProbability(d2); Real recovery = notional(defaultDate) * recoveryRate_ * (defaultTS_->survivalProbability(d1) -defaultTS_->survivalProbability(d2)); NPV_ += coupon * yieldTS()->discount(d2); NPV_ += recovery * yieldTS()->discount(defaultDate); } d1 = d2; } }
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!"); }
FloatingRateBond::FloatingRateBond( Natural settlementDays, Real faceAmount, const Date& startDate, const Date& maturityDate, Frequency couponFrequency, const Calendar& calendar, const ext::shared_ptr<IborIndex>& iborIndex, const DayCounter& accrualDayCounter, BusinessDayConvention accrualConvention, 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, const Date& stubDate, DateGeneration::Rule rule, bool endOfMonth) : Bond(settlementDays, calendar, issueDate) { 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_, Period(couponFrequency), calendar_, accrualConvention, accrualConvention, rule, endOfMonth, firstDate, nextToLastDate); cashflows_ = IborLeg(schedule, iborIndex) .withNotionals(faceAmount) .withPaymentDayCounter(accrualDayCounter) .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); }
void MCIRDLSLSEngine::calculate() const { for(Size i=0;i<additionalStats_.size();++i) { additionalStats_[i].reset(); } pathPricer_ = this->lsmPathPricer(); Size NeedRnd=randNum(); PseudoRandom::rsg_type gen = PseudoRandom::make_sequence_generator(NeedRnd, seed_); const std::vector<Real>& rand = gen.nextSequence().value; //Real values=this->pathPricer_->values(rand,nCalibrationSamples_); Real values=this->pathPricer_->values(rand,maxSamples_); this->pathPricer_->calibrate(nCalibrationSamples_); values=this->pathPricer_->values(rand,maxSamples_); results_.additionalResults["ImpliedCall"] = values; const std::vector<Date> & fixings=this->arguments_.fixingDates; Size sizeOfCouponNum=fixings.size(); Leg expectedCashflows; Leg pastLeg = arguments_.payoffLeg->leg(); expectedCashflows=pastLeg; std::vector<Real> cashflows(sizeOfCouponNum); std::vector<Real> cashflowsDates(sizeOfCouponNum); std::vector<Real> earlyExProbability; std::vector<Real>& earlyExProbabilityM = pathPricer_->earlyExProbability(); // 그거 지난 일자는 빠진거. // //for(Size i=0;i<additionalStats_.size();++i) { // expectedCashflows[sizeOfCouponNum-i-1]=boost::shared_ptr<CashFlow>( // new SimpleCashFlow(additionalStats_[sizeOfCouponNum-i-1].mean(),fixings[sizeOfCouponNum-i-1])); // cashflows[sizeOfCouponNum-i-1]=additionalStats_[sizeOfCouponNum-i-1].mean(); // // //std::cout << additionalStats_[i].mean() << std::endl; //} Date today = Settings::instance().evaluationDate(); Size numberOfPastFixings=0; for(Size i=0;i<sizeOfCouponNum;++i){ if(fixings[i]<today){ numberOfPastFixings=numberOfPastFixings+1; } } for(Size i=0;i<numberOfPastFixings;++i) { expectedCashflows[i]=boost::shared_ptr<CashFlow>( new SimpleCashFlow((arguments_.payoffLeg->payoff())[i]->amount(),fixings[i])); cashflows[i]=(arguments_.payoffLeg->payoff())[i]->amount(),fixings[i]; earlyExProbability.push_back(0.0); } for(Size i=0;i<additionalStats_.size();++i) { expectedCashflows[sizeOfCouponNum-i-1]=boost::shared_ptr<CashFlow>( new SimpleCashFlow(additionalStats_[additionalStats_.size()-i-1].mean(),fixings[sizeOfCouponNum-i-1])); cashflows[sizeOfCouponNum-i-1]=additionalStats_[additionalStats_.size()-i-1].mean(); earlyExProbability.push_back(earlyExProbabilityM[i]/maxSamples_); } results_.additionalResults["cashflows"] = cashflows; /*for(Size i=0;i<additionalStats_.size();++i) { std::cout << "cashflows : "<< cashflows[i] << std::endl; }*/ for(Size i=0;i<sizeOfCouponNum;++i){ cashflowsDates[i]=static_cast<Real>(fixings[i].serialNumber()); } results_.additionalResults["cashflowsDates"] = cashflowsDates; results_.additionalResults["EarlyExProbability"] = earlyExProbability; //pricer에서 Notional을 더해서옴. 언제 상환될지 모르므로... //Real Notional=arguments_.Notional; //expectedCashflows.push_back(boost::shared_ptr<CashFlow>(new SimpleCashFlow(Notional,fixings.back()))); results_.expectedCashflows=expectedCashflows; //expected Bond Price도 넣어야하나..? QL_REQUIRE(!discountTS_.empty(), "discounting term structure handle is empty"); results_.valuationDate = Settings::instance().evaluationDate(); bool includeRefDateFlows =false; Real Notional=arguments_.Notional; results_.additionalResults["nonCallableValue"] = pathPricer_->expectedBondPrice()*10000/maxSamples_; results_.additionalResults["nonCallableUnitValue"] = pathPricer_->expectedBondPrice()*100000000/(maxSamples_*Notional); results_.value = CashFlows::npv(results_.expectedCashflows, **discountTS_, includeRefDateFlows, results_.valuationDate, results_.valuationDate); results_.settlementValue = CashFlows::npv(results_.expectedCashflows, **discountTS_, false, arguments_.settlementDate, arguments_.settlementDate); results_.additionalResults["UnitValue"] = results_.value*10000/Notional; }