/** * Copyright (C) 2015 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.strata.market.curve.interpolator; import static com.opengamma.strata.collect.TestHelper.assertSerialization; import static com.opengamma.strata.collect.TestHelper.assertThrowsIllegalArg; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import com.opengamma.strata.collect.array.DoubleArray; /** * Test {@link QuadraticLeftCurveExtrapolator}. */ @Test public class QuadraticLeftCurveExtrapolatorTest { private static final CurveExtrapolator QL_EXTRAPOLATOR = QuadraticLeftCurveExtrapolator.INSTANCE; private static final DoubleArray X_DATA = DoubleArray.of(0.3, 0.4, 1.0, 1.8, 2.8, 5.0); private static final DoubleArray Y_DATA = DoubleArray.of(3.0, 4.0, 3.1, 2.0, 7.0, 2.0); private static final double EPS = 1.e-7; private static final double TOL = 1.e-12; public void test_basics() { assertEquals(QL_EXTRAPOLATOR.getName(), QuadraticLeftCurveExtrapolator.NAME); assertEquals(QL_EXTRAPOLATOR.toString(), QuadraticLeftCurveExtrapolator.NAME); } public void sameIntervalsTest() { DoubleArray xValues = DoubleArray.of(1., 2., 3., 4., 5., 6., 7., 8.); DoubleArray[] yValues = new DoubleArray[] { DoubleArray.of(1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001), DoubleArray.of(11., 8., 5., 1.001, 1.001, 5., 8., 11.), DoubleArray.of(1.001, 1.001, 5., 9., 9., 12., 18., 18.) }; int nData = xValues.size(); int nKeys = 100 * nData; double[] xKeys = new double[nKeys]; double xMin = 0.; double xMax = xValues.get(nData - 1) + 2.; double step = (xMax - xMin) / nKeys; for (int i = 0; i < nKeys; ++i) { xKeys[i] = xMin + step * i; } CurveExtrapolator extrap = QuadraticLeftCurveExtrapolator.INSTANCE; int yDim = yValues.length; for (int k = 0; k < yDim; ++k) { BoundCurveInterpolator bci = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind( xValues, yValues[k], extrap, CurveExtrapolators.LOG_LINEAR); // Check C0 continuity assertEquals(bci.interpolate(xValues.get(0) - 1.e-14), bci.interpolate(xValues.get(0)), TOL); // Check C1 continuity assertEquals(bci.firstDerivative(xValues.get(0) - TOL), bci.firstDerivative(xValues.get(0)), TOL * 1.e2); // Test sensitivity double[] yValues1Up = yValues[k].toArray(); double[] yValues1Dw = yValues[k].toArray(); for (int j = 0; j < nData; ++j) { yValues1Up[j] = yValues[k].get(j) * (1. + EPS); yValues1Dw[j] = yValues[k].get(j) * (1. - EPS); BoundCurveInterpolator bciUp = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind( xValues, DoubleArray.ofUnsafe(yValues1Up), extrap, CurveExtrapolators.LOG_LINEAR); BoundCurveInterpolator bciDw = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind( xValues, DoubleArray.ofUnsafe(yValues1Dw), extrap, CurveExtrapolators.LOG_LINEAR); for (int i = 0; i < nKeys; ++i) { double res1 = 0.5 * (bciUp.interpolate(xKeys[i]) - bciDw.interpolate(xKeys[i])) / EPS / yValues[k].get(j); assertEquals(res1, bci.parameterSensitivity(xKeys[i]).get(j), Math.max(Math.abs(yValues[k].get(j)) * EPS, EPS) * 1.e2);//because gradient is NOT exact } yValues1Up[j] = yValues[k].get(j); yValues1Dw[j] = yValues[k].get(j); } } } public void differentIntervalsTest() { DoubleArray xValues = DoubleArray.of( 1.0328724558967068, 1.2692381049172323, 2.8611430465380905, 4.296118458251132, 7.011992052151352, 7.293354144919639, 8.557971037612713, 8.77306861567384, 10.572470371584489, 12.96945799507056); DoubleArray[] yValues = new DoubleArray[] { DoubleArray.of(1.1593075755231343, 2.794957672828094, 4.674733634811079, 5.517689918508841, 6.138447304104604, 6.264375977142906, 6.581666492568779, 8.378685055774037, 10.005246918325483, 10.468304334744241), DoubleArray.of(9.95780079114617, 8.733013195721913, 8.192165283188197, 6.539369493529048, 6.3868683960757515, 4.700471352238411, 4.555354921077598, 3.780781869340659, 2.299369456202763, 0.9182441378327986) }; int nData = xValues.size(); int nKeys = 100 * nData; double[] xKeys = new double[nKeys]; double xMin = 0.; double xMax = xValues.get(nData - 1) + 2.; double step = (xMax - xMin) / nKeys; for (int i = 0; i < nKeys; ++i) { xKeys[i] = xMin + step * i; } CurveExtrapolator extrap = QuadraticLeftCurveExtrapolator.INSTANCE; int yDim = yValues.length; for (int k = 0; k < yDim; ++k) { BoundCurveInterpolator bci = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind( xValues, yValues[k], extrap, CurveExtrapolators.LOG_LINEAR); // Check C0 continuity assertEquals(bci.interpolate(xValues.get(0) - 1.e-14), bci.interpolate(xValues.get(0)), TOL); // Check C1 continuity assertEquals(bci.firstDerivative(xValues.get(0) - TOL), bci.firstDerivative(xValues.get(0)), TOL * 1.e2); // Test sensitivity double[] yValues1Up = yValues[k].toArray(); double[] yValues1Dw = yValues[k].toArray(); for (int j = 0; j < nData; ++j) { yValues1Up[j] = yValues[k].get(j) * (1. + EPS); yValues1Dw[j] = yValues[k].get(j) * (1. - EPS); BoundCurveInterpolator bciUp = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind( xValues, DoubleArray.ofUnsafe(yValues1Up), extrap, CurveExtrapolators.LOG_LINEAR); BoundCurveInterpolator bciDw = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind( xValues, DoubleArray.ofUnsafe(yValues1Dw), extrap, CurveExtrapolators.LOG_LINEAR); for (int i = 0; i < nKeys; ++i) { double res1 = 0.5 * (bciUp.interpolate(xKeys[i]) - bciDw.interpolate(xKeys[i])) / EPS / yValues[k].get(j); assertEquals(res1, bci.parameterSensitivity(xKeys[i]).get(j), Math.max(Math.abs(yValues[k].get(j)) * EPS, EPS) * 1.e2);//because gradient is NOT exact } yValues1Up[j] = yValues[k].get(j); yValues1Dw[j] = yValues[k].get(j); } } } public void test_noRight() { BoundCurveInterpolator bci = CurveInterpolators.LINEAR.bind(X_DATA, Y_DATA, QL_EXTRAPOLATOR, QL_EXTRAPOLATOR); assertThrowsIllegalArg(() -> bci.interpolate(10d)); assertThrowsIllegalArg(() -> bci.firstDerivative(10d)); assertThrowsIllegalArg(() -> bci.parameterSensitivity(10d)); } //------------------------------------------------------------------------- public void test_serialization() { assertSerialization(QL_EXTRAPOLATOR); } }