/**
* 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.formula;
import static org.testng.AssertJUnit.assertEquals;
import org.testng.annotations.Test;
import com.opengamma.analytics.financial.model.volatility.BlackImpliedVolatilityFormula;
import com.opengamma.analytics.financial.model.volatility.smile.function.SABRFormulaData;
import com.opengamma.analytics.financial.model.volatility.smile.function.SABRHaganVolatilityFunction;
import com.opengamma.util.test.TestGroup;
/**
* Test.
*/
@Test(groups = TestGroup.UNIT)
public class CEVPriceFunctionTest {
private static final SABRHaganVolatilityFunction SABR = new SABRHaganVolatilityFunction();
private static final CEVPriceFunction CEV = new CEVPriceFunction();
private static final BlackImpliedVolatilityFormula BLACK_IMPLIED_VOL = new BlackImpliedVolatilityFormula();
/**
* For short dated options should have good agreement with the SABR formula for nu = 0
*/
@Test
public void testBeta() {
final double f = 4;
final double k = 3.5;
final double atmVol = 0.3;
final double t = 0.1;
double beta;
for (int i = 0; i < 200; i++) {
beta = i / 100.0;
final double sigma = atmVol * Math.pow(f, 1 - beta);
final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, true);
final CEVFunctionData cevData = new CEVFunctionData(f, 1.0, sigma, beta);
final double price = CEV.getPriceFunction(option).evaluate(cevData);
final double vol = BLACK_IMPLIED_VOL.getImpliedVolatility(new BlackFunctionData(f, 1.0, sigma), option, price);
final SABRFormulaData sabrData = new SABRFormulaData(sigma, beta, 0.0, 0.0);
final double sabrVol = SABR.getVolatilityFunction(option, f).evaluate(sabrData);
assertEquals(sabrVol, vol, 1e-4);//TODO this used to work with 1e-5????
}
}
@Test
public void testStrike() {
final double f = 4;
double k;
final double atmVol = 0.3;
final double t = 0.5;
final double beta = 0.5;
final double sigma = atmVol * Math.pow(f, 1 - beta);
for (int i = 0; i < 20; i++) {
k = 1.0 + i / 2.5;
final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, true);
final CEVFunctionData cevData = new CEVFunctionData(f, 1.0, sigma, beta);
final double price = CEV.getPriceFunction(option).evaluate(cevData);
final double vol = BLACK_IMPLIED_VOL.getImpliedVolatility(new BlackFunctionData(f, 1.0, sigma), option, price);
final SABRFormulaData sabrData = new SABRFormulaData(sigma, beta, 0.0, 0.0);
final double sabrVol = SABR.getVolatilityFunction(option, f).evaluate(sabrData);
assertEquals(sabrVol, vol, 1e-4);
}
}
@Test
public void testBetaAndStrike() {
final double f = 4;
double k;
final double atmVol = 0.3;
final double t = 0.1;
double beta;
double sigma;
for (int i = 0; i < 20; i++) {
beta = (i + 1) / 20.0;
sigma = atmVol * Math.pow(f, 1 - beta);
for (int j = 0; j < 20; j++) {
k = 3.0 + j / 10.0;
final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, true);
final CEVFunctionData cevData = new CEVFunctionData(f, 1.0, sigma, beta);
final double price = CEV.getPriceFunction(option).evaluate(cevData);
final double vol = BLACK_IMPLIED_VOL.getImpliedVolatility(new BlackFunctionData(f, 1.0, sigma), option, price);
final SABRFormulaData sabrData = new SABRFormulaData(sigma, beta, 0.0, 0.0);
final double sabrVol = SABR.getVolatilityFunction(option, f).evaluate(sabrData);
assertEquals(sabrVol, vol, 1e-4);//TODO this used to work with 1e-5????
}
}
}
@Test(enabled = false)
public void funnySmileTest() {
final double beta = 0.4;
final double t = 5.0;
final double r = 0.0;
final double spot = 100;
final double k = spot * Math.exp(-r * t);
final double atmVol = 0.20;
final double volBeta = atmVol * Math.pow(k, 1 - beta);
final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, true);
for (int i = 0; i < 101; i++) {
final double f = 350.0 + 1.0 * i;
final CEVFunctionData cevData = new CEVFunctionData(f, 1.0, volBeta, beta);
final double cevPrice = CEV.getPriceFunction(option).evaluate(cevData);
@SuppressWarnings("unused")
final double cevVol = BLACK_IMPLIED_VOL.getImpliedVolatility(new BlackFunctionData(f, 1.0, volBeta), option, cevPrice);
// System.out.println(f +"\t"+cevPrice+"\t"+cevVol);
}
}
@Test
public void testDebug() {
final double beta = 0.4;
final double t = 5.0;
final double r = 0.1;
final double forward = 163.10;
final double k = 164.87;
final double volBeta = 4.298;
final EuropeanVanillaOption option = new EuropeanVanillaOption(k, t, true);
final CEVFunctionData cevData = new CEVFunctionData(forward, Math.exp(-r * t), volBeta, beta);
final double cevPrice = CEV.getPriceFunction(option).evaluate(cevData);
@SuppressWarnings("unused")
final double cevVol = BLACK_IMPLIED_VOL.getImpliedVolatility(new BlackFunctionData(forward, Math.exp(-r * t), volBeta), option, cevPrice);
//System.out.println(cevPrice+"\t"+cevVol);
}
}