/** * Creates an instance with UFR. * * @param ufr the UFR * @return the instance */ public static SmithWilsonCurveFunction of(double ufr) { return new SmithWilsonCurveFunction(ufr); }
int years = 121; Function<Double, Double> derivFunc = DERIVATIVE.differentiate( x -> SW_FUNCTION.value(x, alpha, nodes, weights), x -> (x >= 0d)); double dfPrev = 1d; for (int i = 0; i < years; ++i) { double t = (double) i; double dfCmp = SW_FUNCTION.value(t, alpha, nodes, weights); assertEquals(dfCmp, dfExp[i], TOL); double derivCmp = SW_FUNCTION.firstDerivative(t, alpha, nodes, weights); double derivExp = derivFunc.apply(t); assertEquals(derivCmp, derivExp, EPS); DoubleArray paramSensiCmp = SW_FUNCTION.parameterSensitivity(t, alpha, nodes); Function<DoubleArray, DoubleArray> paramSensiFunc = PARAM_SENSI.differentiate(w -> SW_FUNCTION.value(t, alpha, nodes, w)); DoubleArray paramSensiExp = paramSensiFunc.apply(weights); assertTrue(DoubleArrayMath.fuzzyEquals(paramSensiCmp.toArray(), paramSensiExp.toArray(), EPS));
/** * Computes the sensitivity of the Smith-Wilson curve function to weights parameters at a x value. * <p> * The {@code nodes} must be sorted in ascending order. * * @param x the x value * @param alpha the alpha parameter * @param nodes the nodes * @return the value */ public DoubleArray parameterSensitivity(double x, double alpha, DoubleArray nodes) { int size = nodes.size(); double[] res = new double[size]; double expOmega = Math.exp(-omega * x); int bound = x < nodes.get(0) ? 0 : FunctionUtils.getLowerBoundIndex(nodes, x) + 1; for (int i = 0; i < bound; ++i) { res[i] = expOmega * wilsonFunctionLeft(x, alpha, nodes.get(i)); } for (int i = bound; i < size; ++i) { res[i] = expOmega * wilsonFunctionRight(x, alpha, nodes.get(i)); } return DoubleArray.ofUnsafe(res); }
@Override public Double apply(DoubleArray t, Double u) { return SW_CURVE.firstDerivative(u, ALPHA, DoubleArray.copyOf(NODE_TIMES), t); } };
@Override public DoubleArray apply(DoubleArray t, Double u) { return SW_CURVE.parameterSensitivity(u, ALPHA, DoubleArray.copyOf(NODE_TIMES)); } };
@Override public Double apply(DoubleArray t, Double u) { return SW_CURVE.value(u, ALPHA, DoubleArray.copyOf(NODE_TIMES), t); } };
/** * Computes the gradient of the Smith-Wilson curve function at a x value. * <p> * The {@code nodes} must be sorted in ascending order and coherent to {@code weights}. * * @param x the x value * @param alpha the alpha parameter * @param nodes the nodes * @param weights the weights * @return the gradient */ public double firstDerivative(double x, double alpha, DoubleArray nodes, DoubleArray weights) { int size = nodes.size(); ArgChecker.isTrue(size == weights.size(), "nodes and weights must be the same size"); double res = -omega; int bound = x < nodes.get(0) ? 0 : FunctionUtils.getLowerBoundIndex(nodes, x) + 1; for (int i = 0; i < bound; ++i) { res += weights.get(i) * wilsonFunctionLeftDerivative(x, alpha, nodes.get(i)); } for (int i = bound; i < size; ++i) { res += weights.get(i) * wilsonFunctionRightDerivative(x, alpha, nodes.get(i)); } res *= Math.exp(-omega * x); return res; }
public void test_gap() { DoubleArray nodes = DoubleArray.of(3d, 5d, 7d, 10d, 15d, 20d, 30d); double testAlpha = 0.05; DoubleArray weights = DoubleArray.of(87.2581459896248, -90.049408220743, 16.5225834204242, 20.401521178462, -12.3472386476547, 5.04900954653571, -1.82365099870708); double gapExp = 4.27089481442022E-03 + ONE_BP; double gapCmp = SmithWilsonCurveFunction.gap(60d, testAlpha, nodes, weights); assertEquals(gapCmp, gapExp, TOL); }
/** * Evaluates the Smith-Wilson curve function at a x value. * <p> * The {@code nodes} must be sorted in ascending order and coherent to {@code weights}. * * @param x the x value * @param alpha the alpha parameter * @param nodes the nodes * @param weights the weights * @return the value */ public double value(double x, double alpha, DoubleArray nodes, DoubleArray weights) { int size = nodes.size(); ArgChecker.isTrue(size == weights.size(), "nodes and weights must be the same size"); double res = 1d; int bound = x < nodes.get(0) ? 0 : FunctionUtils.getLowerBoundIndex(nodes, x) + 1; for (int i = 0; i < bound; ++i) { res += weights.get(i) * wilsonFunctionLeft(x, alpha, nodes.get(i)); } for (int i = bound; i < size; ++i) { res += weights.get(i) * wilsonFunctionRight(x, alpha, nodes.get(i)); } res *= Math.exp(-omega * x); return res; }