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

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

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

import static org.testng.Assert.assertEquals;

import org.testng.annotations.Test;
import org.threeten.bp.Period;
import org.threeten.bp.ZonedDateTime;

import com.opengamma.analytics.financial.forex.definition.ForexDefinition;
import com.opengamma.analytics.financial.forex.definition.ForexOptionDigitalDefinition;
import com.opengamma.analytics.financial.forex.derivative.ForexOptionDigital;
import com.opengamma.analytics.financial.forex.method.TestsDataSetsForex;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.model.volatility.surface.SmileDeltaTermStructureParametersStrikeInterpolation;
import com.opengamma.analytics.financial.schedule.ScheduleCalculator;
import com.opengamma.analytics.math.statistics.distribution.NormalDistribution;
import com.opengamma.analytics.math.statistics.distribution.ProbabilityDistribution;
import com.opengamma.analytics.util.time.TimeCalculator;
import com.opengamma.financial.convention.businessday.BusinessDayConvention;
import com.opengamma.financial.convention.businessday.BusinessDayConventionFactory;
import com.opengamma.financial.convention.calendar.Calendar;
import com.opengamma.financial.convention.calendar.MondayToFridayCalendar;
import com.opengamma.util.money.Currency;
import com.opengamma.util.time.DateUtils;
import com.opengamma.util.tuple.Triple;

/**
*
*/
@SuppressWarnings("deprecation")
public class DigitalOptionFunctionTest {

  private static final double SPOT = 105.;
  private static final double[] STRIKES = new double[] {97., 105., 105.1, 114. };
  private static final double TIME = 4.2;
  private static final double[] INTERESTS = new double[] {-0.01, 0.017, 0.05, 0.1 };
  private static final double[] VOLS = new double[] {0.05, 0.1, 0.5 };
  private static final double[] DIVIDENDS = new double[] {0.005, 0.024, 0.05 };

  private static final ZonedDateTime REFERENCE_DATE = DateUtils.getUTCDate(2011, 6, 13);
  private static final Calendar CALENDAR = new MondayToFridayCalendar("A");
  private static final BusinessDayConvention BUSINESS_DAY = BusinessDayConventionFactory.INSTANCE.getBusinessDayConvention("Modified Following");
  private static final int SETTLEMENT_DAYS = 2;
  private static final Currency EUR = Currency.EUR;
  private static final Currency USD = Currency.USD;
  private static final YieldCurveBundle CURVES = TestsDataSetsForex.createCurvesForex();
  private static final String[] CURVES_NAME = TestsDataSetsForex.curveNames();
  private static final SmileDeltaTermStructureParametersStrikeInterpolation SMILE_TERM = TestsDataSetsForex.smile5points(REFERENCE_DATE);
  private static final ProbabilityDistribution<Double> NORMAL = new NormalDistribution(0, 1);

