/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.interestrate.inflation.provider;
import static org.testng.AssertJUnit.assertEquals;
import java.util.LinkedHashMap;
import org.testng.annotations.Test;
import org.threeten.bp.Period;
import org.threeten.bp.ZonedDateTime;
import com.opengamma.analytics.financial.instrument.index.GeneratorAttributeIR;
import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedInflationMaster;
import com.opengamma.analytics.financial.instrument.index.GeneratorSwapFixedInflationZeroCoupon;
import com.opengamma.analytics.financial.instrument.index.IndexON;
import com.opengamma.analytics.financial.instrument.index.IndexPrice;
import com.opengamma.analytics.financial.instrument.swap.SwapFixedInflationZeroCouponDefinition;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.datasets.StandardDataSetsInflationUSD;
import com.opengamma.analytics.financial.interestrate.datasets.StandardTimeSeriesInflationDataSets;
import com.opengamma.analytics.financial.provider.calculator.inflation.MarketQuoteInflationSensitivityBlockCalculator;
import com.opengamma.analytics.financial.provider.calculator.inflation.ParRateInflationDiscountingCalculator;
import com.opengamma.analytics.financial.provider.calculator.inflation.PresentValueCurveSensitivityDiscountingInflationCalculator;
import com.opengamma.analytics.financial.provider.calculator.inflation.PresentValueDiscountingInflationCalculator;
import com.opengamma.analytics.financial.provider.curve.CurveBuildingBlockBundle;
import com.opengamma.analytics.financial.provider.description.inflation.InflationProviderDiscount;
import com.opengamma.analytics.financial.provider.description.inflation.ParameterInflationProviderInterface;
import com.opengamma.analytics.financial.provider.sensitivity.inflation.ParameterSensitivityInflationParameterCalculator;
import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MultipleCurrencyParameterSensitivity;
import com.opengamma.analytics.financial.util.AssertSensitivityObjects;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.timeseries.precise.zdt.ZonedDateTimeDoubleTimeSeries;
import com.opengamma.util.money.Currency;
import com.opengamma.util.money.MultipleCurrencyAmount;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.tuple.ObjectsPair;
import com.opengamma.util.tuple.Pair;
import com.opengamma.util.tuple.Pairs;
/**
* End-to-end tests for inflation curve calibration and pricing of inflation zero-coupon swaps.
*/
@Test(groups = TestGroup.UNIT)
public class SwapZeroCouponInflationDiscountingUsdE2ETest {
private static final ZonedDateTime CALIBRATION_DATE = DateUtils.getUTCDate(2014, 10, 9);
private static final Currency USD = Currency.USD;
/** Calculators **/
private static final PresentValueDiscountingInflationCalculator PVDIC =
PresentValueDiscountingInflationCalculator.getInstance();
private static final ParRateInflationDiscountingCalculator PRIC =
ParRateInflationDiscountingCalculator.getInstance();
private static final PresentValueCurveSensitivityDiscountingInflationCalculator PVCSDIC =
PresentValueCurveSensitivityDiscountingInflationCalculator.getInstance();
private static final ParameterSensitivityInflationParameterCalculator<ParameterInflationProviderInterface> PSC =
new ParameterSensitivityInflationParameterCalculator<>(PVCSDIC);
private static final MarketQuoteInflationSensitivityBlockCalculator<ParameterInflationProviderInterface> MQSBC =
new MarketQuoteInflationSensitivityBlockCalculator<>(PSC);
/** Curves */
private static final Pair<InflationProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_INFL_1_PAIR =
StandardDataSetsInflationUSD.getCurvesUsdOisUsCpi(CALIBRATION_DATE);
private static final InflationProviderDiscount MULTICURVE_INFL_1 = MULTICURVE_INFL_1_PAIR.getFirst();
private static final CurveBuildingBlockBundle BLOCK_INFL_1 = MULTICURVE_INFL_1_PAIR.getSecond();
private static final Pair<InflationProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_INFL_2_PAIR =
StandardDataSetsInflationUSD.getCurvesUsdOisUsCpi2(CALIBRATION_DATE);
private static final InflationProviderDiscount MULTICURVE_INFL_2 = MULTICURVE_INFL_2_PAIR.getFirst();
private static final CurveBuildingBlockBundle BLOCK_INFL_2 = MULTICURVE_INFL_2_PAIR.getSecond();
private static final Pair<InflationProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_INFL_3_PAIR =
StandardDataSetsInflationUSD.getCurvesUsdOisUsCpi3(CALIBRATION_DATE);
private static final InflationProviderDiscount MULTICURVE_INFL_3 = MULTICURVE_INFL_3_PAIR.getFirst();
private static final CurveBuildingBlockBundle BLOCK_INFL_3 = MULTICURVE_INFL_3_PAIR.getSecond();
private static final Pair<InflationProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_INFL_4_PAIR =
StandardDataSetsInflationUSD.getCurvesUsdOisUsCpiSeasonality(CALIBRATION_DATE);
private static final InflationProviderDiscount MULTICURVE_INFL_4 = MULTICURVE_INFL_4_PAIR.getFirst();
private static final Pair<InflationProviderDiscount, CurveBuildingBlockBundle> MULTICURVE_INFL_5_PAIR =
StandardDataSetsInflationUSD.getCurvesUsdOisUsCpiCurrent(CALIBRATION_DATE);
private static final InflationProviderDiscount MULTICURVE_INFL_5 = MULTICURVE_INFL_5_PAIR.getFirst();
private static final ZonedDateTimeDoubleTimeSeries HTS_CPI =
StandardTimeSeriesInflationDataSets.timeSeriesUsCpi(CALIBRATION_DATE);
private static final GeneratorSwapFixedInflationZeroCoupon GENERATOR_ZCINFLATION_US =
GeneratorSwapFixedInflationMaster.getInstance().getGenerator("USCPI");
private static final IndexPrice US_CPI = GENERATOR_ZCINFLATION_US.getIndexPrice();
private static final double NOTIONAL = 10_000_000;
/** Zero-coupon Inflation US (linear interpolation of Price Index). 2Y node. */
private static final ZonedDateTime ACCRUAL_START_DATE_1 = DateUtils.getUTCDate(2014, 10, 9);
private static final GeneratorAttributeIR ZCI_1_ATTR = new GeneratorAttributeIR(Period.ofYears(2));
private static final double RATE_FIXED_1 = 0.0200;
private static final SwapFixedInflationZeroCouponDefinition ZCI_1_DEFINITION =
GENERATOR_ZCINFLATION_US.generateInstrument(ACCRUAL_START_DATE_1, RATE_FIXED_1, NOTIONAL, ZCI_1_ATTR);
private static final InstrumentDerivative ZCI_1 = ZCI_1_DEFINITION.toDerivative(CALIBRATION_DATE,
new ZonedDateTimeDoubleTimeSeries[] {HTS_CPI, HTS_CPI});
/** Zero-coupon Inflation US (linear interpolation of Price Index). 5Y aged. */
private static final ZonedDateTime ACCRUAL_START_DATE_2 = DateUtils.getUTCDate(2014, 1, 8);
private static final GeneratorAttributeIR ZCI_2_ATTR = new GeneratorAttributeIR(Period.ofYears(5));
private static final double RATE_FIXED_2 = 0.0100;
private static final SwapFixedInflationZeroCouponDefinition ZCI_2_DEFINITION =
GENERATOR_ZCINFLATION_US.generateInstrument(ACCRUAL_START_DATE_2, RATE_FIXED_2, NOTIONAL, ZCI_2_ATTR);
private static final InstrumentDerivative ZCI_2 = ZCI_2_DEFINITION.toDerivative(CALIBRATION_DATE,
new ZonedDateTimeDoubleTimeSeries[] {HTS_CPI, HTS_CPI});
private static final double TOLERANCE_PV = 1.0E-3;
private static final double TOLERANCE_RATE = 1.0E-8;
private static final double TOLERANCE_PV_DELTA = 1.0E-1;
private static final double BP1 = 1.0E-4;
@Test
public void presentValueNode() {
double pvExpectd = 0.0000;
MultipleCurrencyAmount pv1 = ZCI_1.accept(PVDIC, MULTICURVE_INFL_1);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: present value",
pvExpectd, pv1.getAmount(USD), TOLERANCE_PV);
MultipleCurrencyAmount pv2 = ZCI_1.accept(PVDIC, MULTICURVE_INFL_2);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: present value",
pv1.getAmount(USD), pv2.getAmount(USD), TOLERANCE_PV);
MultipleCurrencyAmount pv3 = ZCI_1.accept(PVDIC, MULTICURVE_INFL_3);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: present value",
pv1.getAmount(USD), pv3.getAmount(USD), TOLERANCE_PV);
}
@Test
public void presentValueAged() {
double pvExpectd = 557423.3817;
MultipleCurrencyAmount pv1 = ZCI_2.accept(PVDIC, MULTICURVE_INFL_1);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: present value",
pvExpectd, pv1.getAmount(USD), TOLERANCE_PV);
MultipleCurrencyAmount pv2 = ZCI_2.accept(PVDIC, MULTICURVE_INFL_2);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: present value",
pv1.getAmount(USD), pv2.getAmount(USD), TOLERANCE_PV);
MultipleCurrencyAmount pv3 = ZCI_2.accept(PVDIC, MULTICURVE_INFL_3);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: present value",
pv1.getAmount(USD), pv3.getAmount(USD), TOLERANCE_PV);
}
@Test
public void parRateNode() {
double prExpectd = 0.0200;
Double pr1 = ZCI_1.accept(PRIC, MULTICURVE_INFL_1);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: par rate",
prExpectd, pr1, TOLERANCE_RATE);
Double pr2 = ZCI_1.accept(PRIC, MULTICURVE_INFL_2);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: par rate",
pr1, pr2, TOLERANCE_RATE);
Double pr3 = ZCI_1.accept(PRIC, MULTICURVE_INFL_3);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: par rate",
pr1, pr3, TOLERANCE_RATE);
}
@Test
public void parRateAged() {
double pvExpectd = 0.02104793312426101;
Double pv1 = ZCI_2.accept(PRIC, MULTICURVE_INFL_1);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: par rate",
pvExpectd, pv1, TOLERANCE_RATE);
Double pv2 = ZCI_2.accept(PRIC, MULTICURVE_INFL_2);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: par rate",
pv1, pv2, TOLERANCE_RATE);
Double pv3 = ZCI_2.accept(PRIC, MULTICURVE_INFL_3);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: par rate",
pv1, pv3, TOLERANCE_RATE);
}
@Test
public void presentValueAgedSeasonality() {
double pvExpectd = 515419.8416;
MultipleCurrencyAmount pv1 = ZCI_2.accept(PVDIC, MULTICURVE_INFL_4);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: present value",
pvExpectd, pv1.getAmount(USD), TOLERANCE_PV);
}
@Test
public void presentValueAgedStart() {
double pvExpectd = 557421.1232;
MultipleCurrencyAmount pv1 = ZCI_2.accept(PVDIC, MULTICURVE_INFL_5);
assertEquals("SwapZeroCouponInflationUsdDiscountingE2ETest: present value",
pvExpectd, pv1.getAmount(USD), TOLERANCE_PV);
}
@Test
public void bucketedPv01Node() {
final double[] deltaDsc =
{0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,
0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000};
final double[] deltaCpi =
{0.0000,2026.9265,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,0.0000,
0.0000,0.0000,0.0000,0.0000,0.0000};
final LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> sensitivity = new LinkedHashMap<>();
sensitivity.put(ObjectsPair.of(MULTICURVE_INFL_1.getName(USD), USD), new DoubleMatrix1D(deltaDsc));
sensitivity.put(ObjectsPair.of(MULTICURVE_INFL_1.getName(US_CPI), USD), new DoubleMatrix1D(deltaCpi));
final MultipleCurrencyParameterSensitivity pvpsExpected = new MultipleCurrencyParameterSensitivity(sensitivity);
final MultipleCurrencyParameterSensitivity pvpsComputed1 =
MQSBC.fromInstrument(ZCI_1, MULTICURVE_INFL_1, BLOCK_INFL_1).multipliedBy(BP1);
AssertSensitivityObjects.assertEquals("Zero-coupon Inflation swap: Bucketed PV01",
pvpsExpected, pvpsComputed1, TOLERANCE_PV_DELTA);
final MultipleCurrencyParameterSensitivity pvpsComputed2 =
MQSBC.fromInstrument(ZCI_1, MULTICURVE_INFL_2, BLOCK_INFL_2).multipliedBy(BP1);
AssertSensitivityObjects.assertEquals("Zero-coupon Inflation swap: Bucketed PV01",
pvpsComputed1, pvpsComputed2, TOLERANCE_PV_DELTA);
final MultipleCurrencyParameterSensitivity pvpsComputed3 =
MQSBC.fromInstrument(ZCI_1, MULTICURVE_INFL_3, BLOCK_INFL_3).multipliedBy(BP1);
AssertSensitivityObjects.assertEquals("Zero-coupon Inflation swap: Bucketed PV01",
pvpsComputed1, pvpsComputed3, TOLERANCE_PV_DELTA);
}
@Test
public void bucketedPv01Aged() {
final double[] deltaDsc =
{-0.1561,-0.6246,0.0000,0.0000,0.0000,0.0003,-0.0144,0.7254,1.4424,3.1991,
-186.7859,-58.1989,0.0000,0.0000,0.0000,0.0000,0.0000};
final double[] deltaCpi =
{-0.1751,6.2301,-156.0361,3475.9913,1061.5416,0.0000,0.0000,0.0000,0.0000,0.0000,
0.0000,0.0000,0.0000,0.0000,0.0000};
final LinkedHashMap<Pair<String, Currency>, DoubleMatrix1D> sensitivity = new LinkedHashMap<>();
sensitivity.put(ObjectsPair.of(MULTICURVE_INFL_1.getName(USD), USD), new DoubleMatrix1D(deltaDsc));
sensitivity.put(ObjectsPair.of(MULTICURVE_INFL_1.getName(US_CPI), USD), new DoubleMatrix1D(deltaCpi));
MultipleCurrencyParameterSensitivity pvpsExpected = new MultipleCurrencyParameterSensitivity(sensitivity);
MultipleCurrencyParameterSensitivity pvpsComputed1 =
MQSBC.fromInstrument(ZCI_2, MULTICURVE_INFL_1, BLOCK_INFL_1).multipliedBy(BP1);
AssertSensitivityObjects.assertEquals("Zero-coupon Inflation swap: Bucketed PV01",
pvpsExpected, pvpsComputed1, TOLERANCE_PV_DELTA);
final MultipleCurrencyParameterSensitivity pvpsComputed2 =
MQSBC.fromInstrument(ZCI_2, MULTICURVE_INFL_2, BLOCK_INFL_2).multipliedBy(BP1);
AssertSensitivityObjects.assertEquals("Zero-coupon Inflation swap: Bucketed PV01",
pvpsComputed1, pvpsComputed2, TOLERANCE_PV_DELTA);
final MultipleCurrencyParameterSensitivity pvpsComputed3 =
MQSBC.fromInstrument(ZCI_2, MULTICURVE_INFL_3, BLOCK_INFL_3).multipliedBy(BP1);
AssertSensitivityObjects.assertEquals("Zero-coupon Inflation swap: Bucketed PV01",
pvpsComputed1, pvpsComputed3, TOLERANCE_PV_DELTA);
}
@Test
public void bucketedZeroRatePv01Node() {
IndexON index = StandardDataSetsInflationUSD.getIndexON();
double[] expectedOIS = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0 };
double[] expected1 = new double[] {0.2391924970613193, 3.9334293371931075, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0 };
double[] expected2 = new double[] {0.2391924970613193, 3.9334293371931075, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0 };
double[] expected3 = new double[] {0.2391924970613193, 3.9334293371931075, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0 };
MultipleCurrencyParameterSensitivity computed1 =
PSC.calculateSensitivity(ZCI_1, MULTICURVE_INFL_1).multipliedBy(BP1);
MultipleCurrencyParameterSensitivity computed2 =
PSC.calculateSensitivity(ZCI_1, MULTICURVE_INFL_2).multipliedBy(BP1);
MultipleCurrencyParameterSensitivity computed3 =
PSC.calculateSensitivity(ZCI_1, MULTICURVE_INFL_3).multipliedBy(BP1);
assertArrayRelative("bucketedZeroRatePv01Node", expected1,
computed1.getSensitivity(Pairs.of(MULTICURVE_INFL_1.getName(US_CPI), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Node", expectedOIS,
computed1.getSensitivity(Pairs.of(MULTICURVE_INFL_1.getName(index), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Node", expected2,
computed2.getSensitivity(Pairs.of(MULTICURVE_INFL_2.getName(US_CPI), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Node", expectedOIS,
computed2.getSensitivity(Pairs.of(MULTICURVE_INFL_2.getName(index), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Node", expected3,
computed3.getSensitivity(Pairs.of(MULTICURVE_INFL_3.getName(US_CPI), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Node", expectedOIS,
computed3.getSensitivity(Pairs.of(MULTICURVE_INFL_3.getName(index), USD)).getData(), TOLERANCE_PV);
}
@Test
public void bucketedZeroRatePv01Aged() {
IndexON index = StandardDataSetsInflationUSD.getIndexON();
double[] expectedPr1 = new double[] {0.0, 0.0, 0.0, 3.2884348703648847, 0.7763062873998817, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
double[] expectedOn1 = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -181.78857803005081,
-55.38361696256043, 0.0, 0.0, 0.0, 0.0, 0.0 };
double[] expectedPr2 = new double[] {0.0, 0.0, 0.0, 3.2884348703648847, 0.7763062873998817, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
double[] expectedOn2 = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -181.7885780300487,
-55.383616962559806, 0.0, 0.0, 0.0, 0.0, 0.0 };
double[] expectedPr3 = new double[] {0.0, 0.0, 0.0, 3.288434870364886, 0.776306287399882, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0 };
double[] expectedOn3 = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -181.7885780300488,
-55.38361696255983, 0.0, 0.0, 0.0, 0.0, 0.0 };
MultipleCurrencyParameterSensitivity computed1 =
PSC.calculateSensitivity(ZCI_2, MULTICURVE_INFL_1).multipliedBy(BP1);
MultipleCurrencyParameterSensitivity computed2 =
PSC.calculateSensitivity(ZCI_2, MULTICURVE_INFL_2).multipliedBy(BP1);
MultipleCurrencyParameterSensitivity computed3 =
PSC.calculateSensitivity(ZCI_2, MULTICURVE_INFL_3).multipliedBy(BP1);
assertArrayRelative("bucketedZeroRatePv01Aged", expectedPr1,
computed1.getSensitivity(Pairs.of(MULTICURVE_INFL_1.getName(US_CPI), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Aged", expectedOn1,
computed1.getSensitivity(Pairs.of(MULTICURVE_INFL_1.getName(index), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Aged", expectedPr2,
computed2.getSensitivity(Pairs.of(MULTICURVE_INFL_2.getName(US_CPI), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Aged", expectedOn2,
computed2.getSensitivity(Pairs.of(MULTICURVE_INFL_2.getName(index), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Aged", expectedPr3,
computed3.getSensitivity(Pairs.of(MULTICURVE_INFL_3.getName(US_CPI), USD)).getData(), TOLERANCE_PV);
assertArrayRelative("bucketedZeroRatePv01Aged", expectedOn3,
computed3.getSensitivity(Pairs.of(MULTICURVE_INFL_3.getName(index), USD)).getData(), TOLERANCE_PV);
}
private static void assertArrayRelative(String message, double[] expected, double[] obtained, double relativeTol) {
int nData = expected.length;
assertEquals(message, nData, obtained.length);
for (int i = 0; i < nData; ++i) {
assertRelative(message, expected[i], obtained[i], relativeTol);
}
}
private static void assertRelative(String message, double expected, double obtained, double relativeTol) {
double ref = Math.max(Math.abs(expected), 1.0);
assertEquals(message, expected, obtained, ref * relativeTol);
}
}