/**
* Copyright (C) 2012 - 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 static org.testng.AssertJUnit.assertFalse;
import java.util.Arrays;
import org.testng.annotations.Test;
import com.opengamma.analytics.financial.model.volatility.smile.fitting.interpolation.GeneralSmileInterpolator;
import com.opengamma.analytics.financial.model.volatility.smile.fitting.interpolation.SmileInterpolatorSABR;
import com.opengamma.analytics.financial.model.volatility.smile.fitting.interpolation.SmileInterpolatorSpline;
import com.opengamma.analytics.financial.model.volatility.smile.fitting.sabr.ForexSmileDeltaSurfaceDataBundle;
import com.opengamma.analytics.financial.model.volatility.smile.fitting.sabr.SmileSurfaceDataBundle;
import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolator;
import com.opengamma.analytics.math.interpolation.CombinedInterpolatorExtrapolatorFactory;
import com.opengamma.analytics.math.interpolation.DoubleQuadraticInterpolator1D;
import com.opengamma.analytics.math.interpolation.Interpolator1D;
import com.opengamma.analytics.math.interpolation.Interpolator1DFactory;
import com.opengamma.analytics.math.interpolation.LinearExtrapolator1D;
import com.opengamma.util.test.TestGroup;
/**
* Test.
*/
@Test(groups = TestGroup.UNIT)
public class VolatilitySurfaceInterpolatorTest {
private static final DoubleQuadraticInterpolator1D INTERPOLATOR_1D = new DoubleQuadraticInterpolator1D();
private static final CombinedInterpolatorExtrapolator EXTRAPOLATOR_1D = new CombinedInterpolatorExtrapolator(INTERPOLATOR_1D, new LinearExtrapolator1D(INTERPOLATOR_1D));
private static final GeneralSmileInterpolator SMILE_INTERPOLATOR = new SmileInterpolatorSpline();
private static final Interpolator1D TIME_INTERPOLATOR = CombinedInterpolatorExtrapolatorFactory.getInterpolator(Interpolator1DFactory.NATURAL_CUBIC_SPLINE,
Interpolator1DFactory.LINEAR_EXTRAPOLATOR);
private static final boolean USE_LOG_TIME = true;
private static final boolean USE_INTEGRATED_VARIANCE = true;
private static final boolean USE_LOG_VALUE = true;
private static final VolatilitySurfaceInterpolator SURFACE_INTERPOLATOR = new VolatilitySurfaceInterpolator(SMILE_INTERPOLATOR, TIME_INTERPOLATOR, USE_LOG_TIME,
USE_INTEGRATED_VARIANCE, USE_LOG_VALUE);
private static final double[] DELTAS = new double[] {0.15, 0.25 };
private static final double[] FORWARDS = new double[] {1.34, 1.35, 1.36, 1.38, 1.4, 1.43, 1.45, 1.48, 1.5, 1.52 };
private static final double[] EXPIRIES = new double[] {7. / 365, 14 / 365., 21 / 365., 1 / 12., 3 / 12., 0.5, 0.75, 1, 5, 10 };
private static final double FLAT_VOL = 0.11;
private static final SmileSurfaceDataBundle FLAT_MARKET_DATA;
private static final int N = EXPIRIES.length;
static {
final double[] atm = new double[N];
Arrays.fill(atm, FLAT_VOL);
final double[][] rr = new double[2][N];
final double[][] butt = new double[2][N];
FLAT_MARKET_DATA = new ForexSmileDeltaSurfaceDataBundle(FORWARDS, EXPIRIES, DELTAS, atm, rr, butt, true, EXTRAPOLATOR_1D);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullSmileInterpolator() {
new VolatilitySurfaceInterpolator(null, TIME_INTERPOLATOR, USE_LOG_TIME, USE_INTEGRATED_VARIANCE, USE_LOG_VALUE);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullTimeInterpolator() {
new VolatilitySurfaceInterpolator(SMILE_INTERPOLATOR, null, USE_LOG_TIME, USE_INTEGRATED_VARIANCE, USE_LOG_VALUE);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullData1() {
SURFACE_INTERPOLATOR.getIndependentSmileFits(null);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullData2() {
SURFACE_INTERPOLATOR.getBumpedVolatilitySurface(null, 0, 0, 0);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullData3() {
SURFACE_INTERPOLATOR.getVolatilitySurface(null);
}
@Test
public void testGetters() {
assertEquals(SURFACE_INTERPOLATOR.useIntegratedVariance(), USE_INTEGRATED_VARIANCE);
assertEquals(SURFACE_INTERPOLATOR.useLogTime(), USE_LOG_TIME);
assertEquals(SURFACE_INTERPOLATOR.useLogValue(), USE_LOG_VALUE);
assertEquals(SURFACE_INTERPOLATOR.getSmileInterpolator(), SMILE_INTERPOLATOR);
assertEquals(SURFACE_INTERPOLATOR.getTimeInterpolator(), TIME_INTERPOLATOR);
}
@Test
public void testHashCodeEquals() {
VolatilitySurfaceInterpolator other = new VolatilitySurfaceInterpolator(SMILE_INTERPOLATOR, TIME_INTERPOLATOR, USE_LOG_TIME, USE_INTEGRATED_VARIANCE, USE_LOG_VALUE);
assertEquals(SURFACE_INTERPOLATOR, other);
assertEquals(SURFACE_INTERPOLATOR.hashCode(), other.hashCode());
other = new VolatilitySurfaceInterpolator(new SmileInterpolatorSABR(), TIME_INTERPOLATOR, USE_LOG_TIME, USE_INTEGRATED_VARIANCE, USE_LOG_VALUE);
assertFalse(other.equals(SURFACE_INTERPOLATOR));
other = new VolatilitySurfaceInterpolator(SMILE_INTERPOLATOR, Interpolator1DFactory.LINEAR_INSTANCE, USE_LOG_TIME, USE_INTEGRATED_VARIANCE, USE_LOG_VALUE);
assertFalse(other.equals(SURFACE_INTERPOLATOR));
other = new VolatilitySurfaceInterpolator(SMILE_INTERPOLATOR, Interpolator1DFactory.LINEAR_INSTANCE, !USE_LOG_TIME, USE_INTEGRATED_VARIANCE, USE_LOG_VALUE);
assertFalse(other.equals(SURFACE_INTERPOLATOR));
other = new VolatilitySurfaceInterpolator(SMILE_INTERPOLATOR, Interpolator1DFactory.LINEAR_INSTANCE, USE_LOG_TIME, !USE_INTEGRATED_VARIANCE, USE_LOG_VALUE);
assertFalse(other.equals(SURFACE_INTERPOLATOR));
other = new VolatilitySurfaceInterpolator(SMILE_INTERPOLATOR, Interpolator1DFactory.LINEAR_INSTANCE, USE_LOG_TIME, USE_INTEGRATED_VARIANCE, !USE_LOG_VALUE);
assertFalse(other.equals(SURFACE_INTERPOLATOR));
}
@Test
public void testFlatSurface() {
final BlackVolatilitySurfaceMoneyness blackVol = SURFACE_INTERPOLATOR.getVolatilitySurface(FLAT_MARKET_DATA);
final double tStart = Math.log(0.01);
final double tEnd = Math.log(10.0);
final double xL = 0.3;
final double xH = 3.5;
for (int i = 0; i < 20; i++) {
final double t = Math.exp(tStart + (tEnd - tStart) * i / 19.);
for (int j = 0; j < 20; j++) {
final double x = xL + (xH - xL) * j / 19.;
final double vol = blackVol.getVolatilityForMoneyness(t, x);
assertEquals("time: " + t + " moneyness: " + x, FLAT_VOL, vol, 1e-7);
}
}
}
}