public virtual void negativeDataTest() { DoubleArray xValues = DoubleArray.of(-34.5, -27.0, -22.5, -14.2, -10.0, -5.0, -0.3); DoubleArray yValues = DoubleArray.of(4.0, 2.0, 1.0, 5.0, 10.0, 3.5, -2.0); int nData = yValues.size(); DoubleArray pValues = DoubleArray.of(nData, i => xValues.get(i) * yValues.get(i)); System.Func <double, bool> domain = (double?x) => { return(x.Value >= xValues.get(0) && x.Value <= xValues.get(nData - 1)); }; DoubleArray keys = DoubleArray.of(xValues.get(0), -27.7, -21.2, -17.8, -9.99, -1.52, -0.35, xValues.get(nData - 1)); int nKeys = keys.size(); BoundCurveInterpolator bound = INTERP.bind(xValues, yValues); BoundCurveInterpolator boundBase = BASE_INTERP.bind(xValues, pValues); System.Func <double, double> funcDeriv = x => bound.interpolate(x.Value); for (int i = 0; i < nKeys; ++i) { // interpolate assertEquals(bound.interpolate(keys.get(i)), boundBase.interpolate(keys.get(i)) / keys.get(i), TOL); // first derivative double firstExp = DIFF_CALC.differentiate(funcDeriv, domain).apply(keys.get(i)); assertEquals(bound.firstDerivative(keys.get(i)), firstExp, EPS); // parameter sensitivity int index = i; System.Func <DoubleArray, double> funcSensi = x => INTERP.bind(xValues, x).interpolate(keys.get(index)); DoubleArray sensExp = SENS_CALC.differentiate(funcSensi).apply(yValues); assertTrue(DoubleArrayMath.fuzzyEquals(bound.parameterSensitivity(keys.get(i)).toArray(), sensExp.toArray(), EPS)); } }
public virtual void sampleDataTest() { DoubleArray xValues = DoubleArray.of(0.5, 1.0, 2.5, 4.2, 10.0, 15.0, 30.0); DoubleArray yValues = DoubleArray.of(4.0, 2.0, 1.0, 5.0, 10.0, 3.5, -2.0); int nData = yValues.size(); DoubleArray pValues = DoubleArray.of(nData, i => xValues.get(i) * yValues.get(i)); System.Func <double, bool> domain = (double?x) => { return(x.Value >= xValues.get(0) && x.Value <= xValues.get(nData - 1)); }; DoubleArray keys = DoubleArray.of(xValues.get(0), 0.7, 1.2, 7.8, 10.0, 17.52, 25.0, xValues.get(nData - 1)); int nKeys = keys.size(); BoundCurveInterpolator bound = INTERP.bind(xValues, yValues); PiecewisePolynomialResultsWithSensitivity ppRes = BASE_INTERP.interpolateWithSensitivity(xValues.toArray(), pValues.toArray()); System.Func <double, double> funcDeriv = x => bound.interpolate(x.Value); for (int i = 0; i < nKeys; ++i) { // interpolate assertEquals(bound.interpolate(keys.get(i)), FUNCTION.evaluate(ppRes, keys.get(i)).get(0) / keys.get(i), TOL); // first derivative double firstExp = DIFF_CALC.differentiate(funcDeriv, domain).apply(keys.get(i)); assertEquals(bound.firstDerivative(keys.get(i)), firstExp, EPS); // parameter sensitivity int index = i; System.Func <DoubleArray, double> funcSensi = x => INTERP.bind(xValues, x).interpolate(keys.get(index)); DoubleArray sensExp = SENS_CALC.differentiate(funcSensi).apply(yValues); assertTrue(DoubleArrayMath.fuzzyEquals(bound.parameterSensitivity(keys.get(i)).toArray(), sensExp.toArray(), EPS)); } }
public virtual void test_firstDerivative() { BoundCurveInterpolator bci = NATURAL_CUBLIC_SPLINE_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); double eps = 1e-8; double lo = bci.interpolate(0.2); double hi = bci.interpolate(0.2 + eps); double deriv = (hi - lo) / eps; assertEquals(bci.firstDerivative(0.2), deriv, 1e-6); }
public virtual void value() { BoundCurveInterpolator bci = CurveInterpolators.LINEAR.bind(X_DATA, Y_DATA, EXP_EXTRAPOLATOR, EXP_EXTRAPOLATOR); double mLeft = Math.Log(Y_DATA.get(0)) / X_DATA.get(0); double mRight = Math.Log(Y_DATA.get(X_DATA.size() - 1)) / X_DATA.get(X_DATA.size() - 1); assertEquals(bci.interpolate(0.0), 1d, TOLERANCE_VALUE); assertEquals(bci.interpolate(-0.2), Math.Exp(mLeft * -0.2), TOLERANCE_VALUE); assertEquals(bci.interpolate(6.0), Math.Exp(mRight * 6.0), TOLERANCE_VALUE); }
public virtual void test_exceptionThrown() { BoundCurveInterpolator bci = CurveInterpolators.LINEAR.bind(X_DATA, Y_DATA, EXCEPTION_EXTRAPOLATOR, EXCEPTION_EXTRAPOLATOR); assertThrows(() => bci.interpolate(-1d), typeof(System.NotSupportedException)); assertThrows(() => bci.firstDerivative(-1d), typeof(System.NotSupportedException)); assertThrows(() => bci.parameterSensitivity(-1d), typeof(System.NotSupportedException)); assertThrows(() => bci.interpolate(10d), typeof(System.NotSupportedException)); assertThrows(() => bci.firstDerivative(10d), typeof(System.NotSupportedException)); assertThrows(() => bci.parameterSensitivity(10d), typeof(System.NotSupportedException)); }
public virtual void derivativeTest() { BoundCurveInterpolator bci = PRODUCT_LINEAR.bind(X_VALUES, Y_VALUES, LINEAR, DISCOUNT_FACTOR_LINEAR_RIGHT_ZERO_RATE); for (int i = 0; i < NUM_KEYS; ++i) { double key = X_KEYS.get(i); double computed = bci.firstDerivative(key); double expected = 0.5d * (bci.interpolate(key + EPS) - bci.interpolate(key - EPS)) / EPS; assertEquals(computed, expected, EPS); } }
//------------------------------------------------------------------------- public virtual void test_interpolation() { BoundCurveInterpolator bci = NATURAL_CUBLIC_SPLINE_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); for (int i = 0; i < X_DATA.size(); i++) { assertEquals(bci.interpolate(X_DATA.get(i)), Y_DATA.get(i), TOL); } for (int i = 0; i < X_TEST.size(); i++) { assertEquals(bci.interpolate(X_TEST.get(i)), Y_TEST.get(i), TOL); } }
public virtual 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.0; double xMax = xValues.get(nData - 1) + 2.0; 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.0 + EPS); yValues1Dw[j] = yValues[k].get(j) * (1.0 - 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 virtual void sameIntervalsTest() { DoubleArray xValues = DoubleArray.of(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0); 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.0, 8.0, 5.0, 1.001, 1.001, 5.0, 8.0, 11.0), DoubleArray.of(1.001, 1.001, 5.0, 9.0, 9.0, 12.0, 18.0, 18.0) }; int nData = xValues.size(); int nKeys = 100 * nData; double[] xKeys = new double[nKeys]; double xMin = 0.0; double xMax = xValues.get(nData - 1) + 2.0; 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.0 + EPS); yValues1Dw[j] = yValues[k].get(j) * (1.0 - 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); } } }
internal Bound(DoubleArray xValues, DoubleArray yValues, BoundCurveInterpolator interpolator) { this.nodeCount = xValues.size(); this.firstXValue = xValues.get(0); this.firstYValue = yValues.get(0); this.lastXValue = xValues.get(nodeCount - 1); this.lastYValue = yValues.get(nodeCount - 1); this.eps = EPS * (lastXValue - firstXValue); // left this.leftGradient = (interpolator.interpolate(firstXValue + eps) - firstYValue) / eps; this.leftSens = interpolator.parameterSensitivity(firstXValue + eps); // right this.rightGradient = (lastYValue - interpolator.interpolate(lastXValue - eps)) / eps; this.rightSens = interpolator.parameterSensitivity(lastXValue - eps); }
public virtual void limitingTest() { BoundCurveInterpolator bci = LINEAR.bind(X_DATA, Y_DATA, DISCOUNT_FACTOR_QUADRATIC_LEFT_ZERO_RATE, PRODUCT_LINEAR); double small = 1.0e-8; assertEquals(bci.interpolate(small), bci.interpolate(10d * small), Y_DATA.get(0) * 10d * small); double derivative = bci.firstDerivative(small); double derivativeExp = (bci.interpolate(small + 0.5 * small) - bci.interpolate(small - 0.5 * small)) / small; assertEquals(derivative, derivativeExp, Y_DATA.get(0) * small); DoubleArray sensi = bci.parameterSensitivity(small); DoubleArray sensiS = bci.parameterSensitivity(small * 5d); assertTrue(DoubleArrayMath.fuzzyEquals(sensi.toArray(), sensiS.toArray(), Y_DATA.get(0) * 10d * small)); }
public virtual void sameIntervalsTest() { DoubleArray xValues = DoubleArray.of(-1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0); DoubleArray[] yValues = new DoubleArray[] { DoubleArray.of(1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001), DoubleArray.of(11.0, 11.0, 8.0, 5.0, 1.001, 1.001, 5.0, 8.0, 11.0, 11.0), DoubleArray.of(1.001, 1.001, 5.0, 8.0, 9.0, 9.0, 11.0, 12.0, 18.0, 18.0) }; int nKeys = 100; double[] keys = new double[nKeys]; double interval = 0.061; for (int i = 0; i < nKeys; ++i) { keys[i] = xValues.get(0) + interval * i; } CurveExtrapolator extrap = InterpolatorCurveExtrapolator.INSTANCE; int yDim = yValues.Length; for (int k = 0; k < yDim; ++k) { BoundCurveInterpolator boundInterp = CurveInterpolators.SQUARE_LINEAR.bind(xValues, yValues[k], extrap, extrap); AbstractBoundCurveInterpolator baseInterp = (AbstractBoundCurveInterpolator)boundInterp; for (int j = 0; j < nKeys; ++j) { // value assertEquals(boundInterp.interpolate(keys[j]), baseInterp.doInterpolate(keys[j]), TOL); // derivative assertEquals(boundInterp.firstDerivative(keys[j]), baseInterp.doFirstDerivative(keys[j]), TOL); // sensitivity assertTrue(boundInterp.parameterSensitivity(keys[j]).equalWithTolerance(baseInterp.doParameterSensitivity(keys[j]), TOL)); } } }
public virtual void test_lastNode() { BoundCurveInterpolator bci = LL_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); assertEquals(bci.interpolate(5.0), 2.0, TOL); assertEquals(bci.firstDerivative(5.0), bci.firstDerivative(4.99999999), 1e-6); }
public virtual 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 nKeys = 100; double[] keys = new double[nKeys]; double interval = 0.061; for (int i = 0; i < nKeys; ++i) { keys[i] = xValues.get(0) + interval * i; } CurveExtrapolator extrap = InterpolatorCurveExtrapolator.INSTANCE; int yDim = yValues.Length; for (int k = 0; k < yDim; ++k) { BoundCurveInterpolator boundInterp = CurveInterpolators.SQUARE_LINEAR.bind(xValues, yValues[k], extrap, extrap); AbstractBoundCurveInterpolator baseInterp = (AbstractBoundCurveInterpolator)boundInterp; for (int j = 0; j < nKeys; ++j) { // value assertEquals(boundInterp.interpolate(keys[j]), baseInterp.doInterpolate(keys[j]), TOL); // derivative assertEquals(boundInterp.firstDerivative(keys[j]), baseInterp.doFirstDerivative(keys[j]), TOL); // sensitivity assertTrue(boundInterp.parameterSensitivity(keys[j]).equalWithTolerance(baseInterp.doParameterSensitivity(keys[j]), TOL)); } } }
//------------------------------------------------------------------------- public virtual void test_firstNode() { BoundCurveInterpolator bci = DQ_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); assertEquals(bci.interpolate(0.0), 3.0, TOL); assertEquals(bci.firstDerivative(0.0), bci.firstDerivative(0.00000001), 1e-6); }
// regression to ISDA curve public virtual void curveRegressionTest() { double[] xValues = new double[] { 0.08767123287671233, 0.1726027397260274, 0.2602739726027397, 0.5095890410958904, 1.010958904109589, 2.010958904109589, 3.0136986301369864, 4.0191780821917815, 5.016438356164384, 6.013698630136987, 7.016438356164384, 8.016438356164384, 9.016438356164384, 10.021917808219179, 12.01917808219178, 15.027397260273974, 20.024657534246575, 25.027397260273972, 30.030136986301372 }; double[] yValues = new double[] { 0.0015967771993938666, 0.002000101499768777, 0.002363431670279865, 0.003338175293899776, 0.005634608399714134, 0.00440326902435394, 0.007809961130263494, 0.011941089607974827, 0.015908558015433557, 0.019426790989545677, 0.022365655212981644, 0.02480329609280203, 0.02681632723967965, 0.028566047406753222, 0.031343018999443514, 0.03409375145707815, 0.036451406286344155, 0.0374228389649933, 0.037841116301420584 }; CurveExtrapolator left = CurveExtrapolators.FLAT; CurveExtrapolator right = CurveExtrapolators.PRODUCT_LINEAR; BoundCurveInterpolator interp = INTERP.bind(DoubleArray.ofUnsafe(xValues), DoubleArray.ofUnsafe(yValues), left, right); double[] keys = new double[] { 1d / 365d, 17d / 365d, 30d / 365d, 98d / 365d, 1d, 2.35, 6d, 10d, 12.6, 28d, 32d, 39d }; // interpolate double[] expected = new double[] { 0.0015967771993938666, 0.0015967771993938666, 0.0015967771993938666, 0.0024244214596922794, 0.005609029445739646, 0.005880433874305883, 0.01938638577242741, 0.02853165777399691, 0.031976443846372445, 0.03768939749254428, 0.037969928846136244, 0.038322391316033835 }; for (int i = 0; i < keys.Length; ++i) { double computed = interp.interpolate(keys[i]); assertEquals(computed, expected[i], EPS); } // sensitivity double[][] sensiExp = new double[][] { new double[] { 1d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 1d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 1.0, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0.9374299170217537, 0.0625700829782464, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0.011138558275319966, 0.98886144172468, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0.5663932037211347, 0.43360679627886545, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.011484520046164301, 0.9885154799538357, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.01965436153932362, 0.9803456384606765, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.7697250253579322, 0.23027497464206784, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.3627229965940976, 0.6372770034059024 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, -0.3079596561838882, 1.3079596561838882 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, -1.1506122199305884, 2.1506122199305886 } }; for (int i = 0; i < keys.Length; ++i) { DoubleArray computed = interp.parameterSensitivity(keys[i]); assertTrue(DoubleArrayMath.fuzzyEquals(computed.toArray(), sensiExp[i], EPS)); } // fwd rate double[] fwdExp = new double[] { 0.0015967771993938666, 0.0015967771993938666, 0.0015967771993938666, 0.004355764791085397, 0.007968687949886104, 0.01464196114594003, 0.037124276087345934, 0.04425631735181895, 0.04508415518352911, 0.03993364832127998, 0.03993364832127998, 0.03993364832127998 }; for (int i = 0; i < keys.Length; ++i) { double value = interp.interpolate(keys[i]); double deriv = interp.firstDerivative(keys[i]); double computed = deriv * keys[i] + value; assertEquals(computed, fwdExp[i], EPS); } }
// regression to ISDA curve public virtual void curveNegativeRateRegressionTest() { double[] xValues = new double[] { 0.09589041095890412, 0.1726027397260274, 0.2547945205479452, 0.5041095890410959, 0.7561643835616438, 1.0082191780821919, 2.0136986301369864, 3.0109589041095894, 4.008219178082192, 5.010958904109589, 6.010958904109589, 7.010958904109589, 8.016438356164384, 9.013698630136986, 10.013698630136986, 12.013698630136986, 15.016438356164384, 20.021917808219175, 30.032876712328765 }; double[] yValues = new double[] { -0.0020786675364765166, -0.0016860241245632032, -0.0013445488774423426, -4.237821212705129E-4, 2.5198253623336676E-5, 5.935456094577134E-4, -3.2426565772714425E-4, 6.147334333200949E-4, 0.0019060366773708986, 0.0033107384678633615, 0.004774430364382846, 0.006237401212672876, 0.007639615209817064, 0.00896830709117619, 0.010164859928720184, 0.012196812821300893, 0.014410766977011871, 0.01623618497051232, 0.016522578536714926 }; CurveExtrapolator left = CurveExtrapolators.FLAT; CurveExtrapolator right = CurveExtrapolators.PRODUCT_LINEAR; BoundCurveInterpolator interp = INTERP.bind(DoubleArray.ofUnsafe(xValues), DoubleArray.ofUnsafe(yValues), left, right); double[] keys = new double[] { 1d / 365d, 17d / 365d, 30d / 365d, 98d / 365d, 1d, 2.35, 6d, 10d, 12.6, 28d, 32d, 39d }; // interpolate double[] expected = new double[] { -0.0020786675364765166, -0.0020786675364765166, -0.0020786675364765166, -0.0012495606047715551, 5.795315650672766E-4, 8.145045403416393E-5, 0.004761034017457297, 0.010150085453826136, 0.01271200378309255, 0.016480992621622493, 0.016557789252559695, 0.016654277327326956 }; for (int i = 0; i < keys.Length; ++i) { double computed = interp.interpolate(keys[i]); assertEquals(computed, expected[i], EPS); } // sensitivity double[][] sensiExp = new double[][] { new double[] { 1d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 1d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 1d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0.8968378560215295, 0.1031621439784705, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0.024657534246575567, 0.9753424657534244, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0.5679270452660136, 0.43207295473398644, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.009152436354538397, 0.9908475636454616, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.012347532370050315, 0.9876524676299496, 0d, 0d, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.7672982701729827, 0.23270172982701726, 0d, 0.0 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0.1452054794520546, 0.8547945205479454 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, -0.12294520547945219, 1.1229452054794522 }, new double[] { 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, 0d, -0.4598524762908325, 1.4598524762908325 } }; for (int i = 0; i < keys.Length; ++i) { DoubleArray computed = interp.parameterSensitivity(keys[i]); assertTrue(DoubleArrayMath.fuzzyEquals(computed.toArray(), sensiExp[i], EPS)); } // fwd rate double[] fwdExp = new double[] { -0.0020786675364765166, -0.0020786675364765166, -0.0020786675364765166, 5.172212669050933E-4, 0.0022985876769608432, 0.0025107892902424037, 0.012108930306120206, 0.02095022660137702, 0.023268603631019753, 0.017095365669120136, 0.017095365669120136, 0.017095365669120136 }; for (int i = 0; i < keys.Length; ++i) { double value = interp.interpolate(keys[i]); double deriv = interp.firstDerivative(keys[i]); double computed = deriv * keys[i] + value; assertEquals(computed, fwdExp[i], EPS); } }
//------------------------------------------------------------------------- public virtual void noLeftTest() { BoundCurveInterpolator bci = PRODUCT_LINEAR.bind(X_VALUES, Y_VALUES, DISCOUNT_FACTOR_LINEAR_RIGHT_ZERO_RATE, DISCOUNT_FACTOR_LINEAR_RIGHT_ZERO_RATE); assertThrowsIllegalArg(() => bci.interpolate(0.2d)); assertThrowsIllegalArg(() => bci.firstDerivative(0.3d)); assertThrowsIllegalArg(() => bci.parameterSensitivity(0.6d)); }
public virtual 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 virtual void sameIntervalsTest() { DoubleArray xValues = DoubleArray.of(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0); DoubleArray[] yValues = new DoubleArray[] { DoubleArray.of(0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001), DoubleArray.of(-11.0, 8.0, 5.0, 1.001, -1.001, 5.0, -8.0, 11.0), DoubleArray.of(0.001, -0.001, 5.0, 9.0, 9.0, 12.0, 18.0, 18.0) }; int nData = xValues.size(); int nKeys = 100 * nData; double[] xKeys = new double[nKeys]; double xMin = 0.0; double xMax = xValues.get(nData - 1) + 2d; double step = (xMax - xMin) / nKeys; for (int i = 0; i < nKeys; ++i) { xKeys[i] = xMin + step * i; } int yDim = yValues.Length; for (int k = 0; k < yDim; ++k) { BoundCurveInterpolator bci = PRODUCT_NATURAL_SPLINE_MONOTONE_CUBIC.bind(xValues, yValues[k], DISCOUNT_FACTOR_QUADRATIC_LEFT_ZERO_RATE, PRODUCT_LINEAR); // Check C0 continuity assertEquals(bci.interpolate(xValues.get(0) - TOL), bci.interpolate(xValues.get(0)), TOL * 1.0e2); // Check C1 continuity assertEquals(bci.firstDerivative(xValues.get(0) - TOL), bci.firstDerivative(xValues.get(0)), Math.Sqrt(TOL)); // 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) * (1d + EPS); yValues1Dw[j] = yValues[k].get(j) * (1d - EPS); BoundCurveInterpolator bciUp = PRODUCT_NATURAL_SPLINE_MONOTONE_CUBIC.bind(xValues, DoubleArray.ofUnsafe(yValues1Up), DISCOUNT_FACTOR_QUADRATIC_LEFT_ZERO_RATE, PRODUCT_LINEAR); BoundCurveInterpolator bciDw = PRODUCT_NATURAL_SPLINE_MONOTONE_CUBIC.bind(xValues, DoubleArray.ofUnsafe(yValues1Dw), DISCOUNT_FACTOR_QUADRATIC_LEFT_ZERO_RATE, PRODUCT_LINEAR); for (int i = 2; i < nKeys; ++i) { double exp = 0.5 * (bciUp.interpolate(xKeys[i]) - bciDw.interpolate(xKeys[i])) / EPS / yValues[k].get(j); assertEquals(bci.parameterSensitivity(xKeys[i]).get(j), exp, Math.Max(Math.Abs(yValues[k].get(j)) * EPS, EPS) * 1e3); //because gradient is NOT exact TODO } yValues1Up[j] = yValues[k].get(j); yValues1Dw[j] = yValues[k].get(j); } } }
//------------------------------------------------------------------------- public virtual void test_firstNode() { BoundCurveInterpolator bci = INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); assertEquals(bci.interpolate(0.0), 3.0, TOL); assertEquals(bci.parameterSensitivity(0.0).get(0), 1d, TOL); assertEquals(bci.parameterSensitivity(0.0).get(1), 0d, TOL); }
public virtual void test_lastNode() { BoundCurveInterpolator bci = NATURAL_CUBLIC_SPLINE_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); assertEquals(bci.interpolate(5.0), 2.0, TOL); assertEquals(bci.parameterSensitivity(5.0).get(X_DATA.size() - 2), 0d, TOL); assertEquals(bci.parameterSensitivity(5.0).get(X_DATA.size() - 1), 1d, TOL); }
public virtual void noRightTest() { BoundCurveInterpolator bci = LINEAR.bind(X_DATA, Y_DATA, DISCOUNT_FACTOR_QUADRATIC_LEFT_ZERO_RATE, DISCOUNT_FACTOR_QUADRATIC_LEFT_ZERO_RATE); assertThrowsIllegalArg(() => bci.interpolate(10d)); assertThrowsIllegalArg(() => bci.firstDerivative(10d)); assertThrowsIllegalArg(() => bci.parameterSensitivity(10d)); }
//------------------------------------------------------------------------- public virtual void test_interpolation() { BoundCurveInterpolator bci = LL_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); for (int i = 0; i < X_DATA.size(); i++) { assertEquals(bci.interpolate(X_DATA.get(i)), Y_DATA.get(i), TOL); } // log-linear same as linear where y-values have had log applied BoundCurveInterpolator bciLinear = CurveInterpolators.LINEAR.bind(X_DATA, Y_DATA_LOG, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); assertEquals(Math.Log(bci.interpolate(0.2)), bciLinear.interpolate(0.2), EPS); assertEquals(Math.Log(bci.interpolate(0.8)), bciLinear.interpolate(0.8), EPS); assertEquals(Math.Log(bci.interpolate(1.1)), bciLinear.interpolate(1.1), EPS); assertEquals(Math.Log(bci.interpolate(2.1)), bciLinear.interpolate(2.1), EPS); assertEquals(Math.Log(bci.interpolate(3.4)), bciLinear.interpolate(3.4), EPS); }
public virtual void test_extrapolation() { BoundCurveInterpolator bci = CurveInterpolators.DOUBLE_QUADRATIC.bind(X_DATA, Y_DATA, LINEAR_EXTRAPOLATOR, LINEAR_EXTRAPOLATOR); for (int i = 0; i < X_TEST.size(); i++) { assertEquals(bci.interpolate(X_TEST.get(i)), Y_TEST.get(i), 1e-6); } }
public virtual void test_lastNode() { BoundCurveInterpolator bci = LINEAR_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); assertEquals(bci.interpolate(5.0), 2.0, TOL); assertEquals(bci.firstDerivative(5.0), bci.firstDerivative(4.99), TOL); assertEquals(bci.parameterSensitivity(5.0).get(X_DATA.size() - 2), 0d, TOL); assertEquals(bci.parameterSensitivity(5.0).get(X_DATA.size() - 1), 1d, TOL); }
public virtual void test_allNodes() { BoundCurveInterpolator bci = LL_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); for (int i = 0; i < X_DATA.size(); i++) { assertEquals(bci.interpolate(X_DATA.get(i)), Y_DATA.get(i), TOL); } }
//------------------------------------------------------------------------- public virtual void test_interpolation() { BoundCurveInterpolator bci = DQ_INTERPOLATOR.bind(X_DATA, Y_DATA, FLAT_EXTRAPOLATOR, FLAT_EXTRAPOLATOR); for (int i = 0; i < X_TEST.Length; i++) { assertEquals(bci.interpolate(X_TEST[i]), Y_TEST[i], 1e-8); } }
internal Bound(DoubleArray xValues, DoubleArray yValues, BoundCurveInterpolator interpolator) { this.nodeCount = xValues.size(); this.firstXValue = xValues.get(0); this.firstYValue = yValues.get(0); this.firstYValueLog = Math.Log(firstYValue); this.lastXValue = xValues.get(nodeCount - 1); this.lastYValue = yValues.get(nodeCount - 1); this.lastYValueLog = Math.Log(lastYValue); this.eps = EPS * (lastXValue - firstXValue); // left this.leftGradient = interpolator.firstDerivative(firstXValue) / interpolator.interpolate(firstXValue); this.leftResValueInterpolator = interpolator.interpolate(firstXValue + eps); this.leftSens = interpolator.parameterSensitivity(firstXValue + eps); // right this.rightGradient = interpolator.firstDerivative(lastXValue) / interpolator.interpolate(lastXValue); this.rightResValueInterpolator = interpolator.interpolate(lastXValue - eps); this.rightSens = interpolator.parameterSensitivity(lastXValue - eps); }
public virtual void test_extrapolation() { BoundCurveInterpolator bind = CurveInterpolators.DOUBLE_QUADRATIC.bind(X_DATA, Y_DATA, EXTRAP, EXTRAP); double gradLeft = (bind.interpolate(X_DATA.get(0) + EPS) * (X_DATA.get(0) + EPS) - Y_DATA.get(0) * X_DATA.get(0)) / EPS; for (int i = 0; i < X_LEFT_TEST.size(); ++i) { double xyLeft = gradLeft * (X_LEFT_TEST.get(i) - X_DATA.get(0)) + Y_DATA.get(0) * X_DATA.get(0); double expected = xyLeft / X_LEFT_TEST.get(i); assertEquals(bind.interpolate(X_LEFT_TEST.get(i)), expected, 10d * Math.Abs(expected) * EPS); } double gradRight = (Y_DATA.get(SIZE - 1) * X_DATA.get(SIZE - 1) - bind.interpolate(X_DATA.get(SIZE - 1) - EPS) * (X_DATA.get(SIZE - 1) - EPS)) / EPS; for (int i = 0; i < X_RIGHT_TEST.size(); ++i) { double xyRight = gradRight * (X_RIGHT_TEST.get(i) - X_DATA.get(SIZE - 1)) + Y_DATA.get(SIZE - 1) * X_DATA.get(SIZE - 1); double expected = xyRight / X_RIGHT_TEST.get(i); assertEquals(bind.interpolate(X_RIGHT_TEST.get(i)), expected, 10d * Math.Abs(expected) * EPS); } }