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; }
double McLmmVanillaSwaptionPricer::price(const VanillaSwaption& vanillaSwaption, size_t nbSimulation) const { clock_t start_pricing = std::clock(); assert( mcLmm_->get_lmm()->get_LMMTenorStructure()->get_tenorType() == vanillaSwaption.get_lmmTenorStructureTenorType()); // this pricer can price this swaption VanillaSwap vanillaSwap = vanillaSwaption.getUnderlyingSwap(); double result = 0.0; double variance = 0.0; LMM::Index indexValuationdate = 0; LMM::Index indexMaturity = vanillaSwaption.get_indexMaturity(); for(size_t itrSimulation=0; itrSimulation<nbSimulation; ++itrSimulation) { mcLmm_->simulateLMM(); // YY TODO: not efficient at all, don't need to do all the simulation ... const matrix& liborMatrix = mcLmm_->get_liborMatrix(); const std::vector<double>& numeraire = mcLmm_->get_numeraire(); double npvFloatingLeg = pvFloatingLeg(indexMaturity, vanillaSwap, numeraire, liborMatrix); double npvFixedLeg = pvFixedLeg (indexMaturity, vanillaSwap, numeraire); double payoffAtMaturity = vanillaSwaption.payoff(npvFloatingLeg,npvFixedLeg); double value = payoffAtMaturity * numeraire[indexValuationdate]/numeraire[indexMaturity]; result += value; variance += value*value; } result /= nbSimulation; clock_t end_pricing = std::clock(); double pricing_duration = double(end_pricing - start_pricing) / CLOCKS_PER_SEC; if(LMM::DEUBGLMM()) { variance = (variance/nbSimulation-result*result); std::cout << LMM::NOTIF_MSG << " mcScheme = " << MCSchemeType::mcSchemeType2String(mcLmm_->get_mcSchemeType()) << ", nbSimualtion = " << nbSimulation << ", Pricing Time = " << pricing_duration << ", SwaptionPriceMC = " << result << ", 99% confidential interval = " << 2.57*std::sqrt(variance / nbSimulation) << std::endl; } return result; }