/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.model.volatility.smile.fitting.sabr; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; import org.apache.commons.lang.ArrayUtils; import org.testng.annotations.Test; import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurve; import com.opengamma.analytics.math.curve.InterpolatedDoublesCurve; import com.opengamma.analytics.math.interpolation.Interpolator1D; import com.opengamma.analytics.math.interpolation.Interpolator1DFactory; import com.opengamma.util.test.TestGroup; /** * Test. */ @Test(groups = TestGroup.UNIT) public class StandardSmileSurfaceDataBundleTest { private static final double SPOT = 1.0; private static final double[] FORWARDS = new double[] {1.1, 1.15, 1.3 }; private static final double[] EXPIRIES = new double[] {0.1, 0.25, 1 }; private static final double[][] STRIKES = new double[][] { new double[] {1.1, 1.15, 1.3, 1.5, 1.7 }, new double[] {1.1, 1.15, 1.3, 1.5, 1.7, 2 }, new double[] {1.15, 1.3, 1.5, 1.7, 2 } }; private static final double[][] VOLS = new double[][] { new double[] {0.1, 0.1, 0.1, 0.1, 0.1 }, new double[] {0.11, 0.11, 0.11, 0.11, 0.11, 0.11 }, new double[] {0.12, 0.12, 0.12, 0.12, 0.12 } }; private static final double[][] DECREASING_VARIANCE = new double[][] { new double[] {0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001 }, new double[] {0.11, 0.011, 0.0011, 0.00011, 0.000011, 0.0000011 }, new double[] {0.12, 0.00012, 0.00012, 0.00012, 0.000012, 0.0000012 } }; private static final Interpolator1D INTERPOLATOR = Interpolator1DFactory.DOUBLE_QUADRATIC_INSTANCE; private static final ForwardCurve FORWARD_CURVE; private static final StandardSmileSurfaceDataBundle DATA; private static final double EPS = 1e-15; static { final double[] t = ArrayUtils.add(EXPIRIES, 0, 0.0); final double[] f = ArrayUtils.add(FORWARDS, 0, SPOT); FORWARD_CURVE = new ForwardCurve(InterpolatedDoublesCurve.from(t, f, INTERPOLATOR)); DATA = new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, VOLS); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullForwards() { new StandardSmileSurfaceDataBundle(SPOT, null, EXPIRIES, STRIKES, VOLS, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullExpiries1() { new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, null, STRIKES, VOLS, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullStrikes1() { new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, EXPIRIES, null, VOLS, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullVols1() { new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, EXPIRIES, STRIKES, null, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullInterpolator() { new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, EXPIRIES, STRIKES, VOLS, null); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullForwardCurve() { new StandardSmileSurfaceDataBundle(null, EXPIRIES, STRIKES, VOLS); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullExpiries2() { new StandardSmileSurfaceDataBundle(FORWARD_CURVE, null, STRIKES, VOLS); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullStrikes2() { new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, null, VOLS); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullVols2() { new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, null); } @Test(expectedExceptions = IllegalArgumentException.class) public void testForwardLength() { new StandardSmileSurfaceDataBundle(SPOT, new double[] {1, 2, 3, 4 }, EXPIRIES, STRIKES, VOLS, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testStrikeLength1() { new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, EXPIRIES, new double[][] {new double[] {1, 2, 3, 4, 5, 6 } }, VOLS, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testVolLength1() { new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, EXPIRIES, STRIKES, new double[][] {new double[] {0.1, 0.1, 0.1, 0.1, 0.1, 0.1 } }, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testVolLength2() { new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, EXPIRIES, STRIKES, new double[][] { new double[] {0.1, 0.1, 0.1, 0.1 }, new double[] {0.11, 0.11, 0.11, 0.11 }, new double[] {0.12, 0.12, 0.12, 0.12 } }, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadVolData1() { new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, EXPIRIES, STRIKES, DECREASING_VARIANCE, INTERPOLATOR); } @Test(expectedExceptions = IllegalArgumentException.class) public void testStrikeLength2() { new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, new double[][] {new double[] {1, 2, 3, 4, 5, 6 } }, VOLS); } @Test(expectedExceptions = IllegalArgumentException.class) public void testVolLength3() { new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, new double[][] {new double[] {0.1, 0.1, 0.1, 0.1, 0.1, 0.1 } }); } @Test(expectedExceptions = IllegalArgumentException.class) public void testVolLength4() { new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, new double[][] { new double[] {0.1, 0.1, 0.1, 0.1 }, new double[] {0.11, 0.11, 0.11, 0.11 }, new double[] {0.12, 0.12, 0.12, 0.12 } }); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadVolData2() { new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, DECREASING_VARIANCE); } @Test(expectedExceptions = IllegalArgumentException.class) public void testLowExpiryIndexForBump() { DATA.withBumpedPoint(-1, 1, 0.01); } @Test(expectedExceptions = IllegalArgumentException.class) public void testHighExpiryIndexForBump() { DATA.withBumpedPoint(100, 1, 0.01); } @Test(expectedExceptions = IllegalArgumentException.class) public void testLowStrikeIndexForBump() { DATA.withBumpedPoint(1, -1, 0.01); } @Test(expectedExceptions = IllegalArgumentException.class) public void testHighStrikeIndexForBump() { DATA.withBumpedPoint(1, 100, 0.01); } @Test public void testObject() { assertArrayEquals(FORWARDS, DATA.getForwards(), EPS); assertArrayEquals(EXPIRIES, DATA.getExpiries(), 0); for (int i = 0; i < STRIKES.length; i++) { assertArrayEquals(STRIKES[i], DATA.getStrikes()[i], 0); assertArrayEquals(VOLS[i], DATA.getVolatilities()[i], 0); } assertEquals(FORWARD_CURVE, DATA.getForwardCurve()); // assertEquals(IS_CALL_DATA, DATA.isCallData()); StandardSmileSurfaceDataBundle other = new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, VOLS); assertEquals(DATA, other); assertEquals(DATA.hashCode(), other.hashCode()); other = new StandardSmileSurfaceDataBundle(SPOT, FORWARDS, EXPIRIES, STRIKES, VOLS, INTERPOLATOR); assertArrayEquals(DATA.getExpiries(), other.getExpiries(), 0); for (int i = 0; i < STRIKES.length; i++) { assertArrayEquals(DATA.getStrikes()[i], other.getStrikes()[i], 0); assertArrayEquals(DATA.getVolatilities()[i], other.getVolatilities()[i], 0); } assertArrayEquals(ArrayUtils.toPrimitive(DATA.getForwardCurve().getForwardCurve().getXData()), ArrayUtils.toPrimitive(other.getForwardCurve().getForwardCurve().getXData()), 0); assertArrayEquals(ArrayUtils.toPrimitive(DATA.getForwardCurve().getForwardCurve().getYData()), ArrayUtils.toPrimitive(other.getForwardCurve().getForwardCurve().getYData()), 0); assertEquals(((InterpolatedDoublesCurve) DATA.getForwardCurve().getForwardCurve()).getInterpolator(), ((InterpolatedDoublesCurve) other.getForwardCurve().getForwardCurve()).getInterpolator()); final ForwardCurve otherCurve = new ForwardCurve(InterpolatedDoublesCurve.from(ArrayUtils.add(EXPIRIES, 0, 0), ArrayUtils.add(EXPIRIES, 0, SPOT), INTERPOLATOR)); other = new StandardSmileSurfaceDataBundle(otherCurve, EXPIRIES, STRIKES, VOLS); assertFalse(DATA.equals(other)); other = new StandardSmileSurfaceDataBundle(FORWARD_CURVE, new double[] {0, 0.01, 0.02 }, STRIKES, VOLS); assertFalse(DATA.equals(other)); other = new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, VOLS, VOLS); assertFalse(DATA.equals(other)); other = new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, STRIKES); assertFalse(DATA.equals(other)); // other = new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, VOLS, !IS_CALL_DATA); // assertFalse(DATA.equals(other)); } @Test public void testBumpedPoint() { final SmileSurfaceDataBundle bumped = DATA.withBumpedPoint(2, 3, 0.05); final double[][] bumpedVols = new double[VOLS.length][]; for (int i = 0; i < VOLS.length; i++) { bumpedVols[i] = VOLS[i]; } bumpedVols[2][3] += 0.05; assertEquals(bumped, new StandardSmileSurfaceDataBundle(FORWARD_CURVE, EXPIRIES, STRIKES, bumpedVols)); } }