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

Source Code of com.opengamma.analytics.financial.model.option.pricing.fourier.HestonFourierPricerTest

/**
* 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.fourier;

import static com.opengamma.analytics.math.ComplexMathUtils.exp;
import static org.testng.AssertJUnit.assertEquals;

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

import org.testng.annotations.Test;

import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.BlackFunctionData;
import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption;
import com.opengamma.analytics.financial.model.volatility.BlackImpliedVolatilityFormula;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.number.ComplexNumber;

/**
*
*/
public class HestonFourierPricerTest {
  private static final double FORWARD = 0.04;
  private static final double T = 2.0;
  private static final double DF = 0.93;
  private static final BlackImpliedVolatilityFormula BLACK_IMPLIED_VOL = new BlackImpliedVolatilityFormula();

  @Test
  public void testLowVolOfVol() {
    final double sigma = 0.36;

    final double kappa = 1.0; // mean reversion speed
    final double theta = sigma * sigma; // reversion level
    final double vol0 = theta; // start level
    final double omega = 0.001; // vol-of-vol
    final double rho = -0.3; // correlation

    final MartingaleCharacteristicExponent heston = new HestonCharacteristicExponent(kappa, theta, vol0, omega, rho);
    final FourierPricer pricer = new FourierPricer();

    for (int i = 0; i < 21; i++) {
      final double k = 0.2 + 3.0 * i / 20.0;
      final EuropeanVanillaOption option = new EuropeanVanillaOption(k * FORWARD, T, true);
      final BlackFunctionData data = new BlackFunctionData(FORWARD, DF, 0);
      final double price = pricer.price(data, option, heston, -0.5, 1e-6);
      final double impVol = BLACK_IMPLIED_VOL.getImpliedVolatility(data, option, price);
      assertEquals(sigma, impVol, 1e-3);
    }
  }

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

    final double kappa = 1.0; // mean reversion speed
    final double theta = 0.16; // reversion level
    final double vol0 = theta; // start level
    final double omega = 2; // vol-of-vol
    final double rho = -0.8; // correlation

    final CharacteristicExponent heston = new HestonCharacteristicExponent(kappa, theta, vol0, omega, rho);
    for (int j = 0; j < 101; j++) {
      final double y = -3. + j * 6. / 100.0;
      System.out.print("\t" + y);
    }
    System.out.print("\n");

