/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.volatility.surface;
import static org.testng.AssertJUnit.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.Test;
import cern.jet.random.engine.MersenneTwister;
import cern.jet.random.engine.MersenneTwister64;
import cern.jet.random.engine.RandomEngine;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.surface.Surface;
import com.opengamma.analytics.util.AssertMatrix;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.tuple.DoublesPair;
import com.opengamma.util.tuple.Pair;
/**
*
*/
@Test(groups = TestGroup.UNIT)
public class BasisSplineVolatilityTermStructureProviderTest {
private static final RandomEngine RANDOM = new MersenneTwister64(MersenneTwister.DEFAULT_SEED);
@Test
public void test() {
//this is just linear interpolation
final BasisSplineVolatilityTermStructureProvider pro = new BasisSplineVolatilityTermStructureProvider(0.0, 10.0, 11, 1);
assertEquals(11, pro.getNumModelParameters());
final DoubleMatrix1D w = new DoubleMatrix1D(0.3, 0.35, 0.4, 0.2, 0.6, 0.6, 0.7, 0.14, 0.26, 0.4, 0.41);
final VolatilitySurface volSurf = pro.getVolSurface(w);
//check values at knots
final int n = w.getNumberOfElements();
for (int i = 0; i < n; i++) {
double vol = volSurf.getVolatility(i, 0.05); //Arbitrary strike
assertEquals(w.getEntry(i), vol, 1e-15);
}
//between knots
assertEquals(0.375, volSurf.getVolatility(1.5, 0.07), 1e-15);
assertEquals(0.65, volSurf.getVolatility(5.5, 0.01), 1e-15);
//check sensitivity
final Surface<Double, Double, DoubleMatrix1D> senseSurf = pro.getParameterSensitivitySurface(w);
for (int i = 0; i < n; i++) {
final DoubleMatrix1D sense = senseSurf.getZValue((double) i, 0.05); //Arbitrary strike
final DoubleMatrix1D expected = new DoubleMatrix1D(n);
expected.getData()[i] = 1.0;
AssertMatrix.assertEqualsVectors(expected, sense, 1e-14);
}
//check value and sense
final Surface<Double, Double, Pair<Double, DoubleMatrix1D>> valueAndSenseSurf = pro.getVolAndParameterSensitivitySurface(w);
final int nSamples = 20;
for (int i = 0; i < nSamples; i++) {
final double t = 10.0 * RANDOM.nextDouble();
final double k = 0.3 * RANDOM.nextDouble();
final DoublesPair tk = DoublesPair.of(t, k);
final Double v = volSurf.getVolatility(tk);
final DoubleMatrix1D sense = senseSurf.getZValue(tk);
final Pair<Double, DoubleMatrix1D> vAndSense = valueAndSenseSurf.getZValue(tk);
assertEquals(v, vAndSense.getFirst(), 1e-15);
AssertMatrix.assertEqualsVectors(sense, vAndSense.getSecond(), 1e-15);
}
}
/**
* represent a vol surface as w0 + w1*exp(-0.2*t)
*/
@Test
public void altConstructorTest() {
final Function1D<Double, Double> f1 = new Function1D<Double, Double>() {
@Override
public Double evaluate(final Double x) {
return 1.0;
}
};
final Function1D<Double, Double> f2 = new Function1D<Double, Double>() {
@Override
public Double evaluate(final Double x) {
return Math.exp(-0.2 * x);
}
};
final List<Function1D<Double, Double>> functions = new ArrayList<>();
functions.add(f1);
functions.add(f2);
final BasisSplineVolatilityTermStructureProvider pro = new BasisSplineVolatilityTermStructureProvider(functions);
final DoubleMatrix1D w = new DoubleMatrix1D(0.2, 0.7);
final VolatilitySurface volSurface = pro.getVolSurface(w);
final double t = 1.3;
assertEquals(w.getEntry(0) * f1.evaluate(t) + w.getEntry(1) * f2.evaluate(t), volSurface.getVolatility(t, 0.05));
}
}