//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the CDS index product. /// <para> /// The present value of the product is based on {@code referenceDate}. /// This is typically the valuation date, or cash settlement date if the product is associated with a {@code Trade}. /// </para> /// <para> /// This method can calculate the clean or dirty present value, see <seealso cref="PriceType"/>. /// If calculating the clean value, the accrued interest is calculated based on the step-in date. /// /// </para> /// </summary> /// <param name="cdsIndex"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="referenceDate"> the reference date </param> /// <param name="priceType"> the price type </param> /// <param name="refData"> the reference data </param> /// <returns> the present value </returns> public virtual CurrencyAmount presentValue(ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider, LocalDate referenceDate, PriceType priceType, ReferenceData refData) { if (isExpired(cdsIndex, ratesProvider)) { return(CurrencyAmount.of(cdsIndex.Currency, 0d)); } ResolvedCds cds = cdsIndex.toSingleNameCds(); LocalDate stepinDate = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData); LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate); double recoveryRate = underlyingPricer.recoveryRate(cds, ratesProvider); Triple <CreditDiscountFactors, LegalEntitySurvivalProbabilities, double> rates = reduceDiscountFactors(cds, ratesProvider); double protectionLeg = (1d - recoveryRate) * underlyingPricer.protectionFull(cds, rates.First, rates.Second, referenceDate, effectiveStartDate); double rpv01 = underlyingPricer.riskyAnnuity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate, priceType); double amount = cds.BuySell.normalize(cds.Notional) * rates.Third * (protectionLeg - rpv01 * cds.FixedRate); return(CurrencyAmount.of(cds.Currency, amount)); }