    for (int i = 0; i < 101; i++) {
      final double x = -3. + i * 6. / 100.0;
      System.out.print(x + "\t");
      for (int j = 0; j < 101; j++) {
        final double y = -3. + j * 6. / 100.0;
        final ComplexNumber res = heston.getValue(new ComplexNumber(x, y), 0.25);
        System.out.print(res.getReal() + "\t");
      }
      System.out.print("\n");
    }
  }

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

    final double alpha = 0.75;

    final double kappa = 1.0; // mean reversion speed
    final double theta = 0.16; // reversion level
    final double vol0 = theta; // start level
    final double omega = 2; // vol-of-vol
    final double rho = -0.8; // correlation
    final double t = 1.0;// / 52.0;
    final MartingaleCharacteristicExponent heston = new HestonCharacteristicExponent(kappa, theta, vol0, omega, rho);
    final EuropeanPriceIntegrand integrand = new EuropeanPriceIntegrand(heston, alpha, true);
    final BlackFunctionData data = new BlackFunctionData(1, 1, 0.5);
    for (int i = 0; i < 201; i++) {
      final double x = -0. + i * 80. / 200.0;
      final EuropeanVanillaOption option = new EuropeanVanillaOption(2, t, true);
      final Double res = integrand.getFunction(data, option).evaluate(x);
      System.out.println(x + "\t" + res);
    }

  }

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

    final double alpha = -0.4;

    final double kappa = 1.0; // mean reversion speed
    final double theta = 0.16; // reversion level
    final double vol0 = theta; // start level
    final double omega = 2; // vol-of-vol
    final double rho = -0.8; // correlation
    final double t = 1 / 52.0;
    final MartingaleCharacteristicExponent heston = new HestonCharacteristicExponent(kappa, theta, vol0, omega, rho);
    final EuropeanCallFourierTransform integrand = new EuropeanCallFourierTransform(heston);
    final Function1D<ComplexNumber, ComplexNumber> func = integrand.getFunction(t);

    for (int i = 0; i < 201; i++) {
      final double x = -0. + i * 20. / 200.0;
      final ComplexNumber res = func.evaluate((new ComplexNumber(x, alpha)));
      System.out.println(x + "\t" + res.getReal() + "\t" + res.getImaginary());
    }
  }

  @Test
  public void testHeston() {
    final double alpha = 0.75;

    // parameters from the paper Not-so-complex logarithms in the Heston model
    final double kappa = 1.0; // mean reversion speed
    final double theta = 0.16; // reversion level
    final double vol0 = theta; // start level
    final double omega = 2; // vol-of-vol
    final double rho = -0.8; // correlation

    final double t = 1 / 12.0;

    final MartingaleCharacteristicExponent heston = new HestonCharacteristicExponent(kappa, theta, vol0, omega, rho);
    final FourierPricer pricer = new FourierPricer();
    final BlackFunctionData data = new BlackFunctionData(1, 1, 0);
    for (int i = 0; i < 11; i++) {
      final double k = 0.5 + 1.0 * i / 10.0;

      final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, true);
      final double price = pricer.price(data, option, heston, alpha, 1e-8);
      BLACK_IMPLIED_VOL.getImpliedVolatility(data, option, price);
      //  System.out.println(k + "\t" + impVol);
    }
  }

  @Test
  public void testHestonModelGreeks() {

    final FourierModelGreeks modelGreek = new FourierModelGreeks();

    final double alpha = -0.5;

    final double kappa = 1.0; // mean reversion speed
    final double theta = 0.16; // reversion level
    final double vol0 = theta; // start level
    final double omega = 2; // vol-of-vol
    final double rho = -0.8; // correlation

    final double forward = 1.0;
    final double t = 1 / 12.0;

    final MartingaleCharacteristicExponent heston = new HestonCharacteristicExponent(kappa, theta, vol0, omega, rho);
    final FourierPricer pricer = new FourierPricer();
    final BlackFunctionData data = new BlackFunctionData(forward, 1, 0);

    boolean isCall;
    for (int i = 0; i < 11; i++) {
      final double k = 0.7 + 0.6 * i / 10.0;
      isCall = k >= forward;
      final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, isCall);
      final double[] sense = modelGreek.getGreeks(data, option, heston, alpha, 1e-12);

      final double price = pricer.price(data, option, heston, alpha, 1e-8);
      final double[] fdSense = finiteDifferenceModelGreeks((HestonCharacteristicExponent) heston, pricer, data, option);
//      System.out.println(k + "\t" + price + "\t" + fdSense[0] / price + "\t" + fdSense[1] / price + "\t" + fdSense[2] / price + "\t" + fdSense[3] / price + "\t" + fdSense[4] / price
//          + "\t" + sense[0] / price + "\t" + sense[1] / price + "\t" + sense[2] / price + "\t" + sense[3] / price + "\t" + sense[4] / price);

      for(int index =0;index<5;index++) {
        assertEquals( fdSense[index],sense[index],1e-3*price);
      }
    }
  }

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

    final FourierModelGreeks modelGreek = new FourierModelGreeks();

    final double alpha = -0.75;

    final double kappa = 1.0; // mean reversion speed
    final double theta = 0.16; // reversion level
    final double vol0 = theta; // start level
    final double omega = 2; // vol-of-vol
    final double rho = -0.8; // correlation

    final double forward = 1.0;
    final double strike = 1.4;
    final double t = 1 / 12.0;

    final MartingaleCharacteristicExponent heston = new HestonCharacteristicExponent(kappa, theta, vol0, omega, rho);
    final double k = Math.log(strike / forward);

    final List<Function1D<Double, Double>> funcs = new ArrayList<>(5);
    for (int index = 0; index < 5; index++) {
      funcs.add(modelGreek.getIntegrandFunction(heston.getAdjointFunction(t), alpha, k, index));
    }
    for (int i = 0; i < 201; i++) {
      final double x = 0.0 + 25.0 * i / 200;
      System.out.print(x);

      for (int index = 0; index < 5; index++) {
        final double value = funcs.get(index).evaluate(x);
        System.out.print("\t" + value);
      }
      System.out.print("\n");
    }

  }

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

    final double alpha = -0.75;

    final double kappa = 1.0; // mean reversion speed
    final double theta = 0.16; // reversion level
    final double vol0 = theta; // start level
    final double omega = 2; // vol-of-vol
    final double rho = -0.8; // correlation

    final double t = 1 / 12.0;

    final CharacteristicExponent heston = new HestonCharacteristicExponent(kappa, theta, vol0, omega, rho);

    for (int i = 0; i < 201; i++) {
      final double x = 0.0 + 250.0 * i / 200;
      final ComplexNumber z = new ComplexNumber(x, -(1 + alpha));
      final ComplexNumber[] res = heston.getCharacteristicExponentAdjoint(z, t);
      System.out.print(x);
      for (final ComplexNumber re : res) {
        final double value = exp(re).getReal();
        System.out.print("\t" + value);
      }
      System.out.print("\n");
    }

  }

  public static double[] finiteDifferenceModelGreeks(final HestonCharacteristicExponent ce, final FourierPricer pricer, final BlackFunctionData data, final EuropeanVanillaOption option) {
    final double eps = 1e-5;
    final double tol = 1e-13;
    final double alpha = -0.5;
    final double[] res = new double[5];
    //kappa
    HestonCharacteristicExponent ceTemp = new HestonCharacteristicExponent(ce.getKappa() + eps, ce.getTheta(), ce.getVol0(), ce.getOmega(), ce.getRho());
    double up = pricer.price(data, option, ceTemp, alpha,tol);
    ceTemp = new HestonCharacteristicExponent(ce.getKappa() - eps, ce.getTheta(), ce.getVol0(), ce.getOmega(), ce.getRho());
    double down = pricer.price(data, option, ceTemp, alpha, tol);
    res[0] = (up - down) / 2 / eps;
    //theta
    ceTemp = new HestonCharacteristicExponent(ce.getKappa(), ce.getTheta() + eps, ce.getVol0(), ce.getOmega(), ce.getRho());
    up = pricer.price(data, option, ceTemp, alpha, tol);
    ceTemp = new HestonCharacteristicExponent(ce.getKappa(), ce.getTheta() - eps, ce.getVol0(), ce.getOmega(), ce.getRho());
    down = pricer.price(data, option, ceTemp, alpha, tol);
    res[1] = (up - down) / 2 / eps;
    //vol0
    ceTemp = new HestonCharacteristicExponent(ce.getKappa(), ce.getTheta(), ce.getVol0() + eps, ce.getOmega(), ce.getRho());
    up = pricer.price(data, option, ceTemp, alpha, tol);
    ceTemp = new HestonCharacteristicExponent(ce.getKappa(), ce.getTheta(), ce.getVol0() - eps, ce.getOmega(), ce.getRho());
    down = pricer.price(data, option, ceTemp, alpha, tol);
    res[2] = (up - down) / 2 / eps;
    //omega
    ceTemp = new HestonCharacteristicExponent(ce.getKappa(), ce.getTheta(), ce.getVol0(), ce.getOmega() + eps, ce.getRho());
    up = pricer.price(data, option, ceTemp, alpha, tol);
    ceTemp = new HestonCharacteristicExponent(ce.getKappa(), ce.getTheta(), ce.getVol0(), ce.getOmega() - eps, ce.getRho());
    down = pricer.price(data, option, ceTemp, alpha, tol);
    res[3] = (up - down) / 2 / eps;
    //rho
    ceTemp = new HestonCharacteristicExponent(ce.getKappa(), ce.getTheta(), ce.getVol0(), ce.getOmega(), ce.getRho() + eps);
    up = pricer.price(data, option, ceTemp, alpha, tol);
    ceTemp = new HestonCharacteristicExponent(ce.getKappa(), ce.getTheta(), ce.getVol0(), ce.getOmega(), ce.getRho() - eps);
    down = pricer.price(data, option, ceTemp, alpha, tol);
    res[4] = (up - down) / 2 / eps;

    return res;
  }

}
TOP

Related Classes of com.opengamma.analytics.financial.model.option.pricing.fourier.HestonFourierPricerTest

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.