virtual void updatePath(const std::vector<std::pair<Date, Real> > &events, NotionalPath &path) const { path.reset(); Real losses = 0; Real previousNotional = 1; for(size_t i=0; i<events.size(); ++i) { losses+=events[i].second; if(losses>attachement_ && previousNotional>0) { previousNotional = std::max(0.0, (exhaustion_-losses)/(exhaustion_-attachement_)); path.addReduction(paymentOffset_->paymentDate(events[i].first), previousNotional); } } }
Real MonteCarloCatBondEngine::npv(bool includeSettlementDateFlows, Date settlementDate, Date npvDate, Real& lossProbability, Real &exhaustionProbability, Real& expectedLoss) const { const size_t MAX_PATHS = 10000; //TODO lossProbability = 0.0; exhaustionProbability = 0.0; expectedLoss = 0.0; if (arguments_.cashflows.empty()) return 0.0; if (settlementDate == Date()) settlementDate = Settings::instance().evaluationDate(); if (npvDate == Date()) npvDate = settlementDate; Real totalNPV = 0.0; Date effectiveDate = std::max(arguments_.startDate, settlementDate); Date maturityDate = (*arguments_.cashflows.rbegin())->date(); boost::shared_ptr<CatSimulation> catSimulation = catRisk_->newSimulation(effectiveDate, maturityDate); std::vector<std::pair<Date, Real> > eventsPath; NotionalPath notionalPath; Real riskFreeNPV = pathNpv(includeSettlementDateFlows, settlementDate, notionalPath); size_t pathCount=0; while(catSimulation->nextPath(eventsPath) && pathCount<MAX_PATHS) { arguments_.notionalRisk->updatePath(eventsPath, notionalPath); if(notionalPath.loss()>0) { //optimization, most paths will not include any loss totalNPV += pathNpv(includeSettlementDateFlows, settlementDate, notionalPath); lossProbability+=1; if (notionalPath.loss()==1) exhaustionProbability+=1; expectedLoss+=notionalPath.loss(); } else { totalNPV += riskFreeNPV; } pathCount++; } lossProbability/=pathCount; exhaustionProbability/=pathCount; expectedLoss/=pathCount; return totalNPV/(pathCount*discountCurve_->discount(npvDate)); }
CatBond::results MonteCarloCatBondEngine::npv(bool includeSettlementDateFlows, Date settlementDate, Date npvDate) const { const size_t MAX_PATHS = 10000; //TODO CatBond::results result; result.reset(); double lossProbability = 0.0; double exhaustionProbability = 0.0; double expectedLoss = 0.0; //GenericRiskStatistics<GeneralStatistics> statistics; GeneralStatistics statistics; if (arguments_.cashflows.empty()) { return result; } if (settlementDate == Date()) settlementDate = Settings::instance().evaluationDate(); if (npvDate == Date()) npvDate = settlementDate; Real totalNPV = 0.0; Date effectiveDate = std::max(arguments_.startDate, settlementDate); Date maturityDate = (*arguments_.cashflows.rbegin())->date(); auto catSimulation = catRisk_->newSimulation(effectiveDate, maturityDate); std::vector<std::pair<Date, Real> > eventsPath; NotionalPath notionalPath; Real riskFreeNPV = pathNpv(includeSettlementDateFlows, settlementDate, notionalPath); size_t pathCount=0; while(catSimulation->nextPath(eventsPath) && pathCount<MAX_PATHS) { arguments_.notionalRisk->updatePath(eventsPath, notionalPath); if(notionalPath.loss()>0) { //optimization, most paths will not include any loss double thisNpv = pathNpv(includeSettlementDateFlows, settlementDate, notionalPath); totalNPV += thisNpv; lossProbability+=1; if (notionalPath.loss()==1) exhaustionProbability+=1; expectedLoss+=notionalPath.loss(); statistics.add(thisNpv, 1.0); } else { totalNPV += riskFreeNPV; statistics.add(riskFreeNPV, 1.0); } pathCount++; } lossProbability/=pathCount; exhaustionProbability/=pathCount; expectedLoss/=pathCount; result.valuationDate = settlementDate; result.value = totalNPV/(pathCount*discountCurve_->discount(npvDate)); result.settlementValue = result.value; result.lossProbability = lossProbability; result.exhaustionProbability = exhaustionProbability; result.expectedLoss = expectedLoss; if(Null<Real>()!=varLevel_) { result.var = result.value - statistics.percentile(1.0-varLevel_); result.stdDev = statistics.standardDeviation(); result.skew = statistics.skewness(); result.kurtosis = statistics.kurtosis(); } return result; }
Real MonteCarloCatBondEngine::cashFlowRiskyValue(const boost::shared_ptr<CashFlow> cf, const NotionalPath& notionalPath) const { return cf->amount()*notionalPath.notionalRate(cf->date()); //TODO: fix for more complicated cashflows }