Package com.opengamma.analytics.financial.model.option.pricing.analytic

Source Code of com.opengamma.analytics.financial.model.option.pricing.analytic.HullWhiteStochasticVolatilityModel

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

import org.apache.commons.lang.Validate;
import org.threeten.bp.ZonedDateTime;

import com.opengamma.analytics.financial.model.option.definition.EuropeanVanillaOptionDefinition;
import com.opengamma.analytics.financial.model.option.definition.HullWhiteStochasticVolatilityModelDataBundle;
import com.opengamma.analytics.financial.model.option.definition.OptionDefinition;
import com.opengamma.analytics.financial.model.option.definition.StandardOptionDataBundle;
import com.opengamma.analytics.financial.model.volatility.surface.VolatilitySurface;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.statistics.distribution.NormalDistribution;
import com.opengamma.analytics.math.statistics.distribution.ProbabilityDistribution;
import com.opengamma.analytics.math.surface.ConstantDoublesSurface;
import com.opengamma.util.CompareUtils;

/**
*
*
*/

public class HullWhiteStochasticVolatilityModel extends AnalyticOptionModel<OptionDefinition, HullWhiteStochasticVolatilityModelDataBundle> {
  private static final ProbabilityDistribution<Double> NORMAL = new NormalDistribution(0, 1);
  private static final BlackScholesMertonModel BSM = new BlackScholesMertonModel();
  private static final double ZERO = 1e-4;

  @Override
  public Function1D<HullWhiteStochasticVolatilityModelDataBundle, Double> getPricingFunction(final OptionDefinition definition) {
    Validate.notNull(definition);
    final Function1D<HullWhiteStochasticVolatilityModelDataBundle, Double> pricingFunction = new Function1D<HullWhiteStochasticVolatilityModelDataBundle, Double>() {

      @SuppressWarnings("synthetic-access")
      @Override
      public Double evaluate(final HullWhiteStochasticVolatilityModelDataBundle data) {
        Validate.notNull(data);
        final ZonedDateTime date = data.getDate();
        final double s = data.getSpot();
        final double k = definition.getStrike();
        final double t = definition.getTimeToExpiry(date);
        final double sigma = data.getVolatility(t, k);
        final double r = data.getInterestRate(t);
        final double b = data.getCostOfCarry();
        final double lambda = data.getHalfLife();
        final double sigmaLR = data.getLongRunVolatility();
        final double volOfSigma = data.getVolatilityOfVolatility();
        final double rho = data.getCorrelation();
        final StandardOptionDataBundle bsmData = new StandardOptionDataBundle(data);
        final OptionDefinition call = definition.isCall() ? definition : new EuropeanVanillaOptionDefinition(k, definition.getExpiry(), true);
        final double beta = -Math.log(2) / lambda;
        final double alpha = -beta * sigmaLR * sigmaLR;
        final double delta = beta * t;
        final double eDelta = Math.exp(delta);
        final boolean betaIsZero = CompareUtils.closeEquals(beta, 0, ZERO);
        final double variance = sigma * sigma;
        final double meanVariance = getMeanVariance(betaIsZero, variance, alpha, t, beta, eDelta, delta);
        final double df = getDF(r, b, t);
        final double sDf = s * df;
        final double d1 = getD(s, k, b, meanVariance, t);
        final double d2 = d1 - Math.sqrt(meanVariance * t);
        final double nD1 = NORMAL.getPDF(d1);
        final double f0 = BSM.getPricingFunction(call).evaluate(bsmData.withVolatilitySurface(new VolatilitySurface(ConstantDoublesSurface.from(Math.sqrt(meanVariance)))));
        final double f1 = getF1(betaIsZero, variance, rho, alpha, t, beta, delta, eDelta, sDf, nD1, d2, meanVariance);
        final double f2 = getF2(betaIsZero, variance, rho, alpha, t, beta, delta, eDelta, sDf, nD1, d1, d2, meanVariance);
        final double callPrice = f0 + f1 * volOfSigma + f2 * volOfSigma * volOfSigma;
        if (!definition.isCall()) {
          return callPrice - s * df + k * Math.exp(-r * t);
        }
        return callPrice;
      }

    };
    return pricingFunction;
  }

  double getMeanVariance(final boolean betaIsZero, final double variance, final double alpha, final double t, final double beta, final double eDelta, final double delta) {
    if (betaIsZero) {
      return variance + alpha * t / 2.;
    }
    final double ratio = alpha / beta;
    return (variance + ratio) * (eDelta - 1) / delta - ratio;
  }

