/** * Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.pricer.capfloor; import static com.opengamma.strata.basics.date.DayCounts.ACT_365F; import static com.opengamma.strata.basics.date.DayCounts.ACT_ACT_ISDA; import static com.opengamma.strata.basics.index.IborIndices.GBP_LIBOR_3M; import static com.opengamma.strata.basics.index.IborIndices.USD_LIBOR_3M; import static com.opengamma.strata.collect.TestHelper.assertSerialization; import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg; import static com.opengamma.strata.collect.TestHelper.coverBeanEquals; import static com.opengamma.strata.collect.TestHelper.coverImmutableBean; import static com.opengamma.strata.market.curve.interpolator.CurveInterpolators.DOUBLE_QUADRATIC; import static com.opengamma.strata.market.curve.interpolator.CurveInterpolators.LINEAR; import static com.opengamma.strata.market.curve.interpolator.CurveInterpolators.STEP_UPPER; import static com.opengamma.strata.market.curve.interpolator.CurveInterpolators.TIME_SQUARE; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import java.time.LocalDate; import java.time.Period; import java.util.ArrayList; import java.util.List; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; import com.opengamma.strata.basics.date.BusinessDayAdjustment; import com.opengamma.strata.basics.date.BusinessDayConventions; import com.opengamma.strata.basics.date.DaysAdjustment; import com.opengamma.strata.basics.schedule.Frequency; import com.opengamma.strata.basics.schedule.PeriodicSchedule; import com.opengamma.strata.basics.schedule.RollConventions; import com.opengamma.strata.basics.schedule.StubConvention; import com.opengamma.strata.basics.value.ValueSchedule; import com.opengamma.strata.collect.array.DoubleArray; import com.opengamma.strata.collect.array.DoubleMatrix; import com.opengamma.strata.market.ValueType; import com.opengamma.strata.market.curve.ConstantCurve; import com.opengamma.strata.market.option.SimpleStrike; import com.opengamma.strata.market.surface.SurfaceMetadata; import com.opengamma.strata.market.surface.Surfaces; import com.opengamma.strata.market.surface.interpolator.GridSurfaceInterpolator; import com.opengamma.strata.pricer.common.GenericVolatilitySurfacePeriodParameterMetadata; import com.opengamma.strata.pricer.option.RawOptionData; import com.opengamma.strata.product.capfloor.IborCapFloorLeg; import com.opengamma.strata.product.common.PayReceive; import com.opengamma.strata.product.swap.IborRateCalculation; /** * Test {@link SurfaceIborCapletFloorletVolatilityBootstrapDefinition}. */ @Test public class SurfaceIborCapletFloorletVolatilityBootstrapDefinitionTest { private static final IborCapletFloorletVolatilitiesName NAME = IborCapletFloorletVolatilitiesName.of("TestName"); private static final ConstantCurve SHIFT = ConstantCurve.of("Black shift", 0.02); public void test_of(){ SurfaceIborCapletFloorletVolatilityBootstrapDefinition test = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, STEP_UPPER, DOUBLE_QUADRATIC); assertEquals(test.getDayCount(), ACT_ACT_ISDA); assertEquals(test.getIndex(), USD_LIBOR_3M); assertEquals(test.getInterpolator(), GridSurfaceInterpolator.of(STEP_UPPER, DOUBLE_QUADRATIC)); assertEquals(test.getName(), NAME); assertFalse(test.getShiftCurve().isPresent()); } public void test_of_surface() { GridSurfaceInterpolator interp = GridSurfaceInterpolator.of(LINEAR, LINEAR); SurfaceIborCapletFloorletVolatilityBootstrapDefinition test = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, interp); assertEquals(test.getDayCount(), ACT_ACT_ISDA); assertEquals(test.getIndex(), USD_LIBOR_3M); assertEquals(test.getInterpolator(), interp); assertEquals(test.getName(), NAME); assertFalse(test.getShiftCurve().isPresent()); } public void test_of_shift() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition test = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, STEP_UPPER, DOUBLE_QUADRATIC, SHIFT); assertEquals(test.getDayCount(), ACT_ACT_ISDA); assertEquals(test.getIndex(), USD_LIBOR_3M); assertEquals(test.getInterpolator(), GridSurfaceInterpolator.of(STEP_UPPER, DOUBLE_QUADRATIC)); assertEquals(test.getName(), NAME); assertEquals(test.getShiftCurve().get(), SHIFT); } public void test_of_surface_shift() { GridSurfaceInterpolator interp = GridSurfaceInterpolator.of(LINEAR, LINEAR); SurfaceIborCapletFloorletVolatilityBootstrapDefinition test = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of(NAME, USD_LIBOR_3M, ACT_ACT_ISDA, interp, SHIFT); assertEquals(test.getDayCount(), ACT_ACT_ISDA); assertEquals(test.getIndex(), USD_LIBOR_3M); assertEquals(test.getInterpolator(), interp); assertEquals(test.getName(), NAME); assertEquals(test.getShiftCurve().get(), SHIFT); } public void test_createCap() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, TIME_SQUARE, DOUBLE_QUADRATIC); LocalDate startDate = LocalDate.of(2012, 4, 20); LocalDate endDate = LocalDate.of(2017, 4, 20); double strike = 0.01; IborCapFloorLeg expected = IborCapFloorLeg.builder() .calculation(IborRateCalculation.of(USD_LIBOR_3M)) .capSchedule(ValueSchedule.of(strike)) .currency(USD_LIBOR_3M.getCurrency()) .notional(ValueSchedule.ALWAYS_1) .paymentDateOffset(DaysAdjustment.NONE) .paymentSchedule( PeriodicSchedule.of( startDate, endDate, Frequency.of(USD_LIBOR_3M.getTenor().getPeriod()), BusinessDayAdjustment.of(BusinessDayConventions.MODIFIED_FOLLOWING, USD_LIBOR_3M.getFixingCalendar()), StubConvention.NONE, RollConventions.NONE)) .payReceive(PayReceive.RECEIVE) .build(); IborCapFloorLeg computed = base.createCap(startDate, endDate, strike); assertEquals(computed, expected); } public void test_createMetadata_normal() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); RawOptionData capData = RawOptionData.of( ImmutableList.of(Period.ofYears(1), Period.ofYears(5)), DoubleArray.of(0.005, 0.01, 0.015), ValueType.STRIKE, DoubleMatrix.copyOf(new double[][] {{0.15, 0.12, 0.13}, {0.1, Double.NaN, 0.09}}), ValueType.NORMAL_VOLATILITY); List<GenericVolatilitySurfacePeriodParameterMetadata> list = new ArrayList<>(); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.005))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.01))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.015))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.005))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.015))); SurfaceMetadata expected = Surfaces.normalVolatilityByExpiryStrike( NAME.getName(), ACT_ACT_ISDA).withParameterMetadata(list); SurfaceMetadata computed = base.createMetadata(capData); assertEquals(computed, expected); } public void test_createMetadata_black() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); RawOptionData capData = RawOptionData.of( ImmutableList.of(Period.ofYears(1), Period.ofYears(5)), DoubleArray.of(0.005, 0.01, 0.015), ValueType.STRIKE, DoubleMatrix.copyOf(new double[][] {{0.15, 0.12, 0.13}, {0.1, 0.08, 0.09}}), ValueType.BLACK_VOLATILITY); List<GenericVolatilitySurfacePeriodParameterMetadata> list = new ArrayList<>(); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.005))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.01))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(1), SimpleStrike.of(0.015))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.005))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.01))); list.add(GenericVolatilitySurfacePeriodParameterMetadata.of(Period.ofYears(5), SimpleStrike.of(0.015))); SurfaceMetadata expected = Surfaces.blackVolatilityByExpiryStrike( NAME.getName(), ACT_ACT_ISDA).withParameterMetadata(list); SurfaceMetadata computed = base.createMetadata(capData); assertEquals(computed, expected); } //------------------------------------------------------------------------- public void test_of_wrongInterpolator() { assertThrowsIllegalArg(() -> SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, DOUBLE_QUADRATIC, DOUBLE_QUADRATIC)); } public void test_createMetadata_wrongValueType() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition base = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); RawOptionData capData = RawOptionData.of( ImmutableList.of(Period.ofYears(1), Period.ofYears(5)), DoubleArray.of(0.005, 0.01, 0.015), ValueType.STRIKE, DoubleMatrix.copyOf(new double[][] {{0.15, 0.12, 0.13}, {0.1, 0.08, 0.09}}), ValueType.PRICE); assertThrowsIllegalArg(() -> base.createMetadata(capData)); } //------------------------------------------------------------------------- public void coverage() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition test1 = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); coverImmutableBean(test1); SurfaceIborCapletFloorletVolatilityBootstrapDefinition test2 = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( IborCapletFloorletVolatilitiesName.of("other"), GBP_LIBOR_3M, ACT_365F, LINEAR, LINEAR, SHIFT); coverBeanEquals(test1, test2); } public void test_serialization() { SurfaceIborCapletFloorletVolatilityBootstrapDefinition test = SurfaceIborCapletFloorletVolatilityBootstrapDefinition.of( NAME, USD_LIBOR_3M, ACT_ACT_ISDA, LINEAR, DOUBLE_QUADRATIC); assertSerialization(test); } }