Package com.opengamma.analytics.financial.model.finitedifference.applications

Source Code of com.opengamma.analytics.financial.model.finitedifference.applications.TwoStateMarkovChainSABRFitterTest

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

import java.util.ArrayList;
import java.util.List;

import org.testng.annotations.Test;

import com.opengamma.analytics.financial.model.finitedifference.BoundaryCondition;
import com.opengamma.analytics.financial.model.finitedifference.ConvectionDiffusionPDE1DCoefficients;
import com.opengamma.analytics.financial.model.finitedifference.ConvectionDiffusionPDE1DFullCoefficients;
import com.opengamma.analytics.financial.model.finitedifference.ConvectionDiffusionPDE1DStandardCoefficients;
import com.opengamma.analytics.financial.model.finitedifference.DirichletBoundaryCondition;
import com.opengamma.analytics.financial.model.finitedifference.ExponentialMeshing;
import com.opengamma.analytics.financial.model.finitedifference.HyperbolicMeshing;
import com.opengamma.analytics.financial.model.finitedifference.MeshingFunction;
import com.opengamma.analytics.financial.model.finitedifference.PDE1DDataBundle;
import com.opengamma.analytics.financial.model.finitedifference.PDEFullResults1D;
import com.opengamma.analytics.financial.model.finitedifference.PDEGrid1D;
import com.opengamma.analytics.financial.model.finitedifference.ThetaMethodFiniteDifference;
import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurve;
import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption;
import com.opengamma.analytics.financial.model.volatility.local.DupireLocalVolatilityCalculator;
import com.opengamma.analytics.financial.model.volatility.local.LocalVolatilitySurfaceStrike;
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.surface.BlackVolatilitySurfaceStrike;
import com.opengamma.analytics.math.curve.ConstantDoublesCurve;
import com.opengamma.analytics.math.function.Function;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.matrix.DoubleMatrix1D;
import com.opengamma.analytics.math.statistics.leastsquare.LeastSquareResultsWithTransform;
import com.opengamma.analytics.math.surface.FunctionalDoublesSurface;
import com.opengamma.util.tuple.ObjectsPair;
import com.opengamma.util.tuple.Pair;

/**
*
*/
public class TwoStateMarkovChainSABRFitterTest {

  private static final PDE1DCoefficientsProvider PDE_PROVIDER = new PDE1DCoefficientsProvider();
  private static final InitialConditionsProvider INITAL_CONDITION_PROVIDER = new InitialConditionsProvider();
  private static final Function1D<Double, Double> ALPHA;
  private static final double BETA = 0.5;
  private static final double RHO = -0.0;
  private static final Function1D<Double, Double> NU;
  private static final double T = 5.0;
  private static final double SPOT = 1.0;
  private static final ForwardCurve FORWARD_CURVE;
  //private static final YieldCurve YIELD_CURVE;
  private static final double RATE = 0.0;
  private static final Function<Double, Double> SABR_VOL_FUNCTION;
  private static final List<double[]> EXPIRY_AND_STRIKES = new ArrayList<>();
  private static final List<Pair<double[], Double>> SABR_VOLS;