  private double getPhi1(final boolean betaIsZero, final double variance, final double rho, final double alpha, final double t, final double beta, final double beta4, final double eDelta,
      final double delta) {
    if (betaIsZero) {
      return rho * rho * (variance + alpha * t / 4.) * t * t * t / 6.;
    }
    return rho * rho * ((alpha + beta * variance) * (eDelta * (delta * delta / 2. - delta + 1) - 1) + alpha * (eDelta * (2 - delta) - 2 - delta)) / beta4;
  }

  private double getPhi2(final boolean betaIsZero, final double phi1, final double variance, final double rho, final double alpha, final double beta, final double beta4, final double eDelta,
      final double delta) {
    if (betaIsZero) {
      return phi1 * (2 + 1. / (rho * rho));
    }
    final double eDeltaSq = eDelta * eDelta;
    return 2 * phi1 + ((alpha + beta * variance) * (eDeltaSq - 2 * delta * eDelta - 1) - alpha * (eDeltaSq - 4 * eDelta + 2 * delta + 3) / 2.) / (2 * beta4);
  }

  private double getPhi3(final boolean betaIsZero, final double variance, final double rho, final double alpha, final double t, final double beta, final double beta4, final double eDelta,
      final double delta) {
    if (betaIsZero) {
      return rho * rho * Math.pow(variance + alpha * t / 3., 2) * t * t * t * t / 8.;
    }
    final double x = (alpha + beta * variance) * (eDelta - delta * eDelta - 1) - alpha * (1 + delta - eDelta);
    return rho * rho * x * x / (2 * beta * beta * beta4);
  }

  private double getPhi4(final double phi3) {
    return 2 * phi3;
  }

  double getD(final double s, final double k, final double b, final double meanVariance, final double t) {
    return (Math.log(s / k) + t * (b + meanVariance / 2)) / Math.sqrt(meanVariance * t);
  }

  private double getCSV(final double sDf, final double nD1, final double d2, final double meanVariance) {
    return -sDf * nD1 * d2 / (2 * meanVariance);
  }

  private double getCVV(final double sDf, final double sqrtT, final double nD1, final double d1, final double d2, final double meanVariance) {
    return sDf * sqrtT * nD1 * (d1 * d2 - 1) / (4 * Math.pow(meanVariance, 1.5));
  }

  private double getCSVV(final double sDf, final double nD1, final double d1, final double d2, final double meanVariance) {
    return sDf * nD1 * (-d1 * d2 * d2 + d1 + 2 * d2) / (4 * meanVariance * meanVariance);
  }

  private double getCVVV(final double sDf, final double sqrtT, final double nD1, final double d1, final double d2, final double meanVariance) {
    return sDf * sqrtT * nD1 * ((d1 * d2 - 1) * (d1 * d2 - 3) - d1 * d1 - d2 * d2) / (8 * Math.pow(meanVariance, 2.5));
  }

  double getF1(final boolean betaIsZero, final double variance, final double rho, final double alpha, final double t, final double beta, final double delta, final double eDelta, final double sDf,
      final double nD1, final double d2, final double meanVariance) {
    final double cSV = getCSV(sDf, nD1, d2, meanVariance);
    if (betaIsZero) {
      return rho * (variance + alpha * t / 3.) * t * cSV / 2.;
    }
    return rho * cSV * ((alpha + beta * variance) * (1 - eDelta + delta * eDelta) + alpha * (1 + delta - eDelta)) / (beta * beta * beta * t);
  }

  double getF2(final boolean betaIsZero, final double variance, final double rho, final double alpha, final double t, final double beta, final double delta, final double eDelta, final double sDf,
      final double nD1, final double d1, final double d2, final double meanVariance) {
    final double beta4 = beta * beta * beta * beta;
    final double phi1 = getPhi1(betaIsZero, variance, rho, alpha, t, beta, beta4, eDelta, delta);
    final double phi2 = getPhi2(betaIsZero, phi1, variance, rho, alpha, beta, beta4, eDelta, delta);
    final double phi3 = getPhi3(betaIsZero, variance, rho, alpha, t, beta, beta4, eDelta, delta);
    final double phi4 = getPhi4(phi3);
    final double sqrtT = Math.sqrt(t);
    final double cSV = getCSV(sDf, nD1, d2, meanVariance);
    final double cVV = getCVV(sDf, sqrtT, nD1, d1, d2, meanVariance);
    final double cSVV = getCSVV(sDf, nD1, d1, d2, meanVariance);
    final double cVVV = getCVVV(sDf, sqrtT, nD1, d1, d2, meanVariance);
    final double tInv = 1 / t;
    return tInv * (phi1 * cSV + tInv * (phi2 * cVV + phi3 * cSVV + tInv * phi4 * cVVV));
  }
}
TOP

Related Classes of com.opengamma.analytics.financial.model.option.pricing.analytic.HullWhiteStochasticVolatilityModel

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.