/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.math.curve; import static org.testng.AssertJUnit.assertEquals; import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; import org.apache.commons.lang.ArrayUtils; import org.testng.annotations.Test; import com.opengamma.analytics.math.differentiation.ScalarFirstOrderDifferentiator; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.util.test.TestGroup; /** * Test. */ @Test(groups = TestGroup.UNIT) public class DoublesCurveNelsonSiegelTest { private static final String CURVE_NAME = "NS curve"; private static final double BETA0 = 0.03; private static final double BETA1 = -0.02; private static final double BETA2 = 0.06; private static final double LAMBDA = 2.0; private static final double[] PARAMETERS = new double[] {BETA0, BETA1, BETA2, LAMBDA }; private static final DoublesCurveNelsonSiegel CURVE_NS = new DoublesCurveNelsonSiegel(CURVE_NAME, BETA0, BETA1, BETA2, LAMBDA); private static final double TOLERANCE_YIELD = 1.0E-15; private static final double TOLERANCE_SENSITIVITY = 1.0E-5; @Test(expectedExceptions = IllegalArgumentException.class) public void nullParameters() { new DoublesCurveNelsonSiegel(CURVE_NAME, null); } @Test(expectedExceptions = IllegalArgumentException.class) public void nullName() { new DoublesCurveNelsonSiegel(null, BETA0, BETA1, BETA2, LAMBDA); } @Test public void constructors() { assertEquals("DoublesCurveNelsonSiegel: two constructors", CURVE_NS, new DoublesCurveNelsonSiegel(CURVE_NAME, PARAMETERS)); } @Test public void yValue() { final int nbPoint = 10; final double timeMax = 9.0; final double valueComputed0 = CURVE_NS.getYValue(0.0); final double valueExpected0 = BETA0 + BETA1; assertEquals("DoublesCurveNelsonSiegel: value", valueExpected0, valueComputed0, TOLERANCE_YIELD); for (int loopt = 1; loopt <= nbPoint; loopt++) { // Implementation note: start at 1 to avoid 0 (treated tested separately) final double t = loopt * timeMax / nbPoint; final double valueComputed = CURVE_NS.getYValue(t); final double tl = t / LAMBDA; final double exptl = Math.exp(-tl); final double valueExpected = BETA0 + BETA1 * (1 - exptl) / tl + BETA2 * ((1 - exptl) / tl - exptl); assertEquals("DoublesCurveNelsonSiegel: value", valueExpected, valueComputed, TOLERANCE_YIELD); } } @Test /** * Tests the parameters sensitivity with a finite difference comparison. */ public void yValueParameterSensitivity() { final int nbPoint = 10; final double timeMax = 9.0; final double bump = 0.00001; final Double[] sensitivityComputed0 = CURVE_NS.getYValueParameterSensitivity(0.0); final double[] sensitivityExpected0 = new double[] {1.0, 1.0, 0.0, 0.0 }; assertArrayEquals("DoublesCurveNelsonSiegel: parameter sensitivity", sensitivityExpected0, ArrayUtils.toPrimitive(sensitivityComputed0), TOLERANCE_SENSITIVITY); final double[][] parametersBumped = new double[4][]; final DoublesCurveNelsonSiegel[] curveBumped = new DoublesCurveNelsonSiegel[4]; for (int loopp = 0; loopp < 4; loopp++) { parametersBumped[loopp] = PARAMETERS.clone(); parametersBumped[loopp][loopp] += bump; curveBumped[loopp] = new DoublesCurveNelsonSiegel(CURVE_NAME, parametersBumped[loopp]); } for (int loopt = 1; loopt <= nbPoint; loopt++) { // Implementation note: start at 1 to avoid 0 (treated tested separately) final double t = loopt * timeMax / nbPoint; final double valueComputed = CURVE_NS.getYValue(t); final Double[] sensitivityComputed = CURVE_NS.getYValueParameterSensitivity(t); final double[] sensitivityExpected = new double[4]; for (int loopp = 0; loopp < 4; loopp++) { final double valueBumped = curveBumped[loopp].getYValue(t); sensitivityExpected[loopp] = (valueBumped - valueComputed) / bump; } assertArrayEquals("DoublesCurveNelsonSiegel: parameter sensitivity " + loopt, sensitivityExpected, ArrayUtils.toPrimitive(sensitivityComputed), TOLERANCE_SENSITIVITY); } } @Test(enabled = false) public void analysis() { final int nbPoint = 50; final double timeMax = 20.0; final double[] value = new double[nbPoint + 1]; final double[] t = new double[nbPoint + 1]; for (int loopt = 0; loopt <= nbPoint; loopt++) { t[loopt] = loopt * timeMax / nbPoint; value[loopt] = CURVE_NS.getYValue(t[loopt]); } } @Test public void testDerivative() { final Function1D<Double, Double> func = CURVE_NS.toFunction1D(); final ScalarFirstOrderDifferentiator diff = new ScalarFirstOrderDifferentiator(); final Function1D<Double, Double> grad = diff.differentiate(func); for (int i = 0; i < 50; i++) { final double t = 0 + 10.0 * i / 99.; final double fd = grad.evaluate(t); final double anal = CURVE_NS.getDyDx(t); assertEquals("t=" + t, fd, anal, 1e-12); } } }