/** * 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.financial.model.volatility.discrete.DiscreteVolatilityFunction; import com.opengamma.analytics.financial.model.volatility.discrete.DiscreteVolatilityFunctionProvider; import com.opengamma.analytics.financial.model.volatility.discrete.DiscreteVolatilityFunctionProviderFromVolSurface; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.matrix.DoubleMatrix1D; import com.opengamma.analytics.math.matrix.DoubleMatrix2D; 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 BasisSplineVolatilitySurfaceProviderTest { private static final RandomEngine RANDOM = new MersenneTwister64(MersenneTwister.DEFAULT_SEED); @Test public void test() { final BasisSplineVolatilitySurfaceProvider vsPro = new BasisSplineVolatilitySurfaceProvider(0.0, 0.15, 10, 1, 0.0, 10.0, 7, 1); assertEquals(10 * 7, vsPro.getNumModelParameters()); final DoubleMatrix1D w = new DoubleMatrix1D(70, 0.3); final VolatilitySurface vs = vsPro.getVolSurface(w); final int nSamples = 10; for (int i = 0; i < nSamples; i++) { final double t = 10.0 * RANDOM.nextDouble(); final double k = 0.15 * RANDOM.nextDouble(); assertEquals(0.3, vs.getVolatility(t, k), 1e-15); } } @Test public void sensitivityTest() { final VolatilitySurfaceProvider vsPro = new BasisSplineVolatilitySurfaceProvider(0.0, 0.15, 10, 3, 0.0, 10.0, 7, 2); final DoubleMatrix1D w = new DoubleMatrix1D(vsPro.getNumModelParameters()); for (int i = 0; i < w.getNumberOfElements(); i++) { w.getData()[i] = RANDOM.nextDouble(); } final VolatilitySurface volSurf = vsPro.getVolSurface(w); final Surface<Double, Double, DoubleMatrix1D> senseSurf = vsPro.getParameterSensitivitySurface(w); final Surface<Double, Double, Pair<Double, DoubleMatrix1D>> volAndSenseSurf = vsPro.getVolAndParameterSensitivitySurface(w); final int nSamples = 20; final DoublesPair[] points = new DoublesPair[nSamples]; for (int i = 0; i < nSamples; i++) { final double t = 10.0 * RANDOM.nextDouble(); final double k = 0.15 * RANDOM.nextDouble(); points[i] = DoublesPair.of(t, k); final double vol = volSurf.getVolatility(points[i]); final DoubleMatrix1D sense = senseSurf.getZValue(points[i]); final Pair<Double, DoubleMatrix1D> volAndSense = volAndSenseSurf.getZValue(points[i]); assertEquals(vol, volAndSense.getFirst(), 1e-15); AssertMatrix.assertEqualsVectors(sense, volAndSense.getSecond(), 1e-15); } //create a DiscreteVolatilityFunctionProvider in order to compute the Jacobian for a (random) set the points final DiscreteVolatilityFunctionProvider dvfp = new DiscreteVolatilityFunctionProviderFromVolSurface(vsPro); final DiscreteVolatilityFunction func = dvfp.from(points); final DoubleMatrix2D jac = func.calculateJacobian(w); final DoubleMatrix2D jacFD = func.calculateJacobianViaFD(w); AssertMatrix.assertEqualsMatrix(jacFD, jac, 1e-10); } @Test public void altConstructorTest() { final Function1D<double[], Double> flat = new Function1D<double[], Double>() { @Override public Double evaluate(final double[] x) { return 1.0; } }; final List<Function1D<double[], Double>> functions = new ArrayList<>(); functions.add(flat); final VolatilitySurfaceProvider vsPro = new BasisSplineVolatilitySurfaceProvider(functions); assertEquals(1, vsPro.getNumModelParameters()); final VolatilitySurface vs = vsPro.getVolSurface(new DoubleMatrix1D(0.35)); assertEquals(0.35, vs.getVolatility(4.5, 0.23)); } }