  /**
   * Tests the present value against an explicit computation. The amount is paid in the domestic currency.
   */
  @Test
  public void presentValueDomestic() {
    final double strike = 1.45;
    final boolean isCall = true;
    final boolean isLong = true;
    final double notional = 100000000;
    final ZonedDateTime payDate = ScheduleCalculator.getAdjustedDate(REFERENCE_DATE, Period.ofMonths(9), BUSINESS_DAY, CALENDAR);
    final ZonedDateTime expDate = ScheduleCalculator.getAdjustedDate(payDate, -SETTLEMENT_DAYS, CALENDAR);
    final double timeToExpiry = TimeCalculator.getTimeBetween(REFERENCE_DATE, expDate);
    final ForexDefinition forexUnderlyingDefinition = new ForexDefinition(EUR, USD, payDate, notional, strike);
    final ForexOptionDigitalDefinition forexOptionDefinition = new ForexOptionDigitalDefinition(forexUnderlyingDefinition, expDate, isCall, isLong);
    final ForexOptionDigital forexOption = forexOptionDefinition.toDerivative(REFERENCE_DATE, CURVES_NAME);
    final double dfDomestic = CURVES.getCurve(CURVES_NAME[1]).getDiscountFactor(forexOption.getUnderlyingForex().getPaymentTime());
    final double dfForeign = CURVES.getCurve(CURVES_NAME[0]).getDiscountFactor(forexOption.getUnderlyingForex().getPaymentTime());
    final double rDomestic = CURVES.getCurve(CURVES_NAME[1]).getInterestRate(forexOption.getUnderlyingForex().getPaymentTime());
    final double rForeign = CURVES.getCurve(CURVES_NAME[0]).getInterestRate(forexOption.getUnderlyingForex().getPaymentTime());
    final double forward = SPOT * dfForeign / dfDomestic;
    final double volatility = SMILE_TERM.getVolatility(new Triple<>(timeToExpiry, forward, forward));
    final double sigmaRootT = volatility * Math.sqrt(forexOption.getExpirationTime());
    final double dM = Math.log(forward / strike) / sigmaRootT - 0.5 * sigmaRootT;
    final int omega = isCall ? 1 : -1;

    final double pvExpected = Math.abs(forexOption.getUnderlyingForex().getPaymentCurrency1().getAmount()) * dfDomestic * NORMAL.getCDF(omega * dM) * (isLong ? 1.0 : -1.0);
    final double price = Math.abs(forexOption.getUnderlyingForex().getPaymentCurrency1().getAmount()) *
        DigitalOptionFunction.price(SPOT, strike, forexOption.getUnderlyingForex().getPaymentTime(), volatility, rDomestic, rDomestic - rForeign, isCall);
    assertEquals(price, pvExpected, pvExpected * 1.e-14);
  }

