/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.option.definition;
import static org.testng.AssertJUnit.assertEquals;
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.BlackPriceFunction;
import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption;
import com.opengamma.util.test.TestGroup;
/**
* Tests related to the construction of the data required to describe a delta dependent smile from ATM, risk reversal and strangle as used in Forex market.
*/
@Test(groups = TestGroup.UNIT)
public class SmileDeltaParametersTest {
private static final double TIME_TO_EXPIRY = 2.0;
private static final double FORWARD = 1.40;
private static final double ATM = 0.185;
private static final double[] DELTA = new double[] {0.10, 0.25};
private static final double[] RISK_REVERSAL = new double[] {-0.0130, -0.0050};
private static final double[] STRANGLE = new double[] {0.0300, 0.0100};
private static final SmileDeltaParameters SMILE = new SmileDeltaParameters(TIME_TO_EXPIRY, ATM, DELTA, RISK_REVERSAL, STRANGLE);
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNullDelta() {
new SmileDeltaParameters(TIME_TO_EXPIRY, ATM, null, RISK_REVERSAL, STRANGLE);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testRRLength() {
new SmileDeltaParameters(TIME_TO_EXPIRY, ATM, DELTA, new double[3], STRANGLE);
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testStrangleLength() {
new SmileDeltaParameters(TIME_TO_EXPIRY, ATM, DELTA, RISK_REVERSAL, new double[3]);
}
@Test
/**
* Tests the constructor directly from volatilities (not RR and S).
*/
public void constructorVolatility() {
double[] volatility = SMILE.getVolatility();
SmileDeltaParameters smileFromVolatility = new SmileDeltaParameters(TIME_TO_EXPIRY, DELTA, volatility);
assertEquals("Smile by delta: constructor", SMILE, smileFromVolatility);
}
@Test
/**
* Tests the getters.
*/
public void getter() {
assertEquals("Smile by delta: time to expiry", TIME_TO_EXPIRY, SMILE.getTimeToExpiry());
assertEquals("Smile by delta: delta", DELTA, SMILE.getDelta());
SmileDeltaParameters smile2 = new SmileDeltaParameters(TIME_TO_EXPIRY, DELTA, SMILE.getVolatility());
assertEquals("Smile by delta: volatility", SMILE.getVolatility(), smile2.getVolatility());
}
@Test
/**
* Tests the volatility computations.
*/
public void volatility() {
double[] volatility = SMILE.getVolatility();
int nbDelta = DELTA.length;
assertEquals("Volatility: ATM", ATM, volatility[nbDelta]);
for (int loopdelta = 0; loopdelta < nbDelta; loopdelta++) {
assertEquals("Volatility: Risk Reversal " + loopdelta, RISK_REVERSAL[loopdelta], volatility[2 * nbDelta - loopdelta] - volatility[loopdelta], 1.0E-8);
assertEquals("Volatility: Strangle " + loopdelta, STRANGLE[loopdelta], (volatility[2 * nbDelta - loopdelta] + volatility[loopdelta]) / 2 - volatility[nbDelta], 1.0E-8);
}
}
@Test
/**
* Tests the strikes computations.
*/
public void strike() {
double[] strike = SMILE.getStrike(FORWARD);
BlackPriceFunction function = new BlackPriceFunction();
double[] volatility = SMILE.getVolatility();
int nbDelta = DELTA.length;
for (int loopdelta = 0; loopdelta < nbDelta; loopdelta++) {
BlackFunctionData dataPut = new BlackFunctionData(FORWARD, 1.0, volatility[loopdelta]);
EuropeanVanillaOption optionPut = new EuropeanVanillaOption(strike[loopdelta], TIME_TO_EXPIRY, false);
double[] dPut = function.getPriceAdjoint(optionPut, dataPut);
assertEquals("Strike: Put " + loopdelta, dPut[1], -DELTA[loopdelta], 1.0E-8);
BlackFunctionData dataCall = new BlackFunctionData(FORWARD, 1.0, volatility[2 * nbDelta - loopdelta]);
EuropeanVanillaOption optionCall = new EuropeanVanillaOption(strike[2 * nbDelta - loopdelta], TIME_TO_EXPIRY, true);
double[] dCall = function.getPriceAdjoint(optionCall, dataCall);
assertEquals("Strike: Call " + loopdelta, dCall[1], DELTA[loopdelta], 1.0E-8);
}
BlackFunctionData data = new BlackFunctionData(FORWARD, 1.0, volatility[nbDelta]);
EuropeanVanillaOption optionPut = new EuropeanVanillaOption(strike[nbDelta], TIME_TO_EXPIRY, false);
double[] dPut = function.getPriceAdjoint(optionPut, data);
EuropeanVanillaOption optionCall = new EuropeanVanillaOption(strike[nbDelta], TIME_TO_EXPIRY, true);
double[] dCall = function.getPriceAdjoint(optionCall, data);
assertEquals("Strike: ATM", dCall[1] + dPut[1], 0.0, 1.0E-8);
}
@Test(enabled = false)
/**
* Tests of performance. "enabled = false" for the standard testing.
*/
public void performance() {
int nbDelta = DELTA.length;
long startTime, endTime;
final int nbTest = 1000;
SmileDeltaParameters[] smile = new SmileDeltaParameters[nbTest];
startTime = System.currentTimeMillis();
for (int looptest = 0; looptest < nbTest; looptest++) {
smile[looptest] = new SmileDeltaParameters(TIME_TO_EXPIRY, ATM, DELTA, RISK_REVERSAL, STRANGLE);
}
endTime = System.currentTimeMillis();
System.out.println(nbTest + " smile from ATM/RR/S in delta term: " + (endTime - startTime) + " ms");
startTime = System.currentTimeMillis();
double[][] strikes = new double[nbTest][2 * nbDelta + 1];
for (int looptest = 0; looptest < nbTest; looptest++) {
strikes[looptest] = SMILE.getStrike(FORWARD);
}
endTime = System.currentTimeMillis();
System.out.println(nbTest + " smile from ATM/RR/S in delta term: " + (endTime - startTime) + " ms");
}
}