@Override public Double interpolate(final Interpolator1DDataBundle data, final Double value) { Validate.notNull(data, "data"); Validate.notNull(value, "value"); if (value < data.firstKey()) { return data.firstValue(); } else if (value > data.lastKey()) { return data.lastValue(); } throw new IllegalArgumentException("Value " + value + " was within data range"); }
@Test public void dataBundleTest() { Interpolator1DDataBundle db = INTERPOLATOR.getDataBundle(X_DATA, Y_DATA); double[] keys = db.getKeys(); double[] values = db.getValues(); final int n = X_DATA.length; assertEquals("keys length", n, keys.length); assertEquals("values length", n, values.length); for (int i = 0; i < n; i++) { assertEquals("keys " + i, X_DATA[i], keys[i]); assertEquals("values " + i, Y_DATA[i], values[i]); } }
@Override protected Object getResult( final PDELocalVolatilityCalculator<?> calculator, final LocalVolatilitySurfaceMoneyness localVolatility, final ForwardCurve forwardCurve, final EuropeanVanillaOption option, final YieldAndDiscountCurve discountingCurve) { final Interpolator1DDataBundle data = (Interpolator1DDataBundle) calculator.getResult(localVolatility, forwardCurve, option, discountingCurve); return InterpolatedDoublesCurve.from( data.getKeys(), data.getValues(), ((LocalVolatilityForwardPDEVolatilityGreeksGridCalculator) calculator).getInterpolator()); }
@Override public double[] getNodeSensitivitiesForValue( final Interpolator1DDataBundle data, final Double value) { Validate.notNull(data, "data"); final int n = data.size(); if (value < data.firstKey()) { final double[] result = new double[n]; result[0] = 1; return result; } else if (value > data.lastKey()) { final double[] result = new double[n]; result[n - 1] = 1; return result; } throw new IllegalArgumentException("Value " + value + " was within data range"); }
/** * No clamped points added. checking agreement with the extrapolation done by the underlying * interpolation */ @Test public void notClampedTest() { double[][] xValuesSet = new double[][] { {-5.0, -1.4, 3.2, 3.5, 7.6}, {1., 2., 4.5, 12.1, 14.2}, {-5.2, -3.4, -3.2, -0.9, -0.2} }; double[][] yValuesSet = new double[][] { {-2.2, 1.1, 1.9, 2.3, -0.1}, {3.4, 5.2, 4.3, 1.1, 0.2}, {1.4, 2.2, 4.1, 1.9, 0.99} }; for (int k = 0; k < xValuesSet.length; ++k) { double[] xValues = Arrays.copyOf(xValuesSet[k], xValuesSet[k].length); double[] yValues = Arrays.copyOf(yValuesSet[k], yValuesSet[k].length); int nData = xValues.length; int nKeys = 100; double interval = (xValues[2] - xValues[0]) / (nKeys - 1.0); int n = INTERP_SENSE.length; for (int i = 0; i < n; ++i) { ProductPiecewisePolynomialInterpolator interp = new ProductPiecewisePolynomialInterpolator(INTERP_SENSE[i]); PiecewisePolynomialResult result = interp.interpolateWithSensitivity(xValues, yValues); ReciprocalExtrapolator1D extrap1D = new ReciprocalExtrapolator1D( new ProductPiecewisePolynomialInterpolator1D(INTERP_SENSE[i])); Interpolator1DDataBundle data = extrap1D.getDataBundle(xValues, yValues); InterpolatorTestUtil.assertArrayRelative("notClampedTest", xValues, data.getKeys(), EPS); InterpolatorTestUtil.assertArrayRelative("notClampedTest", yValues, data.getValues(), EPS); /* left extrapolation */ double grad = FUNC.differentiate(result, xValues[0]).getEntry(0); for (int j = 1; j < nKeys; ++j) { double key = xValues[0] - interval * j; double ref = grad * (key - xValues[0]) + yValues[0] * xValues[0]; InterpolatorTestUtil.assertRelative( "notClampedTest", ref / key, extrap1D.interpolate(data, key), EPS); double keyUp = key + DELTA; double keyDw = key - DELTA; double refDeriv = 0.5 * (extrap1D.interpolate(data, keyUp) - extrap1D.interpolate(data, keyDw)) / DELTA; InterpolatorTestUtil.assertRelative( "notClampedTest", refDeriv, extrap1D.firstDerivative(data, key), DELTA); double[] refSense = new double[nData]; for (int l = 0; l < nData; ++l) { double[] yValuesUp = Arrays.copyOf(yValues, nData); double[] yValuesDw = Arrays.copyOf(yValues, nData); yValuesUp[l] += DELTA; yValuesDw[l] -= DELTA; Interpolator1DDataBundle dataUp = extrap1D.getDataBundle(xValues, yValuesUp); Interpolator1DDataBundle dataDw = extrap1D.getDataBundle(xValues, yValuesDw); refSense[l] = 0.5 * (extrap1D.interpolate(dataUp, key) - extrap1D.interpolate(dataDw, key)) / DELTA; } InterpolatorTestUtil.assertArrayRelative( "notClampedTest", extrap1D.getNodeSensitivitiesForValue(data, key), refSense, DELTA * 10.0); } /* right extrapolation */ for (int j = 1; j < nKeys; ++j) { double key = xValues[nData - 1] + interval * j; InterpolatorTestUtil.assertRelative( "notClampedTest", FUNC.evaluate(result, key).getEntry(0) / key, extrap1D.interpolate(data, key), EPS); double keyUp = key + DELTA; double keyDw = key - DELTA; double refDeriv = 0.5 * (extrap1D.interpolate(data, keyUp) - extrap1D.interpolate(data, keyDw)) / DELTA; InterpolatorTestUtil.assertRelative( "notClampedTest", refDeriv, extrap1D.firstDerivative(data, key), DELTA); double[] refSense = new double[nData]; for (int l = 0; l < nData; ++l) { double[] yValuesUp = Arrays.copyOf(yValues, nData); double[] yValuesDw = Arrays.copyOf(yValues, nData); yValuesUp[l] += DELTA; yValuesDw[l] -= DELTA; Interpolator1DDataBundle dataUp = extrap1D.getDataBundle(xValues, yValuesUp); Interpolator1DDataBundle dataDw = extrap1D.getDataBundle(xValues, yValuesDw); refSense[l] = 0.5 * (extrap1D.interpolate(dataUp, key) - extrap1D.interpolate(dataDw, key)) / DELTA; } InterpolatorTestUtil.assertArrayRelative( "notClampedTest", extrap1D.getNodeSensitivitiesForValue(data, key), refSense, DELTA * 10.0); } } } }