/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.integration.marketdata.manipulator.dsl; import static com.opengamma.integration.marketdata.manipulator.dsl.SimulationUtils.volShift; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertTrue; import java.util.Arrays; import java.util.List; import java.util.Map; import org.testng.annotations.Test; import org.threeten.bp.Period; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.opengamma.analytics.financial.model.volatility.smile.fitting.sabr.SmileSurfaceDataBundle; import com.opengamma.analytics.financial.model.volatility.smile.fitting.sabr.StandardSmileSurfaceDataBundle; import com.opengamma.analytics.financial.model.volatility.surface.VolatilitySurface; import com.opengamma.analytics.math.interpolation.LinearInterpolator1D; import com.opengamma.analytics.math.surface.NodalDoublesSurface; import com.opengamma.engine.ComputationTargetSpecification; import com.opengamma.engine.function.FunctionExecutionContext; import com.opengamma.engine.function.FunctionParameters; import com.opengamma.engine.function.SimpleFunctionParameters; import com.opengamma.engine.function.StructureManipulationFunction; import com.opengamma.engine.marketdata.manipulator.DistinctMarketDataSelector; import com.opengamma.engine.marketdata.manipulator.ScenarioDefinition; import com.opengamma.engine.value.ValueProperties; import com.opengamma.engine.value.ValuePropertyNames; import com.opengamma.engine.value.ValueSpecification; import com.opengamma.integration.marketdata.manipulator.dsl.volsurface.VolatilitySurfaceIndexShifts; import com.opengamma.util.test.TestGroup; @Test(groups = TestGroup.INTEGRATION) public class SurfaceShiftTest { private static final double DELTA = 0.000001; @Test public void relative() { Scenario scenario = SimulationUtils.createScenarioFromDsl("src/test/groovy/SurfaceTest1.groovy", null); ScenarioDefinition definition = scenario.createDefinition(); assertEquals("relative surface test", definition.getName()); Map<DistinctMarketDataSelector, FunctionParameters> map = definition.getDefinitionMap(); FunctionParameters params = map.get(new VolatilitySurfaceSelector(null, null, null, null, null, null, null)); assertNotNull(params); Object value = ((SimpleFunctionParameters) params).getValue(StructureManipulationFunction.EXPECTED_PARAMETER_NAME); CompositeStructureManipulator manipulator = (CompositeStructureManipulator) value; List manipulators = manipulator.getManipulators(); assertEquals(1, manipulators.size()); List<VolatilitySurfaceShift> shifts = ImmutableList.of( new VolatilitySurfaceShift(Period.ofMonths(6), 1.5, 0.1), new VolatilitySurfaceShift(Period.ofYears(1), 2.5, 0.2)); VolatilitySurfaceShiftManipulator expected = VolatilitySurfaceShiftManipulator.create(ScenarioShiftType.RELATIVE, shifts); assertEquals(expected, manipulators.get(0)); } @Test public void absolute() { Scenario scenario = SimulationUtils.createScenarioFromDsl("src/test/groovy/SurfaceTest2.groovy", null); ScenarioDefinition definition = scenario.createDefinition(); assertEquals("absolute surface test", definition.getName()); Map<DistinctMarketDataSelector, FunctionParameters> map = definition.getDefinitionMap(); FunctionParameters params = map.get(new VolatilitySurfaceSelector(null, null, null, null, null, null, null)); assertNotNull(params); Object value = ((SimpleFunctionParameters) params).getValue(StructureManipulationFunction.EXPECTED_PARAMETER_NAME); CompositeStructureManipulator manipulator = (CompositeStructureManipulator) value; List manipulators = manipulator.getManipulators(); assertEquals(1, manipulators.size()); List<VolatilitySurfaceShift> shifts = ImmutableList.of( new VolatilitySurfaceShift(0.5, 0.6, 0.1), new VolatilitySurfaceShift(1.5, 0.7, 0.2)); VolatilitySurfaceShiftManipulator expected = VolatilitySurfaceShiftManipulator.create(ScenarioShiftType.ABSOLUTE, shifts); assertEquals(expected, manipulators.get(0)); } /** Tests creating index shifts from a Groovy script. */ @Test public void index() { Scenario scenario = SimulationUtils.createScenarioFromDsl("src/test/groovy/SurfaceTest3.groovy", null); ScenarioDefinition definition = scenario.createDefinition(); assertEquals("surface index shifts", definition.getName()); Map<DistinctMarketDataSelector, FunctionParameters> map = definition.getDefinitionMap(); FunctionParameters params = map.get(new VolatilitySurfaceSelector(null, null, null, null, null, null, null)); assertNotNull(params); Object value = ((SimpleFunctionParameters) params).getValue(StructureManipulationFunction.EXPECTED_PARAMETER_NAME); CompositeStructureManipulator manipulator = (CompositeStructureManipulator) value; List manipulators = manipulator.getManipulators(); assertEquals(1, manipulators.size()); List<Double> shifts = Lists.newArrayList(0d, 1e-4, 2e-4); VolatilitySurfaceIndexShifts expected = new VolatilitySurfaceIndexShifts(ScenarioShiftType.ABSOLUTE, shifts); assertEquals(expected, manipulators.get(0)); } /** Tests applying an absolute index shift to a surface. */ @Test public void indexSurfaceAbsolute() { NodalDoublesSurface surface = new NodalDoublesSurface(new double[]{1.1, 1.2, 1.2, 1.3, 1.3, 1.3}, new double[]{0.1, 0.1, 0.2, 0.1, 0.2, 0.3}, new double[]{1, 2, 3, 4, 5, 6}); List<Double> shiftList = Lists.newArrayList(0d, 0.1, 0.2); VolatilitySurfaceIndexShifts shifts = new VolatilitySurfaceIndexShifts(ScenarioShiftType.ABSOLUTE, shiftList); ValueProperties properties = ValueProperties.with(ValuePropertyNames.FUNCTION, "bar").get(); ValueSpecification spec = new ValueSpecification("foo", ComputationTargetSpecification.NULL, properties); VolatilitySurface shiftedSurface = shifts.execute(new VolatilitySurface(surface), spec, new FunctionExecutionContext()); assertEquals(1.0, shiftedSurface.getVolatility(1.1, 0.1), DELTA); assertEquals(2.1, shiftedSurface.getVolatility(1.2, 0.1), DELTA); assertEquals(3.1, shiftedSurface.getVolatility(1.2, 0.2), DELTA); assertEquals(4.2, shiftedSurface.getVolatility(1.3, 0.1), DELTA); assertEquals(5.2, shiftedSurface.getVolatility(1.3, 0.2), DELTA); assertEquals(6.2, shiftedSurface.getVolatility(1.3, 0.3), DELTA); } /** Tests applying a relative index shift to a surface. */ @Test public void indexSurfaceRelative() { NodalDoublesSurface surface = new NodalDoublesSurface(new double[]{1.1, 1.2, 1.2, 1.3, 1.3, 1.3}, new double[]{10, 10, 20, 10, 20, 30}, new double[]{1, 2, 3, 4, 5, 6}); List<Double> shiftList = Lists.newArrayList(0d, 0.1, 0.2); VolatilitySurfaceIndexShifts shifts = new VolatilitySurfaceIndexShifts(ScenarioShiftType.RELATIVE, shiftList); ValueProperties properties = ValueProperties.with(ValuePropertyNames.FUNCTION, "bar").get(); ValueSpecification spec = new ValueSpecification("foo", ComputationTargetSpecification.NULL, properties); VolatilitySurface shiftedSurface = shifts.execute(new VolatilitySurface(surface), spec, new FunctionExecutionContext()); assertEquals(1.0, shiftedSurface.getVolatility(1.1, 10), DELTA); assertEquals(2.2, shiftedSurface.getVolatility(1.2, 10), DELTA); assertEquals(3.3, shiftedSurface.getVolatility(1.2, 20), DELTA); assertEquals(4.8, shiftedSurface.getVolatility(1.3, 10), DELTA); assertEquals(6.0, shiftedSurface.getVolatility(1.3, 20), DELTA); assertEquals(7.2, shiftedSurface.getVolatility(1.3, 30), DELTA); } /** Tests applying an index shift to a surface where there are fewer shifts specified than expiries in the surface. */ @Test public void indexSurfaceFewerShiftsThanExpiries() { NodalDoublesSurface surface = new NodalDoublesSurface(new double[]{1.1, 1.2, 1.2, 1.3, 1.3, 1.3}, new double[]{0.1, 0.1, 0.2, 0.1, 0.2, 0.3}, new double[]{1, 2, 3, 4, 5, 6}); List<Double> shiftList = Lists.newArrayList(0d, 0.1); VolatilitySurfaceIndexShifts shifts = new VolatilitySurfaceIndexShifts(ScenarioShiftType.ABSOLUTE, shiftList); ValueProperties properties = ValueProperties.with(ValuePropertyNames.FUNCTION, "bar").get(); ValueSpecification spec = new ValueSpecification("foo", ComputationTargetSpecification.NULL, properties); VolatilitySurface shiftedSurface = shifts.execute(new VolatilitySurface(surface), spec, new FunctionExecutionContext()); assertEquals(1.0, shiftedSurface.getVolatility(1.1, 0.1), DELTA); assertEquals(2.1, shiftedSurface.getVolatility(1.2, 0.1), DELTA); assertEquals(3.1, shiftedSurface.getVolatility(1.2, 0.2), DELTA); assertEquals(4.0, shiftedSurface.getVolatility(1.3, 0.1), DELTA); assertEquals(5.0, shiftedSurface.getVolatility(1.3, 0.2), DELTA); assertEquals(6.0, shiftedSurface.getVolatility(1.3, 0.3), DELTA); } /** Tests applying an absolute index shift to SmileSurfaceDataBundle. */ @Test public void indexShiftAbsoluteSurfaceData() { StandardSmileSurfaceDataBundle surfaceData = new StandardSmileSurfaceDataBundle(0d, new double[]{0, 0, 0}, // not relevant to this test new double[]{1.1, 1.2, 1.3}, new double[][]{{10}, {10, 20}, {10, 20, 30}}, new double[][]{{1}, {2, 3}, {4, 5, 6}}, new LinearInterpolator1D()); // not relevant to this test List<Double> shiftList = Lists.newArrayList(0d, 0.1, 0.2); VolatilitySurfaceIndexShifts shifts = new VolatilitySurfaceIndexShifts(ScenarioShiftType.ABSOLUTE, shiftList); SmileSurfaceDataBundle shiftedData = shifts.shiftSurfaceData(surfaceData); double[][] expectedVols = new double[][]{{1}, {2.1, 3.1}, {4.2, 5.2, 6.2}}; double[][] shiftedVols = shiftedData.getVolatilities(); assertTrue(Arrays.deepEquals(expectedVols, shiftedVols)); } /** Tests applying a relative index shift to SmileSurfaceDataBundle. */ @Test public void indexShiftRelativeSurfaceData() { StandardSmileSurfaceDataBundle surfaceData = new StandardSmileSurfaceDataBundle(0d, new double[]{0, 0, 0}, // not relevant to this test new double[]{1.1, 1.2, 1.3}, new double[][]{{10}, {10, 20}, {10, 20, 30}}, new double[][]{{1}, {2, 3}, {4, 5, 6}}, new LinearInterpolator1D()); // not relevant to this test List<Double> shiftList = Lists.newArrayList(0d, 0.1, 0.2); VolatilitySurfaceIndexShifts shifts = new VolatilitySurfaceIndexShifts(ScenarioShiftType.RELATIVE, shiftList); SmileSurfaceDataBundle shiftedData = shifts.shiftSurfaceData(surfaceData); double[][] expectedVols = new double[][]{{1}, {2.2, 3.3}, {4.8, 6.0, 7.2}}; double[][] shiftedVols = shiftedData.getVolatilities(); assertTrue(Arrays.deepEquals(expectedVols, shiftedVols)); } @Test public void dateDouble() { Scenario scenario = new Scenario("Java API test"); scenario.surface().apply().shifts(ScenarioShiftType.RELATIVE, volShift(Period.ofMonths(6), 1.5, 0.1), volShift(Period.ofYears(1), 2.5, 0.2)); ScenarioDefinition definition = scenario.createDefinition(); assertEquals("Java API test", definition.getName()); Map<DistinctMarketDataSelector, FunctionParameters> map = definition.getDefinitionMap(); FunctionParameters params = map.get(new VolatilitySurfaceSelector(null, null, null, null, null, null, null)); assertNotNull(params); Object value = ((SimpleFunctionParameters) params).getValue(StructureManipulationFunction.EXPECTED_PARAMETER_NAME); CompositeStructureManipulator manipulator = (CompositeStructureManipulator) value; List manipulators = manipulator.getManipulators(); assertEquals(1, manipulators.size()); List<VolatilitySurfaceShift> shifts = ImmutableList.of( new VolatilitySurfaceShift(Period.ofMonths(6), 1.5, 0.1), new VolatilitySurfaceShift(Period.ofYears(1), 2.5, 0.2)); VolatilitySurfaceShiftManipulator expected = VolatilitySurfaceShiftManipulator.create(ScenarioShiftType.RELATIVE, shifts); assertEquals(expected, manipulators.get(0)); } @Test public void doubleDate() { Scenario scenario = new Scenario("Java API test"); scenario.surface().apply().shifts(ScenarioShiftType.RELATIVE, volShift(1.5, Period.ofMonths(6), 0.1), volShift(2.5, Period.ofYears(1), 0.2)); ScenarioDefinition definition = scenario.createDefinition(); assertEquals("Java API test", definition.getName()); Map<DistinctMarketDataSelector, FunctionParameters> map = definition.getDefinitionMap(); FunctionParameters params = map.get(new VolatilitySurfaceSelector(null, null, null, null, null, null, null)); assertNotNull(params); Object value = ((SimpleFunctionParameters) params).getValue(StructureManipulationFunction.EXPECTED_PARAMETER_NAME); CompositeStructureManipulator manipulator = (CompositeStructureManipulator) value; List manipulators = manipulator.getManipulators(); assertEquals(1, manipulators.size()); List<VolatilitySurfaceShift> shifts = ImmutableList.of( new VolatilitySurfaceShift(1.5, Period.ofMonths(6), 0.1), new VolatilitySurfaceShift(2.5, Period.ofYears(1), 0.2)); VolatilitySurfaceShiftManipulator expected = VolatilitySurfaceShiftManipulator.create(ScenarioShiftType.RELATIVE, shifts); assertEquals(expected, manipulators.get(0)); } @Test public void doubleDouble() { Scenario scenario = new Scenario("Java API test"); scenario.surface().apply().shifts(ScenarioShiftType.RELATIVE, volShift(1.5, 6.0, 0.1), volShift(2.5, 1.0, 0.2)); ScenarioDefinition definition = scenario.createDefinition(); assertEquals("Java API test", definition.getName()); Map<DistinctMarketDataSelector, FunctionParameters> map = definition.getDefinitionMap(); FunctionParameters params = map.get(new VolatilitySurfaceSelector(null, null, null, null, null, null, null)); assertNotNull(params); Object value = ((SimpleFunctionParameters) params).getValue(StructureManipulationFunction.EXPECTED_PARAMETER_NAME); CompositeStructureManipulator manipulator = (CompositeStructureManipulator) value; List manipulators = manipulator.getManipulators(); assertEquals(1, manipulators.size()); List<VolatilitySurfaceShift> shifts = ImmutableList.of( new VolatilitySurfaceShift(1.5, 6.0, 0.1), new VolatilitySurfaceShift(2.5, 1.0, 0.2)); VolatilitySurfaceShiftManipulator expected = VolatilitySurfaceShiftManipulator.create(ScenarioShiftType.RELATIVE, shifts); assertEquals(expected, manipulators.get(0)); } @Test(expectedExceptions = IllegalArgumentException.class) public void dateDate() { Scenario scenario = new Scenario("Java API test"); scenario.surface().apply().shifts(ScenarioShiftType.RELATIVE, volShift(Period.ofYears(1), Period.ofMonths(6), 0.1), volShift(Period.ofYears(2), Period.ofMonths(9), 0.2)); } }