AnalyticCDSPricer { public double protectionLegCreditSensitivity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final int creditCurveNode) { ArgumentChecker.notNull(cds, "null cds"); ArgumentChecker.notNull(yieldCurve, "null yieldCurve"); ArgumentChecker.notNull(creditCurve, "null creditCurve"); ArgumentChecker.isTrue(creditCurveNode >= 0 && creditCurveNode < creditCurve.getNumberOfKnots(), "creditCurveNode out of range"); if ((creditCurveNode != 0 && cds.getProtectionEnd() <= creditCurve.getTimeAtIndex(creditCurveNode - 1)) || (creditCurveNode != creditCurve.getNumberOfKnots() - 1 && cds.getEffectiveProtectionStart() >= creditCurve.getTimeAtIndex(creditCurveNode + 1))) { return 0.0; } if (cds.getProtectionEnd() <= 0.0) { return 0.0; } final double[] integrationSchedule = getIntegrationsPoints(cds.getEffectiveProtectionStart(), cds.getProtectionEnd(), yieldCurve, creditCurve); double t = integrationSchedule[0]; double ht0 = creditCurve.getRT(t); double rt0 = yieldCurve.getRT(t); double dqdr0 = creditCurve.getSingleNodeDiscountFactorSensitivity(t, creditCurveNode); double q0 = Math.exp(-ht0); double p0 = Math.exp(-rt0); double pvSense = 0.0; final int n = integrationSchedule.length; for (int i = 1; i < n; ++i) { t = integrationSchedule[i]; final double ht1 = creditCurve.getRT(t); final double dqdr1 = creditCurve.getSingleNodeDiscountFactorSensitivity(t, creditCurveNode); final double rt1 = yieldCurve.getRT(t); final double q1 = Math.exp(-ht1); final double p1 = Math.exp(-rt1); if (dqdr0 == 0.0 && dqdr1 == 0.0) { ht0 = ht1; rt0 = rt1; p0 = p1; q0 = q1; continue; } final double hBar = ht1 - ht0; final double fBar = rt1 - rt0; final double fhBar = hBar + fBar; double dPVSense; if (Math.abs(fhBar) < 1e-5) { final double e = epsilon(-fhBar); final double eP = epsilonP(-fhBar); final double dPVdq0 = p0 * ((1 + hBar) * e - hBar * eP); final double dPVdq1 = -p0 * q0 / q1 * (e - hBar * eP); dPVSense = dPVdq0 * dqdr0 + dPVdq1 * dqdr1; } else { final double w = fBar / fhBar * (p0 * q0 - p1 * q1); dPVSense = ((w / q0 + hBar * p0) / fhBar) * dqdr0 - ((w / q1 + hBar * p1) / fhBar) * dqdr1; } pvSense += dPVSense; ht0 = ht1; dqdr0 = dqdr1; rt0 = rt1; p0 = p1; q0 = q1; } pvSense *= cds.getLGD(); final double df = yieldCurve.getDiscountFactor(cds.getCashSettleTime()); pvSense /= df; return pvSense; } AnalyticCDSPricer();  AnalyticCDSPricer(final AccrualOnDefaultFormulae formula); double pv(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final double fractionalSpread, final PriceType cleanOrDirty); double pv(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final double fractionalSpread, final PriceType cleanOrDirty,
      final double valuationTime); double pv(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final double fractionalSpread); double parSpread(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve); double protectionLeg(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve); double protectionLeg(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final double valuationTime); double dirtyAnnuity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve); double annuity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve); double annuity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final PriceType cleanOrDirty); double annuity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final PriceType cleanOrDirty, final double valuationTime); double pvCreditSensitivity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final double fractionalSpread,
      final int creditCurveNode); double pvYieldSensitivity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final double fractionalSpread, final int yieldCurveNode); double parSpreadCreditSensitivity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final int creditCurveNode); double pvPremiumLegCreditSensitivity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final int creditCurveNode); double pvPremiumLegYieldSensitivity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final int yieldCurveNode); double protectionLegCreditSensitivity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final int creditCurveNode); double protectionLegYieldSensitivity(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final int yieldCurveNode);  }
@Test public void sensitivityParallelShiftTest() { final double[] ccTimes = new double[] {0.25, 0.5, 1.00000001, 2.0, 3.0, 5.0, 7.2, 10.0, 20.0 }; final double[] ccRates = new double[] {0.05, 0.06, 0.07, 0.05, 0.09, 0.09, 0.07, 0.065, 0.06 }; final double[] ycTimes = new double[] {1 / 52., 1 / 12., 1 / 4., 1 / 2., 3 / 4., 1.0, 2.1, 5.2, 11.0, 30.0 }; final double[] ycRates = new double[] {0.005, 0.006, 0.007, 0.01, 0.01, 0.015, 0.02, 0.03, 0.04, 0.05 }; final ISDACompliantCreditCurve creditCurve = new ISDACompliantCreditCurve(ccTimes, ccRates); final ISDACompliantYieldCurve yieldCurve = new ISDACompliantYieldCurve(ycTimes, ycRates); final LocalDate today = LocalDate.of(2013, 7, 2); final LocalDate stepin = today.plusDays(2); final LocalDate valueDate = today.plusDays(3); final LocalDate startDate = today.plusMonths(1); final LocalDate endDate = LocalDate.of(2023, 6, 20); final CDSAnalytic cds = new CDSAnalytic(today, stepin, valueDate, startDate, endDate, true, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4); final double fd = fdProtectionLegSense(cds, yieldCurve, creditCurve); final int n = creditCurve.getNumberOfKnots(); double anal = 0.0; for (int i = 0; i < n; i++) { anal += PRICER.protectionLegCreditSensitivity(cds, yieldCurve, creditCurve, i); } assertEquals(fd, anal, 1e-8); }