  static {
    EXPIRY_AND_STRIKES.add(new double[] {1. / 12, 0.925 });
    EXPIRY_AND_STRIKES.add(new double[] {1. / 12, 1.0 });
    EXPIRY_AND_STRIKES.add(new double[] {1. / 12, 1.075 });
    EXPIRY_AND_STRIKES.add(new double[] {0.5, 0.9 });
    EXPIRY_AND_STRIKES.add(new double[] {0.5, 0.95 });
    EXPIRY_AND_STRIKES.add(new double[] {0.5, 1.0 });
    EXPIRY_AND_STRIKES.add(new double[] {0.5, 1.05 });
    EXPIRY_AND_STRIKES.add(new double[] {0.5, 1.1 });
    EXPIRY_AND_STRIKES.add(new double[] {1, 0.8 });
    EXPIRY_AND_STRIKES.add(new double[] {1, 0.9 });
    EXPIRY_AND_STRIKES.add(new double[] {1, 1.0 });
    EXPIRY_AND_STRIKES.add(new double[] {1, 1.1 });
    EXPIRY_AND_STRIKES.add(new double[] {2, 0.7 });
    EXPIRY_AND_STRIKES.add(new double[] {2, 0.9 });
    EXPIRY_AND_STRIKES.add(new double[] {2, 1.0 });
    EXPIRY_AND_STRIKES.add(new double[] {2, 1.2 });
    EXPIRY_AND_STRIKES.add(new double[] {2, 1.4 });
    EXPIRY_AND_STRIKES.add(new double[] {3, 1.0 });
    EXPIRY_AND_STRIKES.add(new double[] {4, 1.0 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 0.4 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 0.6 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 0.8 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 0.9 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 1.0 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 2.0 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 2.5 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 3.0 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 3.5 });
    EXPIRY_AND_STRIKES.add(new double[] {5, 4.0 });

    final Function1D<Double, Double> fwd = new Function1D<Double, Double>() {

      @Override
      public Double evaluate(final Double t) {
        return SPOT * Math.exp(t * RATE);
      }
    };

    FORWARD_CURVE = new ForwardCurve(fwd);
    //    YIELD_CURVE = new YieldCurve(ConstantDoublesCurve.from(RATE));

    ALPHA = new Function1D<Double, Double>() {
      double a = 0.0;
      double b = 0.0;
      double c = 0.0;
      double d = 0.2;

      @Override
      public Double evaluate(final Double t) {
        final double atmVol = (a + b * t) * Math.exp(-c * t) + d;
        return atmVol * Math.pow(SPOT, 1 - BETA);
      }
    };

    NU = new Function1D<Double, Double>() {
      double a = 0.6;
      double b = 0.0;
      double c = 1.0;
      double d = 0.3;

      @Override
      public Double evaluate(final Double t) {
        return (a + b * t) * Math.exp(-c * t) + d;
      }
    };

    SABR_VOL_FUNCTION = new Function<Double, Double>() {
      SABRHaganVolatilityFunction hagan = new SABRHaganVolatilityFunction();

      @SuppressWarnings("synthetic-access")
      @Override
      public Double evaluate(final Double... tk) {
        final double t = tk[0];
        final double k = tk[1];
        final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, true);
        final Function1D<SABRFormulaData, Double> func = hagan.getVolatilityFunction(option, FORWARD_CURVE.getForward(t));
        final SABRFormulaData data = new SABRFormulaData(ALPHA.evaluate(t), BETA, RHO, NU.evaluate(t));
        return func.evaluate(data);
      }
    };

