Package com.opengamma.analytics.financial.model.volatility.smile.fitting

Source Code of com.opengamma.analytics.financial.model.volatility.smile.fitting.SABRModelFitterTest

/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.volatility.smile.fitting;

import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;

import java.util.Arrays;
import java.util.BitSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.Test;

import cern.jet.random.engine.MersenneTwister;

import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.BlackFunctionData;
import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption;
import com.opengamma.analytics.financial.model.volatility.smile.function.SABRFormulaData;
import com.opengamma.analytics.financial.model.volatility.smile.function.SABRHaganVolatilityFunction;
import com.opengamma.analytics.financial.model.volatility.smile.function.VolatilityFunctionProvider;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.statistics.distribution.NormalDistribution;
import com.opengamma.analytics.math.statistics.distribution.ProbabilityDistribution;
import com.opengamma.analytics.math.statistics.leastsquare.LeastSquareResultsWithTransform;
import com.opengamma.util.monitor.OperationTimer;

/**
*
*/
public class SABRModelFitterTest {

  protected Logger _logger = LoggerFactory.getLogger(SABRModelFitterTest.class);
  protected int _hotspotWarmupCycles = 0;
  protected int _benchmarkCycles = 1;
  private static final double F = 0.03;
  private static final double T = 7.0;
  private static final double ALPHA = 0.05;
  private static final double BETA = 0.5;
  private static double RHO = -0.3;
  private static double NU = 0.2;

  private static final EuropeanOptionMarketData[] MARKETDATA;
  private static final EuropeanOptionMarketData[] NOISY_MARKETDATA;
  private static double[] STRIKES;
  private static double[] CLEAN_VOLS;
  private static double[] NOISY_VOLS;
  private static double[] ERRORS;
  private static final SABRFormulaData SABR_DATA = new SABRFormulaData(ALPHA, BETA, RHO, NU);
  private static VolatilityFunctionProvider<SABRFormulaData> SABR = new SABRHaganVolatilityFunction();
  private static ProbabilityDistribution<Double> RANDOM = new NormalDistribution(0, 1, new MersenneTwister(12));
  private static SmileModelFitter<SABRFormulaData> FITTER;
  private static SmileModelFitter<SABRFormulaData> NOISY_FITTER;

  static {
    STRIKES = new double[] {0.005, 0.01, 0.02, 0.03, 0.04, 0.05, 0.07};
    final int n = STRIKES.length;
    MARKETDATA = new EuropeanOptionMarketData[n];
    NOISY_MARKETDATA = new EuropeanOptionMarketData[n];
    CLEAN_VOLS = new double[n];
    NOISY_VOLS = new double[n];
    ERRORS = new double[n];
    Arrays.fill(ERRORS, 0.0001); //1bps error

    for (int i = 0; i < n; i++) {
      final EuropeanVanillaOption option = new EuropeanVanillaOption(STRIKES[i], T, true);
      CLEAN_VOLS[i] = SABR.getVolatilityFunction(option, F).evaluate(SABR_DATA);
      NOISY_VOLS[i] = CLEAN_VOLS[i] + RANDOM.nextRandom() * ERRORS[i];
    }

    FITTER = new SABRModelFitter(F, STRIKES, T, CLEAN_VOLS, ERRORS, SABR);
    NOISY_FITTER = new SABRModelFitter(F, STRIKES, T, NOISY_VOLS, ERRORS, SABR);
  }

  @Test
  public void testExactFit() {

    final double[] start = new double[] {0.1, 0.7, 0.0, 0.3};
    final LeastSquareResultsWithTransform results = FITTER.solve(new DoubleMatrix1D(start));
    final double[] res = results.getModelParameters().getData();
    final double eps = 1e-6;
    assertEquals(ALPHA, res[0], eps);
    assertEquals(BETA, res[1], eps);
    assertEquals(RHO, res[2], eps);
    assertEquals(NU, res[3], eps);
    assertEquals(0.0, results.getChiSq(), eps);
  }

  @Test
  public void testExactFitOddStart() {
    final double[] start = new double[] {0.01, 0.99, 0.9, 0.4};
    final LeastSquareResultsWithTransform results = FITTER.solve(new DoubleMatrix1D(start));
    final double[] res = results.getModelParameters().getData();
    final double eps = 1e-6;
    assertEquals(ALPHA, res[0], eps);
    assertEquals(BETA, res[1], eps);
    assertEquals(RHO, res[2], eps);
    assertEquals(NU, res[3], eps);
    assertEquals(0.0, results.getChiSq(), eps);
  }

