/** Test getDelta, getGamma and getVega */ @Test public void greeksTest() { double tol = 1.0e-12; double eps = 1.0e-5; double[] priceDerivative = new double[3]; for (EuropeanVanillaOption option : new EuropeanVanillaOption[] {ITM_CALL, ITM_PUT, OTM_CALL, OTM_PUT, ATM_CALL, ATM_PUT}) { // consistency with getPriceFunction for first order derivatives FUNCTION.getPriceAdjoint(option, VOL_DATA, priceDerivative); double delta = FUNCTION.getDelta(option, VOL_DATA); double vega = FUNCTION.getVega(option, VOL_DATA); assertEquals(delta, priceDerivative[0], tol); assertEquals(vega, priceDerivative[1], tol); // testing second order derivative against finite difference approximation NormalFunctionData dataUp = new NormalFunctionData(F + eps, DF, SIGMA); NormalFunctionData dataDw = new NormalFunctionData(F - eps, DF, SIGMA); double deltaUp = FUNCTION.getDelta(option, dataUp); double deltaDw = FUNCTION.getDelta(option, dataDw); double ref = 0.5 * (deltaUp - deltaDw) / eps; double gamma = FUNCTION.getGamma(option, VOL_DATA); assertEquals(ref, gamma, eps); EuropeanVanillaOption optionUp = new EuropeanVanillaOption(option.getStrike(), T + eps, option.isCall()); EuropeanVanillaOption optionDw = new EuropeanVanillaOption(option.getStrike(), T - eps, option.isCall()); double priceTimeUp = FUNCTION.getPriceAdjoint(optionUp, VOL_DATA, priceDerivative); double priceTimeDw = FUNCTION.getPriceAdjoint(optionDw, VOL_DATA, priceDerivative); ref = -0.5 * (priceTimeUp - priceTimeDw) / eps; double theta = FUNCTION.getTheta(option, VOL_DATA); assertEquals(ref, theta, eps); } }
/** Testing the branch for sigmaRootT < 1e-16 */ @Test public void smallParameterGreeksTest() { double eps = 1.0e-5; double[] der = new double[3]; NormalFunctionData dataVolUp = new NormalFunctionData(F, DF, eps); NormalFunctionData dataFwUp = new NormalFunctionData(F + eps, DF, 0.0); NormalFunctionData dataFwDw = new NormalFunctionData(F - eps, DF, 0.0); for (EuropeanVanillaOption option : new EuropeanVanillaOption[] {ITM_CALL, ITM_PUT, OTM_CALL, OTM_PUT, ATM_CALL, ATM_PUT}) { double delta = FUNCTION.getDelta(option, ZERO_VOL_DATA); double priceUp = FUNCTION.getPriceAdjoint(option, dataFwUp, der); double priceDw = FUNCTION.getPriceAdjoint(option, dataFwDw, der); double refDelta = 0.5 * (priceUp - priceDw) / eps; assertEquals(refDelta, delta, eps); double vega = FUNCTION.getVega(option, ZERO_VOL_DATA); double priceVolUp = FUNCTION.getPriceAdjoint(option, dataVolUp, der); double price = FUNCTION.getPriceAdjoint(option, ZERO_VOL_DATA, der); double refVega = (priceVolUp - price) / eps; assertEquals(refVega, vega, eps); double gamma = FUNCTION.getGamma(option, ZERO_VOL_DATA); double deltaUp = FUNCTION.getDelta(option, dataFwUp); double deltaDw = FUNCTION.getDelta(option, dataFwDw); double refGamma = 0.5 * (deltaUp - deltaDw) / eps; if (Math.abs(refGamma) > 0.1 / eps) { // infinity handled assertTrue(Double.isInfinite(gamma)); } else { assertEquals(refGamma, gamma, eps); } EuropeanVanillaOption optionUp = new EuropeanVanillaOption(option.getStrike(), T + eps, option.isCall()); EuropeanVanillaOption optionDw = new EuropeanVanillaOption(option.getStrike(), T - eps, option.isCall()); double priceTimeUp = FUNCTION.getPriceAdjoint(optionUp, ZERO_VOL_DATA, der); double priceTimeDw = FUNCTION.getPriceAdjoint(optionDw, ZERO_VOL_DATA, der); double refTheta = -0.5 * (priceTimeUp - priceTimeDw) / eps; double theta = FUNCTION.getTheta(option, ZERO_VOL_DATA); assertEquals(refTheta, theta, eps); } }
@Test public void testPriceAdjoint() { // Price double price = FUNCTION.getPriceFunction(ITM_CALL).evaluate(VOL_DATA); double[] priceDerivative = new double[3]; double priceAdjoint = FUNCTION.getPriceAdjoint(ITM_CALL, VOL_DATA, priceDerivative); assertEquals(price, priceAdjoint, 1E-10); // Price with 0 volatility double price0 = FUNCTION.getPriceFunction(ITM_CALL).evaluate(ZERO_VOL_DATA); double[] price0Derivative = new double[3]; double price0Adjoint = FUNCTION.getPriceAdjoint(ITM_CALL, ZERO_VOL_DATA, price0Derivative); assertEquals(price0, price0Adjoint, 1E-10); // Derivative forward. double deltaF = 0.01; NormalFunctionData dataFP = new NormalFunctionData(F + deltaF, DF, SIGMA); NormalFunctionData dataFM = new NormalFunctionData(F - deltaF, DF, SIGMA); double priceFP = FUNCTION.getPriceFunction(ITM_CALL).evaluate(dataFP); double priceFM = FUNCTION.getPriceFunction(ITM_CALL).evaluate(dataFM); double derivativeF_FD = (priceFP - priceFM) / (2 * deltaF); assertEquals(derivativeF_FD, priceDerivative[0], 1E-7); // Derivative strike. double deltaK = 0.01; EuropeanVanillaOption optionKP = new EuropeanVanillaOption(F - DELTA + deltaK, T, true); EuropeanVanillaOption optionKM = new EuropeanVanillaOption(F - DELTA - deltaK, T, true); double priceKP = FUNCTION.getPriceFunction(optionKP).evaluate(VOL_DATA); double priceKM = FUNCTION.getPriceFunction(optionKM).evaluate(VOL_DATA); double derivativeK_FD = (priceKP - priceKM) / (2 * deltaK); assertEquals(derivativeK_FD, priceDerivative[2], 1E-7); // Derivative volatility. double deltaV = 0.0001; NormalFunctionData dataVP = new NormalFunctionData(F, DF, SIGMA + deltaV); NormalFunctionData dataVM = new NormalFunctionData(F, DF, SIGMA - deltaV); double priceVP = FUNCTION.getPriceFunction(ITM_CALL).evaluate(dataVP); double priceVM = FUNCTION.getPriceFunction(ITM_CALL).evaluate(dataVM); double derivativeV_FD = (priceVP - priceVM) / (2 * deltaV); assertEquals(derivativeV_FD, priceDerivative[1], 1E-6); }