    SABR_VOLS = new ArrayList<>(EXPIRY_AND_STRIKES.size());
    for (int i = 0; i < EXPIRY_AND_STRIKES.size(); i++) {
      final double[] tk = EXPIRY_AND_STRIKES.get(i);
      final Pair<double[], Double> pair = new ObjectsPair<>(tk, SABR_VOL_FUNCTION.evaluate(tk[0], tk[1]));
      SABR_VOLS.add(pair);
    }

  }

  @Test(enabled = false)
  public void dumpSurfaceTest() {

    PDEUtilityTools.printSurface("dumpSurfaceTest", FunctionalDoublesSurface.from(SABR_VOL_FUNCTION), 0, 5.0, SPOT / 4.0, 4.0 * SPOT);
  }

  @Test
  (enabled = false)
  public void test() {
    final DoubleMatrix1D initialGuess = new DoubleMatrix1D(new double[] {0.2, 0.3, 0.2, 2.0, 0.95, 0.8 });
    final TwoStateMarkovChainFitter fitter = new TwoStateMarkovChainFitter();
    final LeastSquareResultsWithTransform res = fitter.fit(FORWARD_CURVE, SABR_VOLS, initialGuess);
    System.out.println("chi^2:" + res.getChiSq() + "\n params: " + res.getModelParameters().toString());
  }

  //TODO this test does not work for the ConvectionDiffusionPDE1DStandardCoefficients case
  @Test
  (enabled = false)
  public void fokkerPlankTest() {
    final DupireLocalVolatilityCalculator cal = new DupireLocalVolatilityCalculator(1e-4);

    final BlackVolatilitySurfaceStrike volSurface = new BlackVolatilitySurfaceStrike(FunctionalDoublesSurface.from(SABR_VOL_FUNCTION));

    final LocalVolatilitySurfaceStrike localVol = cal.getLocalVolatility(volSurface, new ForwardCurve(SPOT, RATE));

    //    final ZZConvectionDiffusionPDEDataBundle db1 = LocalVolDensity.getConvectionDiffusionPDEDataBundle(FORWARD_CURVE, localVol);
    //    final ExtendedConvectionDiffusionPDEDataBundle db2 = LocalVolDensity.getExtendedConvectionDiffusionPDEDataBundle(FORWARD_CURVE, localVol);

    final int tNodes = 50;
    final int xNodes = 100;
    final BoundaryCondition lower = new DirichletBoundaryCondition(0.0, 0.0);
    final BoundaryCondition upper = new DirichletBoundaryCondition(0.0, 10 * FORWARD_CURVE.getForward(T));
    final MeshingFunction timeMesh = new ExponentialMeshing(0, T, tNodes, 5.0);
    final MeshingFunction spaceMesh = new HyperbolicMeshing(0.0, upper.getLevel(), SPOT, xNodes, 0.01);
    final PDEGrid1D grid = new PDEGrid1D(timeMesh, spaceMesh);

    final ConvectionDiffusionPDE1DFullCoefficients pde1 = PDE_PROVIDER.getFokkerPlank(ConstantDoublesCurve.from(RATE), localVol);
    final ConvectionDiffusionPDE1DStandardCoefficients pde2 = PDE_PROVIDER.getFokkerPlankInStandardCoefficients(ConstantDoublesCurve.from(RATE), localVol);
    final Function1D<Double, Double> initalCondition = INITAL_CONDITION_PROVIDER.getLogNormalDensity(SPOT, 0.01, 0.2);

    final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db1 = new PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients>(pde1, initalCondition, lower, upper, grid);
    final PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients> db2 = new PDE1DDataBundle<ConvectionDiffusionPDE1DCoefficients>(pde2, initalCondition, lower, upper, grid);

    final ThetaMethodFiniteDifference thetaMethod = new ThetaMethodFiniteDifference(0.5, true);

    final PDEFullResults1D res1 = (PDEFullResults1D) thetaMethod.solve(db1);
    final PDEFullResults1D res2 = (PDEFullResults1D) thetaMethod.solve(db2);

    PDEUtilityTools.printSurface("State 1 density", res1);
    PDEUtilityTools.printSurface("State 2 density", res2);
  }

  //TODO need to have real tests here rather than print a lot of surfaces
  @Test
  (enabled = false)
  public void localVolFitTest() {
    final DoubleMatrix1D initialGuess = new DoubleMatrix1D(new double[] {0.2, 0.3, 0.2, 2.0, 0.95, 0.8 });
    final TwoStateMarkovChainLocalVolFitter fitter = new TwoStateMarkovChainLocalVolFitter(true);
    fitter.fit(FORWARD_CURVE, new BlackVolatilitySurfaceStrike(FunctionalDoublesSurface.from(SABR_VOL_FUNCTION)), SABR_VOLS, initialGuess);
    // System.out.println("chi^2:" + res.getChiSq() + "\n params: " + res.getParameters().toString());
  }

  @Test(enabled = false)
  public void localVolTest() {
    final DupireLocalVolatilityCalculator cal = new DupireLocalVolatilityCalculator();

    final BlackVolatilitySurfaceStrike volSurface = new BlackVolatilitySurfaceStrike(FunctionalDoublesSurface.from(SABR_VOL_FUNCTION));
    final LocalVolatilitySurfaceStrike localVol = cal.getLocalVolatility(volSurface, new ForwardCurve(SPOT, RATE));

    PDEUtilityTools.printSurface("localVolTest", localVol.getSurface(), 0, 5.0, SPOT / 4.0, SPOT * 4.0);
  }

}
TOP

Related Classes of com.opengamma.analytics.financial.model.finitedifference.applications.TwoStateMarkovChainSABRFitterTest

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.