double LmmVanillaSwapPricer::swapNPV_Analytical_2(const VanillaSwap& vanillaSwap, const std::vector<double>& liborsInitValue) const // initLibor[i] = L_i[T_0] { assert(pLMMTenorStructure_->get_horizon()+1 == liborsInitValue.size()); assert(pLMMTenorStructure_->get_horizon() >= vanillaSwap.get_indexEnd()); // if not cannot price this swap; size_t horizon = pLMMTenorStructure_->get_horizon(); const double & floatingLegdelta_T = vanillaSwap.get_floatingLegTenorType().YearFraction(); const double & fixedLegdelta_T = vanillaSwap.get_fixedLegTenorType().YearFraction(); //! ZC[i] = P(T_0,T_i) std::vector<double> ZC(horizon+2); ZC[0] = 1.0; for(size_t i=1; i<ZC.size(); ++i) { ZC[i] = ZC[i-1]/(1+floatingLegdelta_T*liborsInitValue[i-1]); } //! numeraire std::vector<double> numeraire(ZC.size() ); // determinisitc IR for(size_t i=0; i<ZC.size(); ++i) { numeraire[i] = 1.0/ZC[i]; } //! pvFloatingLeg: 1 - 1 const std::vector<LMM::Index>& floatingLegPaymentIndexSchedule = vanillaSwap.get_floatingLegPaymentIndexSchedule(); //size_t floatingLegTenorLmmTenorRatio = vanillaSwap.get_floatingLegTenorLmmTenorRatio(); LMM::Index indexFloatingLegStart = floatingLegPaymentIndexSchedule.front(); LMM::Index indexFloatingLegEnd = floatingLegPaymentIndexSchedule.back(); double pvFloatingLegValue = ZC[indexFloatingLegStart-1] - ZC[indexFloatingLegEnd]; ////! pvFloatingLeg: exact //double pvFloatingLeg = 0.0; //const std::vector<LMM::Index>& floatingLegPaymentIndexSchedule = vanillaSwap.get_floatingLegPaymentIndexSchedule(); //for(size_t itr = 0; itr < floatingLegPaymentIndexSchedule.size(); ++itr) //{ // //! At time T_{i+1}, pay: L_i(T_i) // size_t floatingLegPaymentIndex = floatingLegPaymentIndexSchedule[itr]; // = i+1 // size_t indexLibor = floatingLegPaymentIndex-1; // =i, because : floatingTenor = lmmTenor // pvFloatingLeg += floatingLegdelta_T*initLibor[indexLibor]*ZC[floatingLegPaymentIndex]; //} LMM::Index indexValuationDate = 0; double pvFixedLegValue = pvFixedLeg(indexValuationDate,vanillaSwap,numeraire); return pvFloatingLegValue - pvFixedLegValue; }
const Real Gaussian1dModel::zerobondOption( const Option::Type &type, const Date &expiry, const Date &valueDate, const Date &maturity, const Rate strike, const Date &referenceDate, const Real y, const Handle<YieldTermStructure> &yts, const Real yStdDevs, const Size yGridPoints, const bool extrapolatePayoff, const bool flatPayoffExtrapolation) const { calculate(); Time fixingTime = termStructure()->timeFromReference(expiry); Time referenceTime = referenceDate == Null<Date>() ? 0.0 : termStructure()->timeFromReference(referenceDate); Array yg = yGrid(yStdDevs, yGridPoints, fixingTime, referenceTime, y); Array z = yGrid(yStdDevs, yGridPoints); Array p(yg.size()); for (Size i = 0; i < yg.size(); i++) { Real expValDsc = zerobond(valueDate, expiry, yg[i], yts); Real discount = zerobond(maturity, expiry, yg[i], yts) / expValDsc; p[i] = std::max((type == Option::Call ? 1.0 : -1.0) * (discount - strike), 0.0) / numeraire(fixingTime, yg[i], yts) * expValDsc; } CubicInterpolation payoff( z.begin(), z.end(), p.begin(), CubicInterpolation::Spline, true, CubicInterpolation::Lagrange, 0.0, CubicInterpolation::Lagrange, 0.0); Real price = 0.0; for (Size i = 0; i < z.size() - 1; i++) { price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[i], payoff.bCoefficients()[i], payoff.aCoefficients()[i], p[i], z[i], z[i], z[i + 1]); } if (extrapolatePayoff) { if (flatPayoffExtrapolation) { price += gaussianShiftedPolynomialIntegral( 0.0, 0.0, 0.0, 0.0, p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0); price += gaussianShiftedPolynomialIntegral(0.0, 0.0, 0.0, 0.0, p[0], z[0], -100.0, z[0]); } else { if (type == Option::Call) price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[z.size() - 2], payoff.bCoefficients()[z.size() - 2], payoff.aCoefficients()[z.size() - 2], p[z.size() - 2], z[z.size() - 2], z[z.size() - 1], 100.0); if (type == Option::Put) price += gaussianShiftedPolynomialIntegral( 0.0, payoff.cCoefficients()[0], payoff.bCoefficients()[0], payoff.aCoefficients()[0], p[0], z[0], -100.0, z[0]); } } return numeraire(referenceTime, y, yts) * price; }