/**
* 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 org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import com.opengamma.strata.collect.array.DoubleArray;
/**
* Test {@link LogLinearCurveExtrapolator}.
*/
@Test
public class LogLinearCurveExtrapolatorTest {
private static final CurveExtrapolator LL_EXTRAPOLATOR = LogLinearCurveExtrapolator.INSTANCE;
private static final double EPS = 1.e-7;
private static final double TOL = 1.e-12;
public void test_basics() {
assertEquals(LL_EXTRAPOLATOR.getName(), LogLinearCurveExtrapolator.NAME);
assertEquals(LL_EXTRAPOLATOR.toString(), LogLinearCurveExtrapolator.NAME);
}
public void sameIntervalsTest() {
DoubleArray xValues = DoubleArray.of(-1., 0., 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, 1.001, 1.001),
DoubleArray.of(11., 11., 8., 5., 1.001, 1.001, 5., 8., 11., 11.),
DoubleArray.of(1.001, 1.001, 5., 8., 9., 9., 11., 12., 18., 18.)
};
int nData = xValues.size();
int nKeys = 100 * nData;
double[] xKeys = new double[nKeys];
double xMin = xValues.get(0) - 2.2;
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 = LogLinearCurveExtrapolator.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, extrap);
double firstStart = bci.firstDerivative(xValues.get(0)) / bci.interpolate(xValues.get(0));
double firstEnd = bci.firstDerivative(xValues.get(nData - 1)) / bci.interpolate(xValues.get(nData - 1));
for (int i = 0; i < nKeys; ++i) {
// Check log-linearity
if (xKeys[i] <= xValues.get(0)) {
assertEquals(bci.firstDerivative(xKeys[i]) / bci.interpolate(xKeys[i]), firstStart, TOL);
} else {
if (xKeys[i] >= xValues.get(nData - 1)) {
assertEquals(bci.firstDerivative(xKeys[i]) / bci.interpolate(xKeys[i]), firstEnd, TOL);
}
}
}
// Check C0 continuity
assertEquals(bci.interpolate(xValues.get(nData - 1) + 1.e-14), bci.interpolate(xValues.get(nData - 1)), TOL);
assertEquals(bci.interpolate(xValues.get(0) - 1.e-14), bci.interpolate(xValues.get(0)), TOL);
// Check C1 continuity
assertEquals(bci.firstDerivative(xValues.get(nData - 1) + TOL) / bci.interpolate(xValues.get(nData - 1) + TOL),
bci.firstDerivative(xValues.get(nData - 1)) / bci.interpolate(xValues.get(nData - 1)), TOL);
assertEquals(bci.firstDerivative(xValues.get(0) - TOL) / bci.interpolate(xValues.get(0) - TOL),
bci.firstDerivative(xValues.get(0)) / bci.interpolate(xValues.get(0)), 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) * (1. + EPS);
yValues1Dw[j] = yValues[k].get(j) * (1. - EPS);
BoundCurveInterpolator bciUp = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind(
xValues, DoubleArray.ofUnsafe(yValues1Up), extrap, extrap);
BoundCurveInterpolator bciDw = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind(
xValues, DoubleArray.ofUnsafe(yValues1Dw), extrap, extrap);
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(bci.parameterSensitivity(xKeys[i]).get(j), res1,
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 = -xValues.get(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 = LogLinearCurveExtrapolator.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, extrap);
double firstStart = bci.firstDerivative(xValues.get(0)) / bci.interpolate(xValues.get(0));
double firstEnd = bci.firstDerivative(xValues.get(nData - 1)) / bci.interpolate(xValues.get(nData - 1));
for (int i = 0; i < nKeys; ++i) {
// Check log-linearity
if (xKeys[i] <= xValues.get(0)) {
assertEquals(firstStart, bci.firstDerivative(xKeys[i]) / bci.interpolate(xKeys[i]), TOL);
} else {
if (xKeys[i] >= xValues.get(nData - 1)) {
assertEquals(firstEnd, bci.firstDerivative(xKeys[i]) / bci.interpolate(xKeys[i]), TOL);
}
}
}
// Check C0 continuity
assertEquals(bci.interpolate(xValues.get(nData - 1) + 1.e-14), bci.interpolate(xValues.get(nData - 1)), TOL);
assertEquals(bci.interpolate(xValues.get(0) - 1.e-14), bci.interpolate(xValues.get(0)), TOL);
// Check C1 continuity
assertEquals(
bci.firstDerivative(xValues.get(nData - 1) + TOL) / bci.interpolate(xValues.get(nData - 1) + TOL),
bci.firstDerivative(xValues.get(nData - 1)) / bci.interpolate(xValues.get(nData - 1)), TOL);
assertEquals(
bci.firstDerivative(xValues.get(0) - TOL) / bci.interpolate(xValues.get(0) - TOL),
bci.firstDerivative(xValues.get(0)) / bci.interpolate(xValues.get(0)), 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) * (1. + EPS);
yValues1Dw[j] = yValues[k].get(j) * (1. - EPS);
BoundCurveInterpolator bciUp = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind(
xValues, DoubleArray.ofUnsafe(yValues1Up), extrap, extrap);
BoundCurveInterpolator bciDw = CurveInterpolators.LOG_NATURAL_SPLINE_MONOTONE_CUBIC.bind(
xValues, DoubleArray.ofUnsafe(yValues1Dw), extrap, extrap);
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_serialization() {
assertSerialization(LL_EXTRAPOLATOR);
}
}