/// <summary>
        /// Calculates the present value sensitivity of the product.
        /// <para>
        /// The present value sensitivity of the product is the sensitivity of present value to the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="cdsIndex">  the product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="referenceDate">  the reference date </param>
        /// <param name="refData">  the reference data </param>
        /// <returns> the present value sensitivity </returns>
        public virtual PointSensitivityBuilder presentValueSensitivity(ResolvedCdsIndex cdsIndex, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData)
        {
            if (isExpired(cdsIndex, ratesProvider))
            {
                return(PointSensitivityBuilder.none());
            }
            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 signedNotional = cds.BuySell.normalize(cds.Notional);
            PointSensitivityBuilder protectionLegSensi = underlyingPricer.protectionLegSensitivity(cds, rates.First, rates.Second, referenceDate, effectiveStartDate, recoveryRate);

            protectionLegSensi = protectionLegSensi.multipliedBy(signedNotional * rates.Third);
            PointSensitivityBuilder riskyAnnuitySensi = underlyingPricer.riskyAnnuitySensitivity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate);

            riskyAnnuitySensi = riskyAnnuitySensi.multipliedBy(-cds.FixedRate * signedNotional * rates.Third);

            return(protectionLegSensi.combinedWith(riskyAnnuitySensi));
        }