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

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

/**
* 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 com.opengamma.analytics.financial.model.option.definition.EuropeanVanillaOptionDefinition;
import com.opengamma.analytics.financial.model.option.definition.OptionDefinition;
import com.opengamma.analytics.financial.model.option.definition.SkewKurtosisOptionDataBundle;
import com.opengamma.analytics.financial.model.option.definition.StandardOptionDataBundle;
import com.opengamma.analytics.math.function.Function1D;

/**
* The Jarrow-Rudd option pricing formula extends the Black-Scholes-Merton
* model for non-normal skewness and kurtosis in the underlying price
* distribution.
* <p>
* The price of a call option is given by:
* $$
* \begin{align*}
* c = c_{BSM} + \lambda_1 Q_3 + \lambda_2 Q_4
* \end{align*}
* $$
* $c_{BSM}$ is the Black-Scholes-Merton call price (see {@link BlackScholesMertonModel}) and
* $$
* \begin{align*}
* d_1 &= \frac{\ln(\frac{S}{K} + (r + \frac{\sigma^2}{2})T}{\sigma\sqrt{T}}\\
* d_2 &= d_1 - \sigma\sqrt{T}\\
* Q_3 &= -\frac{(Se^{-rT})^3(e^{\sigma^2 T} - 1)^{\frac{3}{2}} e^{-rT}}{6}\frac{da(X)}{dS}\\
* Q_4 &= \frac{(Se^{-rT})^4(e^{\sigma^2 T} - 1)^2 e^{-rT}}{24}\frac{d^2a(X)}{dS^2}\\
* \lambda_1 &= \gamma_1(F) - \gamma_1(A)\\
* \lambda_2 &= \gamma_2(F) - \gamma_2(A)\\
* a(X) &= \frac{e^{-\frac{d_2^2}{2}}}{2\pi K\sigma\sqrt{T}}
* \end{align*}
* $$
* The skewness ($\gamma_1(A)$) and kurtosis ($\gamma_2(A)$) of a lognormal
* distribution are $\gamma_1 = 3y + y^3$ and
* $\gamma_2 = 16y^2 + 15y^4 + 6y^6 * + y^8$ where $y = \sqrt{e^{\sigma^2 T} - 1}$.
* $\gamma_1(F)$ are $\gamma_2(F)$ are the observed skewness and kurtosis of
* the underlying price distribution.
* <p>
* Put options are priced using put-call parity.
*/
public class JarrowRuddSkewnessKurtosisModel extends AnalyticOptionModel<OptionDefinition, SkewKurtosisOptionDataBundle> {
  private static final AnalyticOptionModel<OptionDefinition, StandardOptionDataBundle> BSM = new BlackScholesMertonModel();

  /**
   * {@inheritDoc}
   */
  @Override
  public Function1D<SkewKurtosisOptionDataBundle, Double> getPricingFunction(final OptionDefinition definition) {
    Validate.notNull(definition);
    final Function1D<SkewKurtosisOptionDataBundle, Double> pricingFunction = new Function1D<SkewKurtosisOptionDataBundle, Double>() {

      @SuppressWarnings("synthetic-access")
      @Override
      public Double evaluate(final SkewKurtosisOptionDataBundle data) {
        Validate.notNull(data);
        final double s = data.getSpot();
        final double k = definition.getStrike();
        final double t = definition.getTimeToExpiry(data.getDate());
        final double sigma = data.getVolatility(t, k);
        final double r = data.getInterestRate(t);
        final double b = data.getCostOfCarry();
        final double skew = data.getAnnualizedSkew();
        final double kurtosis = data.getAnnualizedPearsonKurtosis();
        final OptionDefinition callDefinition = definition.isCall() ? definition : new EuropeanVanillaOptionDefinition(k, definition.getExpiry(), true);
        final Function1D<StandardOptionDataBundle, Double> bsm = BSM.getPricingFunction(callDefinition);
        final double bsmCall = bsm.evaluate(data);
        final double d2 = getD2(getD1(s, k, t, sigma, b), sigma, t);
        final double sigmaT = sigma * Math.sqrt(t);
        final double a = getA(d2, k, sigmaT);
        final double call = bsmCall + getLambda1(sigma, t, skew) * getQ3(s, k, sigmaT, t, r, a, d2) + getLambda2(sigma, t, kurtosis) * getQ4(s, k, sigmaT, t, r, a, d2);
        if (!definition.isCall()) {
          return call - s * Math.exp((b - r) * t) + k * Math.exp(-r * t);
        }
        return call;
      }
    };
    return pricingFunction;
  }

  private double getA(final double d2, final double k, final double sigmaT) {
    return Math.exp(-d2 * d2 / 2.) / k / sigmaT / Math.sqrt(2 * Math.PI);
  }

  private double getLambda1(final double sigma, final double t, final double skew) {
    final double q = Math.sqrt(Math.exp(sigma * sigma * t) - 1);
    final double skewDistribution = q * (3 + q * q);
    return skew - skewDistribution;
  }

  private double getLambda2(final double sigma, final double t, final double kurtosis) {
    final double q = Math.sqrt(Math.exp(sigma * sigma * t) - 1);
    final double q2 = q * q;
    final double q4 = q2 * q2;
    final double q6 = q4 * q2;
    final double q8 = q6 * q2;
    final double kurtosisDistribution = 16 * q2 + 15 * q4 + 6 * q6 + q8 + 3;
    return kurtosis - kurtosisDistribution;
  }

  private double getQ3(final double s, final double k, final double sigmaT, final double t, final double r, final double a, final double d2) {
    final double da = a * (d2 - sigmaT) / (k * sigmaT);
    final double df = Math.exp(-r * t);
    return -Math.pow(s * df, 3) * Math.pow(Math.exp(sigmaT * sigmaT - 1), 1.5) * df * da / 6.;
  }

  private double getQ4(final double s, final double k, final double sigmaT, final double t, final double r, final double a, final double d2) {
    final double sigmaTSq = sigmaT * sigmaT;
    final double x = d2 - sigmaT;
    final double da2 = a * (x * x - sigmaT * x - 1) / (k * k * sigmaTSq);
    final double df = Math.exp(-r * t);
    return Math.pow(s * df, 4) * Math.pow(Math.exp(sigmaTSq) - 1, 2) * df * da2 / 24.;
  }
}
TOP

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

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.