inline boost::shared_ptr<LongstaffSchwartzMultiPathPricer> MCAmericanPathEngine<RNG>::lsmPathPricer() const { boost::shared_ptr<StochasticProcessArray> processArray = boost::dynamic_pointer_cast<StochasticProcessArray>(this->process_); QL_REQUIRE(processArray && processArray->size()>0, "Stochastic process array required"); boost::shared_ptr<GeneralizedBlackScholesProcess> process = boost::dynamic_pointer_cast<GeneralizedBlackScholesProcess>( processArray->process(0)); QL_REQUIRE(process, "generalized Black-Scholes process required"); const TimeGrid theTimeGrid = this->timeGrid(); const std::vector<Time> & times = theTimeGrid.mandatoryTimes(); const Size numberOfTimes = times.size(); const std::vector<Date> & fixings = this->arguments_.fixingDates; QL_REQUIRE(fixings.size() == numberOfTimes, "Invalid dates/times"); std::vector<Size> timePositions(numberOfTimes); Array discountFactors(numberOfTimes); std::vector<Handle<YieldTermStructure> > forwardTermStructures(numberOfTimes); const Handle<YieldTermStructure> & riskFreeRate = process->riskFreeRate(); for (Size i = 0; i < numberOfTimes; ++i) { timePositions[i] = theTimeGrid.index(times[i]); discountFactors[i] = riskFreeRate->discount(times[i]); forwardTermStructures[i] = Handle<YieldTermStructure>( boost::make_shared<ImpliedTermStructure>(riskFreeRate, fixings[i])); } const Size polynomialOrder = 2; const LsmBasisSystem::PolynomType polynomType = LsmBasisSystem::Monomial; return boost::shared_ptr<LongstaffSchwartzMultiPathPricer> ( new LongstaffSchwartzMultiPathPricer(this->arguments_.payoff, timePositions, forwardTermStructures, discountFactors, polynomialOrder, polynomType)); }
inline boost::shared_ptr<typename MCPathBasketEngine<RNG,S>::path_pricer_type> MCPathBasketEngine<RNG,S>::pathPricer() const { boost::shared_ptr<PathPayoff> payoff = arguments_.payoff; QL_REQUIRE(payoff, "non-basket payoff given"); boost::shared_ptr<GeneralizedBlackScholesProcess> process = boost::dynamic_pointer_cast<GeneralizedBlackScholesProcess>( process_->process(0)); QL_REQUIRE(process, "Black-Scholes process required"); const TimeGrid theTimeGrid = timeGrid(); const std::vector<Time> & times = theTimeGrid.mandatoryTimes(); const Size numberOfTimes = times.size(); const std::vector<Date> & fixings = this->arguments_.fixingDates; QL_REQUIRE(fixings.size() == numberOfTimes, "Invalid dates/times"); std::vector<Size> timePositions(numberOfTimes); Array discountFactors(numberOfTimes); std::vector<Handle<YieldTermStructure> > forwardTermStructures(numberOfTimes); const Handle<YieldTermStructure> & riskFreeRate = process->riskFreeRate(); for (Size i = 0; i < numberOfTimes; ++i) { timePositions[i] = theTimeGrid.index(times[i]); discountFactors[i] = riskFreeRate->discount(times[i]); forwardTermStructures[i] = Handle<YieldTermStructure>( new ImpliedTermStructure(riskFreeRate, fixings[i])); } return boost::shared_ptr< typename MCPathBasketEngine<RNG,S>::path_pricer_type>( new EuropeanPathMultiPathPricer(payoff, timePositions, forwardTermStructures, discountFactors)); }
//! \brief Calculate the NPV of the remaining cash flow at default time \f$ \tau \f$. //! //! The calculation method used here is based on CIR model. virtual Real defaultNPV(const MultiPath& path, Time defaultTime) const { //find short rate at default time TimeGrid timeGrid = path[0].timeGrid(); auto defaultPos = timeGrid.index(defaultTime); Real shortRate = path[0][defaultPos]; //calculate discount factor from reference time to the default time Time previousTime = timeGrid[0]; Real discountFactor = 1.0; for (auto i = 0; i <= defaultPos; ++i){ discountFactor *= std::exp(-path[0].value(i) * (timeGrid[i] - previousTime)); previousTime = timeGrid[i]; } boost::shared_ptr<const MCVanillaSwapUCVAEngine> engine = engine_.lock(); VanillaSwap::arguments* arguments = dynamic_cast<VanillaSwap::arguments*>(engine->getArguments()); Handle<YieldTermStructure> discountCurve = engine->discountCurve(); Date referenceDate = discountCurve->referenceDate(); std::vector<Date> fixedDates = arguments->fixedPayDates; std::vector<Date> floatingDates = arguments->floatingPayDates; // transfer payment Dates to Times std::vector<Real> fixedTimes; std::vector<Real> floatingTimes; for (int i = 0; i != fixedDates.size(); ++i){ fixedTimes.push_back(engine->instrument()->fixedDayCount().yearFraction(referenceDate, fixedDates[i])); } for (int i = 0; i != floatingDates.size(); ++i){ floatingTimes.push_back(engine->instrument()->floatingDayCount().yearFraction(referenceDate, floatingDates[i])); } // calculate the corresponding discount factors of each leg to default time std::vector<Real> fixedDiscountFactor; std::vector<Real> floatingDiscountFactor; int fixedIndex = 0; int floatingIndex = 0; for (int i = 0; i != fixedTimes.size(); ++i){ if (fixedTimes[i] >= defaultTime){ fixedDiscountFactor.push_back(engine->Model()->discountBond(0.0, fixedTimes[i] - defaultTime, shortRate)); } else{ ++fixedIndex; } } for (int i = 0; i != floatingTimes.size(); ++i){ if (floatingTimes[i] >= defaultTime){ floatingDiscountFactor.push_back(engine->Model()->discountBond(0.0, floatingTimes[i] - defaultTime, shortRate)); } else{ ++floatingIndex; } } //calculate the NPV(tau) Real NPVtau = 0.0; NPVtau += arguments->nominal * (1. - floatingDiscountFactor.back()); for (int m = 0; m != floatingDiscountFactor.size(); ++m){ NPVtau += arguments->nominal * arguments->floatingSpreads[m + floatingIndex] * floatingDiscountFactor[m]; } for (int m = 0; m != fixedDiscountFactor.size(); ++m){ NPVtau -= arguments->fixedCoupons[m + fixedIndex] * fixedDiscountFactor[m]; } if (arguments->type == QuantLib::VanillaSwap::Payer){ NPVtau = NPVtau; } else{ NPVtau = -NPVtau; } return NPVtau * discountFactor; }
boost::shared_ptr<IRDLSCallablePricer> MCIRDLSLSEngine::lsmPathPricer() const { boost::shared_ptr<StochasticProcessArray> processArray = boost::dynamic_pointer_cast<StochasticProcessArray>(this->process_); QL_REQUIRE(processArray && processArray->size()>0, "Stochastic process array required"); boost::shared_ptr<PayoffLeg> payoffLeg = arguments_.payoffLeg; QL_REQUIRE(payoffLeg, "IRDLS payoffLeg given"); //const Handle<YieldTermStructure> &df=arguments_.df; //Frequency freq = arguments_.freq; const TimeGrid theTimeGrid = this->timeGrid(); const std::vector<Time> & times = theTimeGrid.mandatoryTimes(); const Size numberOfTimes = times.size(); const std::vector<Date> & fixings = this->arguments_.fixingDates; std::vector<Date> remainfixings; Date today = Settings::instance().evaluationDate(); const Size numberOfFixings = fixings.size(); for(Size i=0;i<numberOfFixings;++i){ if(fixings[i]>today){ remainfixings.push_back(fixings[i]); } } const Size numberOfRemainFixings = remainfixings.size(); additionalStats_.resize(numberOfTimes); QL_REQUIRE(numberOfRemainFixings == numberOfTimes, "Invalid dates/times"); std::vector<Size> timePositions(numberOfTimes); Array discountFactors(numberOfTimes); //std::vector<Handle<YieldTermStructure> > forwardTermStructures(numberOfTimes); //const Handle<YieldTermStructure> & riskFreeRate = process->riskFreeRate(); for (Size i = 0; i < numberOfTimes; ++i){ timePositions[i] = theTimeGrid.index(times[i]); discountFactors[i] = discountTS_->discount(times[i]); } // forwardTermStructures[i] = Handle<YieldTermStructure>( // new ImpliedTermStructure(riskFreeRate, fixings[i])); const Size polynomialOrder = 2; const LsmBasisSystem::PolynomType polynomType = LsmBasisSystem::Monomial; return boost::shared_ptr<IRDLSCallablePricer> ( new IRDLSCallablePricer(payoffLeg, timePositions, process_, discountFactors, additionalStats_, polynomialOrder, polynomType)); }