  @Test
  public void testExactFitWithFixedBeta() {
    final double[] start = new double[] {0.1, 0.5, 0.0, 0.3};
    final BitSet fixed = new BitSet();
    fixed.set(1);
    final LeastSquareResultsWithTransform results = FITTER.solve(new DoubleMatrix1D(start), fixed);
    final double[] res = results.getModelParameters().getData();
    final double eps = 1e-6;
    assertEquals(ALPHA, res[0], eps);
    assertEquals(BETA, res[1], eps);
    assertEquals(RHO, res[2], eps);
    assertEquals(NU, res[3], eps);
    assertEquals(0.0, results.getChiSq(), eps);
  }

  @Test
  public void testFitWithFixedWrongBeta() {

    final double[] start = new double[] {0.1, 0.8, 0.0, 0.3};
    final BitSet fixed = new BitSet();
    fixed.set(1);
    final LeastSquareResultsWithTransform results = FITTER.solve(new DoubleMatrix1D(start), fixed);
    final double[] res = results.getModelParameters().getData();
    final double eps = 1e-6;
    assertEquals(0.8, res[1], eps);

    final double bpError = 35.0; //35 bps error
    final int n = MARKETDATA.length;
    final double exChi2 = bpError * bpError * n;
    assertTrue("chi^2 " + results.getChiSq(), results.getChiSq() < exChi2);
  }

  @Test
  public void testNoisyFit() {

    final double[] start = new double[] {0.1, 0.7, 0.0, 0.3};
    final LeastSquareResultsWithTransform results = NOISY_FITTER.solve(new DoubleMatrix1D(start));
    final double[] res = results.getModelParameters().getData();
    final double eps = 1e-2;
    assertEquals(ALPHA, res[0], eps);
    assertEquals(BETA, res[1], eps);
    assertEquals(RHO, res[2], eps);
    assertEquals(NU, res[3], eps);
    assertTrue(results.getChiSq() < 7);
  }

  //SABRModelFitterTest - 813ms-processing 1000 cycles fitting SABR smile
  //Disable test before commit
  @Test(enabled = false)
  public void fitTimeTest() {
    final int hotspotWarmupCycles = 200;
    final int benchmarkCycles = 1000;
    for (int i = 0; i < hotspotWarmupCycles; i++) {
      testNoisyFit();
    }
    if (benchmarkCycles > 0) {
      final OperationTimer timer = new OperationTimer(_logger, "processing {} cycles fitting SABR smile", benchmarkCycles);
      for (int i = 0; i < benchmarkCycles; i++) {
        testNoisyFit();
      }
      timer.finished();
    }
  }

  //SABRModelFitterTest - 1555ms-processing 1000 cycles fitting SABR smile - old
  @SuppressWarnings("deprecation")
  @Test
  public void testOldMethod() {
    //set to 1 and 0 before commit
    final int hotspotWarmupCycles = 1;
    final int benchmarkCycles = 0;
    final double[] start = new double[] {0.1, 0.7, 0.0, 0.3};
    final BitSet fixed = new BitSet();
    final SABRNonLinearLeastSquareFitter fitter = new SABRNonLinearLeastSquareFitter(SABR);
    final int n = NOISY_MARKETDATA.length;
    final EuropeanVanillaOption[] options = new EuropeanVanillaOption[n];
    final BlackFunctionData[] data = new BlackFunctionData[n];
    for (int i = 0; i < n; i++) {
      options[i] = new EuropeanVanillaOption(STRIKES[i], T, true);
      data[i] = new BlackFunctionData(F, 1.0, CLEAN_VOLS[i]);
    }
    for (int i = 0; i < hotspotWarmupCycles; i++) {
      doOldTest(options, data, start, fixed, fitter);
    }
    if (benchmarkCycles > 0) {
      final OperationTimer timer = new OperationTimer(_logger, "processing {} cycles fitting SABR smile - old", benchmarkCycles);
      for (int i = 0; i < benchmarkCycles; i++) {
        doOldTest(options, data, start, fixed, fitter);
      }
      timer.finished();
    }

  }

  @SuppressWarnings("deprecation")
  private void doOldTest(final EuropeanVanillaOption[] options, final BlackFunctionData[] data, final double[] start, final BitSet fixed, final SABRNonLinearLeastSquareFitter fitter) {
    final LeastSquareResultsWithTransform lsRes = fitter.getFitResult(options, data, ERRORS, start, fixed);
    final double[] res = lsRes.getModelParameters().getData();
    final double eps = 1e-2;
    assertEquals(ALPHA, res[0], eps);
    assertEquals(BETA, res[1], eps);
    assertEquals(RHO, res[2], eps);
    assertEquals(NU, res[3], eps);
    assertTrue(lsRes.getChiSq() < 7);
  }

}
TOP

Related Classes of com.opengamma.analytics.financial.model.volatility.smile.fitting.SABRModelFitterTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.