/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.credit;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Map;
import java.util.SortedMap;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.threeten.bp.LocalDate;
import org.threeten.bp.Period;
import com.google.common.collect.ImmutableSortedMap;
import com.opengamma.analytics.financial.credit.isdastandardmodel.ISDACompliantCreditCurve;
import com.opengamma.analytics.financial.credit.isdastandardmodel.StubType;
import com.opengamma.analytics.util.time.TimeCalculator;
import com.opengamma.core.holiday.HolidaySource;
import com.opengamma.core.link.ConventionLink;
import com.opengamma.core.region.RegionSource;
import com.opengamma.financial.analytics.isda.credit.CdsQuote;
import com.opengamma.financial.analytics.isda.credit.CreditCurveData;
import com.opengamma.financial.analytics.isda.credit.CreditCurveDataKey;
import com.opengamma.financial.analytics.isda.credit.ParSpreadQuote;
import com.opengamma.financial.convention.IsdaCreditCurveConvention;
import com.opengamma.financial.convention.businessday.BusinessDayConventions;
import com.opengamma.financial.convention.daycount.DayCounts;
import com.opengamma.sesame.Environment;
import com.opengamma.sesame.credit.curve.CreditCurveDataProviderFn;
import com.opengamma.util.money.Currency;
import com.opengamma.util.result.FailureStatus;
import com.opengamma.util.result.Result;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.time.Tenor;
/**
* Credit curve build test.
*
* Test data from /sesame-function/src/test/resources/credit/YC Test Data.xls
*
*/
@Test(groups = TestGroup.UNIT)
public class StandardIsdaCompliantCreditCurveFnTest {
private static final double DELTA = 10e-15;
private static final IsdaYieldCurve YIELD_CURVE =
IsdaYieldCurve.builder()
.calibratedCurve(CreditCurveCalibrationSampleData.createYieldCurve())
.curveData(CreditCurveCalibrationSampleData.createYieldCurveData())
.build();
private static final LocalDate VALUATION_DATE = LocalDate.of(2014, 3, 27);
private StandardIsdaCompliantCreditCurveFn _fn;
private Environment _env;
private final CreditCurveDataKey _goodKey = CreditCurveDataKey.builder().curveName("USD").currency(Currency.USD).build();
private final CreditCurveDataKey _badKey = CreditCurveDataKey.builder().curveName("GBP").currency(Currency.GBP).build();
private IsdaCompliantYieldCurveFn _yieldCurveFn;
private CreditCurveDataProviderFn _curveDataProviderFn;
private static final SortedMap<LocalDate, Double> EXPECTED;
static {
EXPECTED = ImmutableSortedMap.<LocalDate, Double> naturalOrder()
.put(LocalDate.of(2014, 6, 1), 0.997588273438233)
.put(LocalDate.of(2014, 7, 1), 0.996493957721021)
.put(LocalDate.of(2014, 8, 1), 0.995364425907840)
.put(LocalDate.of(2014, 9, 1), 0.994236174425670)
.put(LocalDate.of(2014, 10, 1), 0.993145535831308)
.put(LocalDate.of(2014, 11, 1), 0.992019799474205)
.put(LocalDate.of(2014, 12, 1), 0.990931592157365)
.put(LocalDate.of(2015, 1, 1), 0.989808365318550)
.put(LocalDate.of(2015, 2, 1), 0.988686411664022)
.put(LocalDate.of(2015, 3, 1), 0.987674127298215)
.put(LocalDate.of(2015, 4, 1), 0.986554592815145)
.build();
}
@BeforeMethod
public void beforeMethod() {
_env = mock(Environment.class);
when(_env.getValuationDate()).thenReturn(VALUATION_DATE);
_yieldCurveFn = mock(IsdaCompliantYieldCurveFn.class);
when(_yieldCurveFn.buildIsdaCompliantCurve(_env, Currency.USD)).thenReturn(Result.success(YIELD_CURVE));
when(_yieldCurveFn.buildIsdaCompliantCurve(_env, Currency.USD)).thenReturn(Result.success(YIELD_CURVE));
_curveDataProviderFn = mock(CreditCurveDataProviderFn.class);
HolidaySource holidaySource = mock(HolidaySource.class);
RegionSource regionSource = mock(RegionSource.class);
_fn = new StandardIsdaCompliantCreditCurveFn(_yieldCurveFn, _curveDataProviderFn, holidaySource, regionSource);
IsdaCreditCurveConvention curveConvention = new IsdaCreditCurveConvention();
curveConvention.setAccrualDayCount(DayCounts.ACT_360);
curveConvention.setBusinessDayConvention(BusinessDayConventions.FOLLOWING);
curveConvention.setCashSettle(3);
curveConvention.setCouponInterval(Period.ofMonths(3));
curveConvention.setCurveDayCount(DayCounts.ACT_365);
curveConvention.setPayAccOnDefault(true);
curveConvention.setProtectFromStartOfDay(true);
curveConvention.setStepIn(1);
curveConvention.setStubType(StubType.FRONTSHORT);
ConventionLink<IsdaCreditCurveConvention> conventionLink = ConventionLink.resolved(curveConvention);
SortedMap<Tenor, CdsQuote> spreadData = ImmutableSortedMap.<Tenor, CdsQuote> naturalOrder()
.put(Tenor.FIVE_YEARS, ParSpreadQuote.from(0.007928))
.build();
CreditCurveData curveData = CreditCurveData.builder()
.curveConventionLink(conventionLink)
.recoveryRate(0.4)
.cdsQuotes(spreadData)
.build();
when(_curveDataProviderFn.retrieveCreditCurveData(_env, _goodKey)).thenReturn(Result.success(curveData));
}
@Test
public void testCurveBuild() {
//curve successfully bootstrapped
Result<IsdaCreditCurve> result = _fn.buildIsdaCompliantCreditCurve(_env, _goodKey);
assertTrue("Expected success result", result.isSuccess());
ISDACompliantCreditCurve curve = result.getValue().getCalibratedCurve();
for (Map.Entry<LocalDate, Double> entry : EXPECTED.entrySet()) {
double t = TimeCalculator.getTimeBetween(VALUATION_DATE, entry.getKey());
double discountFactor = curve.getDiscountFactor(t);
System.out.println(entry.getKey() + " " + discountFactor + " " + (discountFactor - entry.getValue()));
assertEquals(entry.getValue(), discountFactor, DELTA);
}
}
@Test
public void testMissingCreditCurveData() {
//credit curve data missing but yc present
when(_yieldCurveFn.buildIsdaCompliantCurve(_env, Currency.GBP)).thenReturn(Result.success(YIELD_CURVE));
when(_curveDataProviderFn.retrieveCreditCurveData(_env, _badKey))
.thenReturn(Result.<CreditCurveData> failure(FailureStatus.ERROR, "Error"));
Result<IsdaCreditCurve> result = _fn.buildIsdaCompliantCreditCurve(_env, _badKey);
assertFalse("Expected failure result", result.isSuccess());
}
@Test
public void testMissingYieldCurveData() {
//yc missing but credit curve data present
when(_yieldCurveFn.buildIsdaCompliantCurve(_env, Currency.GBP))
.thenReturn(Result.<IsdaYieldCurve> failure(FailureStatus.ERROR, "Error"));
when(_curveDataProviderFn.retrieveCreditCurveData(_env, _badKey))
.thenReturn(Result.success(mock(CreditCurveData.class)));
Result<IsdaCreditCurve> result = _fn.buildIsdaCompliantCreditCurve(_env, _badKey);
assertFalse("Expected failure result", result.isSuccess());
}
}