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

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

/**
* 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 java.util.Collections;
import java.util.Set;

import org.apache.commons.lang.Validate;

import com.opengamma.analytics.financial.greeks.Greek;
import com.opengamma.analytics.financial.greeks.GreekResultCollection;
import com.opengamma.analytics.financial.model.option.definition.AmericanVanillaOptionDefinition;
import com.opengamma.analytics.financial.model.option.definition.OptionDefinition;
import com.opengamma.analytics.financial.model.option.definition.StandardOptionDataBundle;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.rootfinding.BisectionSingleRootFinder;
import com.opengamma.analytics.math.rootfinding.RealSingleRootFinder;
import com.opengamma.analytics.math.statistics.distribution.NormalDistribution;
import com.opengamma.analytics.math.statistics.distribution.ProbabilityDistribution;

/**
*
*/
public class JuZhongModel extends AnalyticOptionModel<AmericanVanillaOptionDefinition, StandardOptionDataBundle> {
  private static final ProbabilityDistribution<Double> NORMAL = new NormalDistribution(0, 1);
  private static final AnalyticOptionModel<OptionDefinition, StandardOptionDataBundle> BSM = new BlackScholesMertonModel();
  private static final Set<Greek> PRICE = Collections.singleton(Greek.FAIR_PRICE);
  private static final RealSingleRootFinder FINDER = new BisectionSingleRootFinder();

  @Override
  public Function1D<StandardOptionDataBundle, Double> getPricingFunction(final AmericanVanillaOptionDefinition definition) {
    Validate.notNull(definition);
    final double phi = definition.isCall() ? 1 : -1;
    final Function1D<StandardOptionDataBundle, Double> pricingFunction = new Function1D<StandardOptionDataBundle, Double>() {

      @SuppressWarnings("synthetic-access")
      @Override
      public Double evaluate(final StandardOptionDataBundle data) {
        Validate.notNull(data);
        final GreekResultCollection bsmResult = BSM.getGreeks(definition, data, PRICE);
        final double bsmPrice = bsmResult.get(Greek.FAIR_PRICE);
        final double s = data.getSpot();
        final double k = definition.getStrike();
        final double t = definition.getTimeToExpiry(data.getDate());
        final double r = data.getInterestRate(t);
        final double b = data.getCostOfCarry();
        final double sigma = data.getVolatility(t, k);
        final double sigmaSq = sigma * sigma;
        final double h = getH(r, t);
        final double alpha = getAlpha(r, sigmaSq);
        final double beta = getBeta(r, b, sigmaSq);
        final double lambda = getLambda(phi, alpha, beta, h);
        final double lambdaDash = getLambdaDash(phi, alpha, beta, h);
        final Function1D<Double, Double> function = getFunction(phi, Math.exp(-b * t), k, t, sigmaSq, b, lambda, definition, data);
        final double sEstimate = FINDER.getRoot(function, 0., s * 2);
        if (phi * (sEstimate - s) <= 0) {
          return phi * (s - k);
        }
        final double estimatePrice = BSM.getGreeks(definition, data.withSpot(sEstimate), PRICE).get(Greek.FAIR_PRICE);
        final double hA = phi * (sEstimate - k) - estimatePrice;
        final double derivative = getDerivative(k, r, b, t, sigma, phi, sEstimate);
        final double c = getC(h, alpha, lambdaDash, lambda, beta);
        final double d = getD(h, alpha, derivative, hA, lambdaDash, lambda, beta);
        final double ratio = Math.log(s / sEstimate);
        final double chi = c * Math.pow(ratio, 2) + d * ratio;
        return bsmPrice + hA * Math.pow(s / sEstimate, lambda) / (1 - chi);
      }

    };
    return pricingFunction;
  }

  protected double getH(final double r, final double t) {
    return 1 - Math.exp(-r * t);
  }

  protected double getAlpha(final double r, final double sigmaSq) {
    return 2 * r / sigmaSq;
  }

  protected double getBeta(final double r, final double b, final double sigmaSq) {
    return 2 * (r - b) / sigmaSq;
  }

  protected double getLambda(final double phi, final double alpha, final double beta, final double h) {
    final double beta1 = beta - 1;
    return (-beta + phi * Math.sqrt(beta1 * beta1 + 4 * alpha / h)) / 2;
  }

  protected double getLambdaDash(final double phi, final double alpha, final double beta, final double h) {
    return phi * alpha / (h * h * Math.sqrt((beta - 1) * (beta - 1) + 4 * alpha / h));
  }

  protected double getC(final double h, final double alpha, final double lambdaDash, final double lambda, final double beta) {
    return (1 - h) * alpha * lambdaDash / (2 * (2 * lambda + beta - 1));
  }

  protected double getD(final double h, final double alpha, final double derivative, final double hA, final double lambdaDash, final double lambda, final double beta) {
    final double denom = 2 * lambda + beta - 1;
    return (1 - h) * alpha * (derivative / hA + 1 / h + lambdaDash / denom) / denom;
  }

  protected double getDerivative(final double k, final double r, final double b, final double t, final double sigma, final double phi, final double sEstimate) {
    final double df = Math.exp(t * (r - b));
    final double d1 = getD1(sEstimate, k, t, sigma, b);
    final double d2 = getD2(d1, sigma, t);
    return sEstimate * NORMAL.getPDF(d1) * sigma * df / (2 * r * Math.sqrt(t)) - phi * b * sEstimate * NORMAL.getCDF(phi * d1) * df / r + phi * k * NORMAL.getCDF(phi * d2);
  }

  protected Function1D<Double, Double> getFunction(final double phi, final double df, final double k, final double t, final double sigma, final double b, final double lambda,
      final OptionDefinition definition, final StandardOptionDataBundle data) {
    return new Function1D<Double, Double>() {

      @SuppressWarnings("synthetic-access")
      @Override
      public Double evaluate(final Double x) {
        final GreekResultCollection bsmPrice = BSM.getGreeks(definition, data.withSpot(x), PRICE);
        final double price = bsmPrice.get(Greek.FAIR_PRICE);
        return phi * (df * NORMAL.getCDF(phi * getD1(x, k, t, sigma, b)) + lambda * (phi * (x - k) - price) / x - 1);
      }

    };
  }
}
TOP

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

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.