  /**
   *
   */
  @Test
  public void greeksTest() {
    final boolean[] tfSet = new boolean[] {true, false };
    final double eps = 1.e-6;
    for (final boolean isCall : tfSet) {
      for (final double strike : STRIKES) {
        for (final double interest : INTERESTS) {
          for (final double vol : VOLS) {
            for (final double dividend : DIVIDENDS) {
              final double delta = DigitalOptionFunction.delta(SPOT, strike, TIME, vol, interest, interest - dividend, isCall);
              final double gamma = DigitalOptionFunction.gamma(SPOT, strike, TIME, vol, interest, interest - dividend, isCall);
              final double theta = DigitalOptionFunction.theta(SPOT, strike, TIME, vol, interest, interest - dividend, isCall);
              final double vega = DigitalOptionFunction.vega(SPOT, strike, TIME, vol, interest, interest - dividend, isCall);
              final double upSpot = DigitalOptionFunction.price(SPOT + eps, strike, TIME, vol, interest, interest - dividend, isCall);
              final double downSpot = DigitalOptionFunction.price(SPOT - eps, strike, TIME, vol, interest, interest - dividend, isCall);
              final double upSpotDelta = DigitalOptionFunction.delta(SPOT + eps, strike, TIME, vol, interest, interest - dividend, isCall);
              final double downSpotDelta = DigitalOptionFunction.delta(SPOT - eps, strike, TIME, vol, interest, interest - dividend, isCall);
              final double upTime = DigitalOptionFunction.price(SPOT, strike, TIME + eps, vol, interest, interest - dividend, isCall);
              final double downTime = DigitalOptionFunction.price(SPOT, strike, TIME - eps, vol, interest, interest - dividend, isCall);
              final double upVol = DigitalOptionFunction.price(SPOT, strike, TIME, vol + eps, interest, interest - dividend, isCall);
              final double downVol = DigitalOptionFunction.price(SPOT, strike, TIME, vol - eps, interest, interest - dividend, isCall);
              assertEquals(delta, 0.5 * (upSpot - downSpot) / eps, eps);
              assertEquals(gamma, 0.5 * (upSpotDelta - downSpotDelta) / eps, eps);
              assertEquals(theta, -0.5 * (upTime - downTime) / eps, eps);
              assertEquals(vega, 0.5 * (upVol - downVol) / eps, eps);

              final double forward = SPOT * Math.exp(interest - dividend * TIME);
              final double forwardTheta = DigitalOptionFunction.driftlessTheta(forward, strike, TIME, vol, isCall);
              final double sign = isCall ? 1. : -1.;
              final double dUp = Math.log(forward / strike) / vol / Math.sqrt(TIME + eps) - 0.5 * vol * Math.sqrt(TIME + eps);
              final double dDw = Math.log(forward / strike) / vol / Math.sqrt(TIME - eps) - 0.5 * vol * Math.sqrt(TIME - eps);
              final double fwUp = NORMAL.getCDF(sign * dUp);
              final double fwDw = NORMAL.getCDF(sign * dDw);
              assertEquals(forwardTheta, -0.5 * (fwUp - fwDw) / eps, eps);
            }
          }
        }
      }
    }
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeSpotPriceTest() {
    DigitalOptionFunction.price(-SPOT, STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeStrikePriceTest() {
    DigitalOptionFunction.price(SPOT, -STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeTimePriceTest() {
    DigitalOptionFunction.price(SPOT, STRIKES[0], -TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeVolPriceTest() {
    DigitalOptionFunction.price(SPOT, STRIKES[0], TIME, -VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeSpotdeltaTest() {
    DigitalOptionFunction.delta(-SPOT, STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeStrikedeltaTest() {
    DigitalOptionFunction.delta(SPOT, -STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeTimedeltaTest() {
    DigitalOptionFunction.delta(SPOT, STRIKES[0], -TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeVoldeltaTest() {
    DigitalOptionFunction.delta(SPOT, STRIKES[0], TIME, -VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeSpotgammaTest() {
    DigitalOptionFunction.gamma(-SPOT, STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeStrikegammaTest() {
    DigitalOptionFunction.gamma(SPOT, -STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeTimegammaTest() {
    DigitalOptionFunction.gamma(SPOT, STRIKES[0], -TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeVolgammaTest() {
    DigitalOptionFunction.gamma(SPOT, STRIKES[0], TIME, -VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeSpotthetaTest() {
    DigitalOptionFunction.theta(-SPOT, STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeStrikethetaTest() {
    DigitalOptionFunction.theta(SPOT, -STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeTimethetaTest() {
    DigitalOptionFunction.theta(SPOT, STRIKES[0], -TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeVolthetaTest() {
    DigitalOptionFunction.theta(SPOT, STRIKES[0], TIME, -VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeSpotvegaTest() {
    DigitalOptionFunction.vega(-SPOT, STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeStrikevegaTest() {
    DigitalOptionFunction.vega(SPOT, -STRIKES[0], TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeTimevegaTest() {
    DigitalOptionFunction.vega(SPOT, STRIKES[0], -TIME, VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeVolvegaTest() {
    DigitalOptionFunction.vega(SPOT, STRIKES[0], TIME, -VOLS[1], INTERESTS[1], INTERESTS[1] - DIVIDENDS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeSpotdriftlessThetaTest() {
    DigitalOptionFunction.driftlessTheta(-SPOT, STRIKES[0], TIME, VOLS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeStrikedriftlessThetaTest() {
    DigitalOptionFunction.driftlessTheta(SPOT, -STRIKES[0], TIME, VOLS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeTimedriftlessThetaTest() {
    DigitalOptionFunction.driftlessTheta(SPOT, STRIKES[0], -TIME, VOLS[1], true);
  }

  /**
   *
   */
  @Test(expectedExceptions = IllegalArgumentException.class)
  public void negativeVoldriftlessThetaTest() {
    DigitalOptionFunction.driftlessTheta(SPOT, STRIKES[0], TIME, -VOLS[1], true);
  }
}
TOP

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

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.