/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.credit.isdastandardmodel;
import static org.testng.AssertJUnit.assertEquals;
import org.testng.annotations.Test;
import org.threeten.bp.LocalDate;
import org.threeten.bp.Month;
import org.threeten.bp.Period;
import com.opengamma.util.test.TestGroup;
/**
* Test.
*/
@Test(groups = TestGroup.UNIT)
public class AnalyticCDSPricerTest extends ISDABaseTest {
@SuppressWarnings("unused")
@Test(enabled = false)
public void timingTest() {
final int warmup = 1000;
final int benchmark = 10000;
final double fracSpred = 0.01;
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); // Tuesday
final LocalDate stepin = today.plusDays(1);
final LocalDate valueDate = today.plusDays(3); // Friday
final LocalDate startDate = today.plusMonths(1); // protection starts in a month
final LocalDate endDate1 = LocalDate.of(2018, 6, 20);
final LocalDate endDate2 = LocalDate.of(2023, 6, 20);
final CDSAnalytic cds1 = new CDSAnalytic(today, stepin, valueDate, startDate, endDate1, true, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4);
final CDSAnalytic cds2 = new CDSAnalytic(today, stepin, valueDate, startDate, endDate2, true, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4);
for (int i = 0; i < warmup; i++) {
final double p1 = PRICER.pv(cds1, yieldCurve, creditCurve, fracSpred);
final double p2 = PRICER.pv(cds2, yieldCurve, creditCurve, fracSpred);
}
long timer = System.nanoTime();
double p1 = 0;
for (int i = 0; i < benchmark; i++) {
p1 += PRICER.pv(cds1, yieldCurve, creditCurve, fracSpred);
}
System.out.println(p1);
double time = (System.nanoTime() - timer) / 1e6;
System.out.println("time for " + benchmark + " 5 year CDS: " + time + "ms");
timer = System.nanoTime();
double p2 = 0;
for (int i = 0; i < benchmark; i++) {
p2 += PRICER.pv(cds2, yieldCurve, creditCurve, fracSpred);
}
System.out.println(p2);
time = (System.nanoTime() - timer) / 1e6;
System.out.println("time for " + benchmark + " 10 year CDS: " + time + "ms");
// now do the date logic
for (int i = 0; i < warmup; i++) {
final CDSAnalytic cds1temp = new CDSAnalytic(today, stepin, valueDate, startDate, endDate1, true, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4);
final CDSAnalytic cds2temp = new CDSAnalytic(today, stepin, valueDate, startDate, endDate2, true, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4);
}
timer = System.nanoTime();
double p3 = 0;
for (int i = 0; i < benchmark; i++) {
final CDSAnalytic cds = new CDSAnalytic(today, stepin, valueDate, startDate, endDate1, true, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4);
p3 += PRICER.pv(cds, yieldCurve, creditCurve, fracSpred);
}
System.out.println(p3);
time = (System.nanoTime() - timer) / 1e6;
System.out.println("time for " + benchmark + " 5 year CDS with date logic: " + time + "ms");
timer = System.nanoTime();
double p4 = 0;
for (int i = 0; i < benchmark; i++) {
final CDSAnalytic cds = new CDSAnalytic(today, stepin, valueDate, startDate, endDate2, true, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4);
p4 += PRICER.pv(cds, yieldCurve, creditCurve, fracSpred);
}
System.out.println(p3);
time = (System.nanoTime() - timer) / 1e6;
System.out.println("time for " + benchmark + " 10 year CDS with date logic: " + time + "ms");
}
@Test
public void creditCurveSensitivityTest() {
final double[] ccTimes = new double[] {0.25, 0.5, 1.001, 2.0, 3.0, 5.0, 7.2, 10.0, 20.0 };
final double[] ccNormalRates = new double[] {0.05, 0.06, 0.07, 0.08, 0.09, 0.09, 0.07, 0.065, 0.06 };
final double[] ccLowRates = new double[] {0.00, 0.00, 1e-6, 2e-4, 5e-4, 0.001, 0.0015, 0.002, 0.0015 };
final double[] ycTimes = new double[] {1 / 52., 1 / 12., 1 / 4., 1 / 2., 3 / 4., 1.0, 2.1, 5.0, 11.0, 30.0 };
final double[] ycNormalRates = new double[] {0.004, 0.006, 0.007, 0.01, 0.01, 0.015, 0.02, 0.03, 0.04, 0.05 };
final double[] ycLowRates = new double[] {0.00, 0.00, 0.00, 0.0, 0.00, 0.0005, 0.001, 0.0015, 0.002, 0.0015 };
final ISDACompliantCreditCurve creditCurveLow = new ISDACompliantCreditCurve(ccTimes, ccLowRates);
final ISDACompliantCreditCurve creditCurveNorm = new ISDACompliantCreditCurve(ccTimes, ccNormalRates);
final ISDACompliantYieldCurve yieldCurveLow = new ISDACompliantYieldCurve(ycTimes, ycLowRates);
final ISDACompliantYieldCurve yieldCurveNorm = new ISDACompliantYieldCurve(ycTimes, ycNormalRates);
final LocalDate today = LocalDate.of(2013, 7, 2); // Tuesday
final LocalDate stepin = today.plusDays(1); // this is usually 1
final LocalDate valueDate = today.plusDays(3); // Friday
final LocalDate startDate = today; // protection starts now
final LocalDate endDate = LocalDate.of(2017, 9, 20);
final boolean payAccOnDefault = true;
final CDSAnalytic cds = new CDSAnalytic(today, stepin, valueDate, startDate, endDate, payAccOnDefault, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4);
for (int count = 0; count < 2; count++) {
final AnalyticCDSPricer pricer = count == 0 ? PRICER : PRICER_MARKIT_FIX;
creditCurveSenseTest(pricer, cds, yieldCurveLow, creditCurveLow);
creditCurveSenseTest(pricer, cds, yieldCurveLow, creditCurveNorm);
creditCurveSenseTest(pricer, cds, yieldCurveNorm, creditCurveLow);
creditCurveSenseTest(pricer, cds, yieldCurveNorm, creditCurveNorm);
}
}
@Test
public void yieldCurveSenseTest() {
final double coupon = 0.01;
final double[] ccTimes = new double[] {0.25, 0.5, 1.001, 2.0, 3.0, 5.0, 7.2, 10.0, 20.0 };
final double[] ccNormalRates = new double[] {0.05, 0.06, 0.07, 0.08, 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.0, 11.0, 30.0 };
final double[] ycNormalRates = new double[] {0.004, 0.006, 0.007, 0.01, 0.01, 0.015, 0.02, 0.03, 0.04, 0.05 };
final ISDACompliantCreditCurve creditCurveNorm = new ISDACompliantCreditCurve(ccTimes, ccNormalRates);
final ISDACompliantYieldCurve yieldCurveNorm = new ISDACompliantYieldCurve(ycTimes, ycNormalRates);
final CDSAnalyticFactory factory = new CDSAnalyticFactory();
final CDSAnalytic cds = factory.makeIMMCDS(LocalDate.of(2013, Month.SEPTEMBER, 10), Period.ofYears(5));
// final AnalyticCDSPricer pricer = new AnalyticCDSPricer(true);
final int n = ycTimes.length;
for (int i = 0; i < n; i++) {
double fd = fdProtectionLegYieldSense(PRICER_MARKIT_FIX, cds, yieldCurveNorm, creditCurveNorm, i);
double anal = PRICER_MARKIT_FIX.protectionLegYieldSensitivity(cds, yieldCurveNorm, creditCurveNorm, i);
// System.out.println(fd + "\t" + anal);
assertEquals(fd, anal, 1e-10);
fd = fdPremiumLegYieldSense(PRICER_MARKIT_FIX, cds, yieldCurveNorm, creditCurveNorm, i);
anal = PRICER_MARKIT_FIX.pvPremiumLegYieldSensitivity(cds, yieldCurveNorm, creditCurveNorm, i);
// System.out.println(fd + "\t" + anal);
assertEquals(fd, anal, 1e-9);
fd = fdPVYieldSense(PRICER_MARKIT_FIX, cds, yieldCurveNorm, creditCurveNorm, coupon, i);
anal = PRICER_MARKIT_FIX.pvYieldSensitivity(cds, yieldCurveNorm, creditCurveNorm, coupon, i);
// System.out.println(fd + "\t" + anal);
assertEquals(fd, anal, 1e-10);
}
}
@Test(enabled = false)
void spreadSensitivityTest() {
System.out.println("spreadSensitivityTest");
final double[] ccTimes = new double[] {0.25, 0.5, 1.001, 2.0, 3.0, 5.0, 7.2, 10.0, 20.0 };
final double[] ccNormalRates = new double[] {0.05, 0.06, 0.07, 0.08, 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.0, 11.0, 30.0 };
final double[] ycNormalRates = new double[] {0.004, 0.006, 0.007, 0.01, 0.01, 0.015, 0.02, 0.03, 0.04, 0.05 };
final ISDACompliantCreditCurve creditCurveNorm = new ISDACompliantCreditCurve(ccTimes, ccNormalRates);
final ISDACompliantYieldCurve yieldCurveNorm = new ISDACompliantYieldCurve(ycTimes, ycNormalRates);
final LocalDate today = LocalDate.of(2013, 7, 2); // Tuesday
final LocalDate stepin = today.plusDays(1); // this is usually 1
final LocalDate valueDate = today.plusDays(3); // Friday
final LocalDate startDate = today; // protection starts now
final LocalDate endDate = LocalDate.of(2017, 9, 20);
final boolean payAccOnDefault = true;
final CDSAnalytic cds = new CDSAnalytic(today, stepin, valueDate, startDate, endDate, payAccOnDefault, Period.ofMonths(3), StubType.FRONTSHORT, false, 0.4);
for (int i = 0; i < ccTimes.length; i++) {
final double dSdH = PRICER.parSpreadCreditSensitivity(cds, yieldCurveNorm, creditCurveNorm, i);
System.out.println(dSdH);
}
}
private void creditCurveSenseTest(final AnalyticCDSPricer pricer, final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve) {
final int n = creditCurve.getNumberOfKnots();
for (int i = 0; i < n; i++) {
final double fdProSense = fdProtectionLegSense(cds, yieldCurve, creditCurve, i);
final double analProSense = pricer.protectionLegCreditSensitivity(cds, yieldCurve, creditCurve, i);
final double fdRPV01Sense = fdRPV01Sense(cds, yieldCurve, creditCurve, i, pricer);
final double analRPV01Sense = pricer.pvPremiumLegCreditSensitivity(cds, yieldCurve, creditCurve, i);
assertEquals("ProSense " + i, fdProSense, analProSense, 1e-9);
assertEquals("RPV01Sense " + i, fdRPV01Sense, analRPV01Sense, 5e-8);
}
}
@Test
// (enabled=false)
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); // Tuesday
final LocalDate stepin = today.plusDays(2); // this is usually 1
final LocalDate valueDate = today.plusDays(3); // Friday
final LocalDate startDate = today.plusMonths(1); // protection starts in a month
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);
}
private double fdRPV01Sense(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final int creditCurveNode, final AnalyticCDSPricer pricer) {
final double h = creditCurve.getZeroRateAtIndex(creditCurveNode);
final double eps = 1e-3 * Math.max(1e-3, h);
final ISDACompliantCreditCurve ccUp = creditCurve.withRate(h + eps, creditCurveNode);
final ISDACompliantCreditCurve ccDown = creditCurve.withRate(h - eps, creditCurveNode);
final double up = pricer.annuity(cds, yieldCurve, ccUp, PriceType.DIRTY); // clean or dirty has no effect on sensitivity
final double down = pricer.annuity(cds, yieldCurve, ccDown, PriceType.DIRTY);
return (up - down) / 2 / eps;
}
private double fdProtectionLegSense(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve) {
final int n = creditCurve.getNumberOfKnots();
final double h = 0.5 * (creditCurve.getZeroRateAtIndex(0) + creditCurve.getZeroRateAtIndex(n - 1));
final double eps = 1e-4 * h;
final double[] rUp = creditCurve.getKnotZeroRates();
final double[] rDown = creditCurve.getKnotZeroRates();
for (int i = 0; i < n; i++) {
rUp[i] += eps;
rDown[i] -= eps;
}
final double up = PRICER.protectionLeg(cds, yieldCurve, creditCurve.withRates(rUp));
final double down = PRICER.protectionLeg(cds, yieldCurve, creditCurve.withRates(rDown));
return (up - down) / 2 / eps;
}
private double fdProtectionLegSense(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final int creditCurveNode) {
final double h = creditCurve.getZeroRateAtIndex(creditCurveNode);
final double eps = 1e-4 * Math.max(1e-3, h);
final ISDACompliantCreditCurve ccUp = creditCurve.withRate(h + eps, creditCurveNode);
final ISDACompliantCreditCurve ccDown = creditCurve.withRate(h - eps, creditCurveNode);
final double up = PRICER.protectionLeg(cds, yieldCurve, ccUp);
final double down = PRICER.protectionLeg(cds, yieldCurve, ccDown);
return (up - down) / 2 / eps;
}
private double fdProtectionLegYieldSense(final AnalyticCDSPricer pricer, final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve,
final int yieldCurveNode) {
final double r = yieldCurve.getZeroRateAtIndex(yieldCurveNode);
final double eps = 1e-4 * Math.max(1e-3, r);
final ISDACompliantYieldCurve yUp = yieldCurve.withRate(r + eps, yieldCurveNode);
final ISDACompliantYieldCurve yDown = yieldCurve.withRate(r - eps, yieldCurveNode);
final double up = pricer.protectionLeg(cds, yUp, creditCurve);
final double down = pricer.protectionLeg(cds, yDown, creditCurve);
return (up - down) / 2 / eps;
}
private double fdPremiumLegYieldSense(final AnalyticCDSPricer pricer, final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve,
final int yieldCurveNode) {
final double r = yieldCurve.getZeroRateAtIndex(yieldCurveNode);
final double eps = 1e-4 * Math.max(1e-3, r);
final ISDACompliantYieldCurve yUp = yieldCurve.withRate(r + eps, yieldCurveNode);
final ISDACompliantYieldCurve yDown = yieldCurve.withRate(r - eps, yieldCurveNode);
final double up = pricer.annuity(cds, yUp, creditCurve, PriceType.CLEAN);
final double down = pricer.annuity(cds, yDown, creditCurve, PriceType.CLEAN);
return (up - down) / 2 / eps;
}
private double fdPVYieldSense(final AnalyticCDSPricer pricer, final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve, final ISDACompliantCreditCurve creditCurve, final double coupon,
final int yieldCurveNode) {
final double r = yieldCurve.getZeroRateAtIndex(yieldCurveNode);
final double eps = 1e-4 * Math.max(1e-3, r);
final ISDACompliantYieldCurve yUp = yieldCurve.withRate(r + eps, yieldCurveNode);
final ISDACompliantYieldCurve yDown = yieldCurve.withRate(r - eps, yieldCurveNode);
final double up = pricer.pv(cds, yUp, creditCurve, coupon, PriceType.DIRTY);
final double down = pricer.pv(cds, yDown, creditCurve, coupon, PriceType.DIRTY);
return (up - down) / 2 / eps;
}
}