/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.market.curve; import static com.opengamma.strata.collect.TestHelper.coverBeanEquals; import static com.opengamma.strata.collect.TestHelper.coverImmutableBean; import static com.opengamma.strata.collect.TestHelper.date; import static org.assertj.core.api.Assertions.assertThat; import java.util.List; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; import com.opengamma.strata.basics.ReferenceData; import com.opengamma.strata.basics.date.DayCounts; import com.opengamma.strata.basics.date.Tenor; import com.opengamma.strata.collect.array.DoubleArray; import com.opengamma.strata.data.scenario.MarketDataBox; import com.opengamma.strata.market.ShiftType; import com.opengamma.strata.market.curve.interpolator.CurveInterpolator; import com.opengamma.strata.market.curve.interpolator.CurveInterpolators; import com.opengamma.strata.market.param.LabelDateParameterMetadata; /** * Test {@link CurvePointShifts}. */ @Test public class CurvePointShiftsTest { private static final ReferenceData REF_DATA = ReferenceData.standard(); private static final String TNR_1W = "1W"; private static final String TNR_1M = "1M"; private static final String TNR_3M = "3M"; private static final String TNR_6M = "6M"; private static final CurveInterpolator INTERPOLATOR = CurveInterpolators.LOG_LINEAR; public void absolute() { List<LabelDateParameterMetadata> nodeMetadata = ImmutableList.of( LabelDateParameterMetadata.of(date(2011, 3, 8), TNR_1M), LabelDateParameterMetadata.of(date(2011, 5, 8), TNR_3M), LabelDateParameterMetadata.of(date(2011, 8, 8), TNR_6M)); // This should create 4 scenarios. Scenario zero has no shifts and scenario 3 doesn't have shifts on all nodes CurvePointShifts shift = CurvePointShifts.builder(ShiftType.ABSOLUTE) .addShift(1, TNR_1W, 0.1) // Tenor not in the curve, should be ignored .addShift(1, TNR_1M, 0.2) .addShift(1, TNR_3M, 0.3) .addShift(2, TNR_1M, 0.4) .addShift(2, TNR_3M, 0.5) .addShift(2, TNR_6M, 0.6) .addShift(3, TNR_3M, 0.7) .build(); Curve curve = InterpolatedNodalCurve.of( Curves.zeroRates(CurveName.of("curve"), DayCounts.ACT_365F, nodeMetadata), DoubleArray.of(1, 2, 3), DoubleArray.of(5, 6, 7), INTERPOLATOR); MarketDataBox<Curve> shiftedCurveBox = shift.applyTo(MarketDataBox.ofSingleValue(curve), REF_DATA); Curve scenario1Curve = InterpolatedNodalCurve.of( Curves.zeroRates(CurveName.of("curve"), DayCounts.ACT_365F, nodeMetadata), DoubleArray.of(1, 2, 3), DoubleArray.of(5.2, 6.3, 7), INTERPOLATOR); Curve scenario2Curve = InterpolatedNodalCurve.of( Curves.zeroRates(CurveName.of("curve"), DayCounts.ACT_365F, nodeMetadata), DoubleArray.of(1, 2, 3), DoubleArray.of(5.4, 6.5, 7.6), INTERPOLATOR); Curve scenario3Curve = InterpolatedNodalCurve.of( Curves.zeroRates(CurveName.of("curve"), DayCounts.ACT_365F, nodeMetadata), DoubleArray.of(1, 2, 3), DoubleArray.of(5, 6.7, 7), INTERPOLATOR); // Scenario zero has no perturbations so the expected curve is the same as the input List<Curve> expectedCurves = ImmutableList.of(curve, scenario1Curve, scenario2Curve, scenario3Curve); for (int scenarioIndex = 0; scenarioIndex < 4; scenarioIndex++) { // Check every point from 0 to 4 in steps of 0.1 is the same on the bumped curve and the expected curve for (int xIndex = 0; xIndex <= 40; xIndex++) { double xValue = xIndex * 0.1; Curve expectedCurve = expectedCurves.get(scenarioIndex); Curve shiftedCurve = shiftedCurveBox.getValue(scenarioIndex); double shiftedY = shiftedCurve.yValue(xValue); double expectedY = expectedCurve.yValue(xValue); assertThat(shiftedY) .overridingErrorMessage( "Curve differed in scenario %d at x value %f, expected %f, actual %f", scenarioIndex, xValue, expectedY, shiftedY) .isEqualTo(expectedY); } } } public void relative() { List<LabelDateParameterMetadata> nodeMetadata = ImmutableList.of( LabelDateParameterMetadata.of(date(2011, 3, 8), TNR_1M), LabelDateParameterMetadata.of(date(2011, 5, 8), TNR_3M), LabelDateParameterMetadata.of(date(2011, 8, 8), TNR_6M)); // This should create 4 scenarios. Scenario zero has no shifts and scenario 3 doesn't have shifts on all nodes CurvePointShifts shift = CurvePointShifts.builder(ShiftType.RELATIVE) .addShift(1, TNR_1W, 0.1) // Tenor not in the curve, should be ignored .addShift(1, TNR_1M, 0.2) .addShift(1, TNR_3M, 0.3) .addShift(2, TNR_1M, 0.4) .addShift(2, TNR_3M, 0.5) .addShift(2, TNR_6M, 0.6) .addShift(3, TNR_3M, 0.7) .build(); Curve curve = InterpolatedNodalCurve.of( Curves.zeroRates(CurveName.of("curve"), DayCounts.ACT_365F, nodeMetadata), DoubleArray.of(1, 2, 3), DoubleArray.of(5, 6, 7), INTERPOLATOR); MarketDataBox<Curve> shiftedCurveBox = shift.applyTo(MarketDataBox.ofSingleValue(curve), REF_DATA); Curve scenario1Curve = InterpolatedNodalCurve.of( Curves.zeroRates(CurveName.of("curve"), DayCounts.ACT_365F, nodeMetadata), DoubleArray.of(1, 2, 3), DoubleArray.of(6, 7.8, 7), INTERPOLATOR); Curve scenario2Curve = InterpolatedNodalCurve.of( Curves.zeroRates(CurveName.of("curve"), DayCounts.ACT_365F, nodeMetadata), DoubleArray.of(1, 2, 3), DoubleArray.of(7, 9, 11.2), INTERPOLATOR); Curve scenario3Curve = InterpolatedNodalCurve.of( Curves.zeroRates(CurveName.of("curve"), DayCounts.ACT_365F, nodeMetadata), DoubleArray.of(1, 2, 3), DoubleArray.of(5, 10.2, 7), INTERPOLATOR); // Scenario zero has no perturbations so the expected curve is the same as the input List<Curve> expectedCurves = ImmutableList.of(curve, scenario1Curve, scenario2Curve, scenario3Curve); for (int scenarioIndex = 0; scenarioIndex < 4; scenarioIndex++) { // Check every point from 0 to 4 in steps of 0.1 is the same on the bumped curve and the expected curve for (int xIndex = 0; xIndex <= 40; xIndex++) { double xValue = xIndex * 0.1; Curve expectedCurve = expectedCurves.get(scenarioIndex); Curve shiftedCurve = shiftedCurveBox.getValue(scenarioIndex); double shiftedY = shiftedCurve.yValue(xValue); double expectedY = expectedCurve.yValue(xValue); assertThat(shiftedY) .overridingErrorMessage( "Curve differed in scenario %d at x value %f, expected %f, actual %f", scenarioIndex, xValue, expectedY, shiftedY) .isEqualTo(expectedY); } } } //------------------------------------------------------------------------- public void coverage() { CurvePointShifts test = CurvePointShifts.builder(ShiftType.RELATIVE) .addShift(0, Tenor.TENOR_1W, 0.1) .addShift(0, Tenor.TENOR_1M, 0.2) .addShift(0, Tenor.TENOR_3M, 0.3) .build(); coverImmutableBean(test); CurvePointShifts test2 = CurvePointShifts.builder(ShiftType.ABSOLUTE) .addShift(0, Tenor.TENOR_1M, 0.2) .addShift(0, Tenor.TENOR_3M, 0.3) .build(); coverBeanEquals(test, test2); } }