ITM_CALL, ITM_PUT, OTM_CALL, OTM_PUT, ATM_CALL, ATM_PUT}; for (EuropeanVanillaOption option : options) { double delta = FUNCTION.getDelta(option, ZERO_VOL_DATA); double priceUp = FUNCTION.getPriceFunction(option).apply(dataFwUp); double priceDw = FUNCTION.getPriceFunction(option).apply(dataFwDw); double refDelta = 0.5 * (priceUp - priceDw) / eps; assertEquals(delta, refDelta, eps); double vega = FUNCTION.getVega(option, ZERO_VOL_DATA); double priceVolUp = FUNCTION.getPriceFunction(option).apply(dataVolUp); double price = FUNCTION.getPriceFunction(option).apply(ZERO_VOL_DATA); double refVega = (priceVolUp - price) / eps; assertEquals(vega, refVega, 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 double priceTimeUp = FUNCTION.getPriceFunction(optionUp).apply(ZERO_VOL_DATA); double priceTimeDw = FUNCTION.getPriceFunction(optionDw).apply(ZERO_VOL_DATA); double refTheta = -0.5 * (priceTimeUp - priceTimeDw) / eps; double theta = FUNCTION.getTheta(option, ZERO_VOL_DATA); assertEquals(theta, refTheta, eps);
double price = FUNCTION.getPriceFunction(ITM_CALL).apply(VOL_DATA); ValueDerivatives priceAdjoint = FUNCTION.getPriceAdjoint(ITM_CALL, VOL_DATA); assertEquals(priceAdjoint.getValue(), price, 1E-10); double price0 = FUNCTION.getPriceFunction(ITM_CALL).apply(ZERO_VOL_DATA); ValueDerivatives price0Adjoint = FUNCTION.getPriceAdjoint(ITM_CALL, ZERO_VOL_DATA); assertEquals(price0Adjoint.getValue(), price0, 1E-10); NormalFunctionData dataFP = NormalFunctionData.of(F + deltaF, DF, SIGMA); NormalFunctionData dataFM = NormalFunctionData.of(F - deltaF, DF, SIGMA); double priceFP = FUNCTION.getPriceFunction(ITM_CALL).apply(dataFP); double priceFM = FUNCTION.getPriceFunction(ITM_CALL).apply(dataFM); double derivativeF_FD = (priceFP - priceFM) / (2 * deltaF); assertEquals(priceAdjoint.getDerivative(0), derivativeF_FD, 1E-7); EuropeanVanillaOption optionKP = EuropeanVanillaOption.of(F - DELTA + deltaK, T, CALL); EuropeanVanillaOption optionKM = EuropeanVanillaOption.of(F - DELTA - deltaK, T, CALL); double priceKP = FUNCTION.getPriceFunction(optionKP).apply(VOL_DATA); double priceKM = FUNCTION.getPriceFunction(optionKM).apply(VOL_DATA); double derivativeK_FD = (priceKP - priceKM) / (2 * deltaK); assertEquals(priceAdjoint.getDerivative(2), derivativeK_FD, 1E-7); NormalFunctionData dataVP = NormalFunctionData.of(F, DF, SIGMA + deltaV); NormalFunctionData dataVM = NormalFunctionData.of(F, DF, SIGMA - deltaV); double priceVP = FUNCTION.getPriceFunction(ITM_CALL).apply(dataVP); double priceVM = FUNCTION.getPriceFunction(ITM_CALL).apply(dataVM); double derivativeV_FD = (priceVP - priceVM) / (2 * deltaV); assertEquals(priceAdjoint.getDerivative(1), derivativeV_FD, 1E-6);
public void testZeroVolPrice() { assertEquals(FUNCTION.getPriceFunction(ITM_CALL).apply(ZERO_VOL_DATA), DF * DELTA, 1e-15); assertEquals(FUNCTION.getPriceFunction(OTM_CALL).apply(ZERO_VOL_DATA), 0, 1e-15); assertEquals(FUNCTION.getPriceFunction(ITM_PUT).apply(ZERO_VOL_DATA), DF * DELTA, 1e-15); assertEquals(FUNCTION.getPriceFunction(OTM_PUT).apply(ZERO_VOL_DATA), 0, 1e-15); }
public void present_value_delta_formula() { double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD); double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD); double volatility = NORMAL_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(), SWAP_TENOR_YEAR, STRIKE, forward); NormalFunctionData normalData = NormalFunctionData.of(forward, Math.abs(pvbp), volatility); double expiry = NORMAL_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.getExpiry()); EuropeanVanillaOption option = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); double pvDeltaExpected = NORMAL.getDelta(option, normalData); CurrencyAmount pvDeltaComputed = PRICER_SWAPTION_NORMAL.presentValueDelta(SWAPTION_LONG_REC, MULTI_USD, NORMAL_VOLS_USD_STD); assertEquals(pvDeltaComputed.getCurrency(), USD); assertEquals(pvDeltaComputed.getAmount(), pvDeltaExpected, TOLERANCE_PV); }
public void present_value_gamma_formula() { double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD); double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD); double volatility = NORMAL_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(), SWAP_TENOR_YEAR, STRIKE, forward); NormalFunctionData normalData = NormalFunctionData.of(forward, Math.abs(pvbp), volatility); double expiry = NORMAL_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.getExpiry()); EuropeanVanillaOption option = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); double pvGammaExpected = NORMAL.getGamma(option, normalData); CurrencyAmount pvGammaComputed = PRICER_SWAPTION_NORMAL.presentValueGamma(SWAPTION_LONG_REC, MULTI_USD, NORMAL_VOLS_USD_STD); assertEquals(pvGammaComputed.getCurrency(), USD); assertEquals(pvGammaComputed.getAmount(), pvGammaExpected, TOLERANCE_PV); }
public void present_value_theta_formula() { double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD); double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD); double volatility = NORMAL_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(), SWAP_TENOR_YEAR, STRIKE, forward); NormalFunctionData normalData = NormalFunctionData.of(forward, Math.abs(pvbp), volatility); double expiry = NORMAL_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.getExpiry()); EuropeanVanillaOption option = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); double pvThetaExpected = NORMAL.getTheta(option, normalData); CurrencyAmount pvThetaComputed = PRICER_SWAPTION_NORMAL.presentValueTheta(SWAPTION_LONG_REC, MULTI_USD, NORMAL_VOLS_USD_STD); assertEquals(pvThetaComputed.getCurrency(), USD); assertEquals(pvThetaComputed.getAmount(), pvThetaExpected, TOLERANCE_PV); }
public void priceSensitivityNormalVolatility_from_future_price() { IborIndexRates mockIbor = mock(IborIndexRates.class); SimpleRatesProvider prov = new SimpleRatesProvider(); prov.setIborRates(mockIbor); when(mockIbor.rate(OPTION.getUnderlyingFuture().getIborRate().getObservation())).thenReturn(RATE); double futurePrice = 0.9875; double strike = OPTION.getStrikePrice(); double timeToExpiry = ACT_365F.relativeYearFraction(VAL_DATE, OPTION.getExpiryDate()); double priceSimpleMoneyness = strike - futurePrice; double normalVol = PARAMETERS_PRICE.zValue(timeToExpiry, priceSimpleMoneyness); EuropeanVanillaOption option = EuropeanVanillaOption.of(strike, timeToExpiry, OPTION.getPutCall()); NormalFunctionData normalPoint = NormalFunctionData.of(futurePrice, 1.0, normalVol); double optionVegaExpected = NORMAL_FUNCTION.getVega(option, normalPoint); IborFutureOptionSensitivity optionVegaComputed = OPTION_PRICER.priceSensitivityModelParamsVolatility( OPTION, prov, VOL_SIMPLE_MONEY_PRICE, futurePrice); assertEquals(optionVegaComputed.getSensitivity(), optionVegaExpected, TOLERANCE_PRICE); assertEquals(optionVegaComputed.getExpiry(), timeToExpiry); assertEquals(optionVegaComputed.getFixingDate(), OPTION.getUnderlyingFuture().getIborRate().getObservation().getFixingDate()); assertEquals(optionVegaComputed.getStrikePrice(), OPTION.getStrikePrice()); assertEquals(optionVegaComputed.getFuturePrice(), futurePrice); }
public void testInvalid() { assertThrowsIllegalArg(() -> FUNCTION.getPriceFunction(null)); assertThrowsIllegalArg(() -> FUNCTION.getPriceFunction(ITM_CALL).apply((NormalFunctionData) null)); }
public void test_presentValueDelta() { CurrencyAmount pvDeltaRecComputed = PRICER_SWAPTION.presentValueDelta(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS); CurrencyAmount pvDeltaPayComputed = PRICER_SWAPTION.presentValueDelta(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS); double forward = PRICER_SWAP.parRate(RSWAP_REC, RATE_PROVIDER); double annuityCash = PRICER_SWAP.getLegPricer().annuityCash(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), forward); double volatility = VOLS.volatility(SWAPTION_REC_LONG.getExpiry(), SWAP_TENOR_YEAR, STRIKE, forward); double discount = RATE_PROVIDER.discountFactor(USD, SETTLE_DATE); NormalFunctionData normalData = NormalFunctionData.of(forward, annuityCash * discount, volatility); double expiry = VOLS.relativeTime(SWAPTION_REC_LONG.getExpiry()); EuropeanVanillaOption optionRec = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); EuropeanVanillaOption optionPay = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.CALL); double pvDeltaRecExpected = NORMAL.getDelta(optionRec, normalData); double pvDeltaPayExpected = -NORMAL.getDelta(optionPay, normalData); assertEquals(pvDeltaRecComputed.getCurrency(), USD); assertEquals(pvDeltaRecComputed.getAmount(), pvDeltaRecExpected, NOTIONAL * TOL); assertEquals(pvDeltaPayComputed.getCurrency(), USD); assertEquals(pvDeltaPayComputed.getAmount(), pvDeltaPayExpected, NOTIONAL * TOL); }
public void test_presentValueGamma() { CurrencyAmount pvGammaRecComputed = PRICER_SWAPTION.presentValueGamma(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS); CurrencyAmount pvGammaPayComputed = PRICER_SWAPTION.presentValueGamma(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS); double forward = PRICER_SWAP.parRate(RSWAP_REC, RATE_PROVIDER); double annuityCash = PRICER_SWAP.getLegPricer().annuityCash(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), forward); double volatility = VOLS.volatility(SWAPTION_REC_LONG.getExpiry(), SWAP_TENOR_YEAR, STRIKE, forward); double discount = RATE_PROVIDER.discountFactor(USD, SETTLE_DATE); NormalFunctionData normalData = NormalFunctionData.of(forward, annuityCash * discount, volatility); double expiry = VOLS.relativeTime(SWAPTION_REC_LONG.getExpiry()); EuropeanVanillaOption optionRec = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); EuropeanVanillaOption optionPay = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.CALL); double pvGammaRecExpected = NORMAL.getGamma(optionRec, normalData); double pvGammaPayExpected = -NORMAL.getGamma(optionPay, normalData); assertEquals(pvGammaRecComputed.getCurrency(), USD); assertEquals(pvGammaRecComputed.getAmount(), pvGammaRecExpected, NOTIONAL * TOL); assertEquals(pvGammaPayComputed.getCurrency(), USD); assertEquals(pvGammaPayComputed.getAmount(), pvGammaPayExpected, NOTIONAL * TOL); }
public void test_presentValueTheta() { CurrencyAmount pvThetaRecComputed = PRICER_SWAPTION.presentValueTheta(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS); CurrencyAmount pvThetaPayComputed = PRICER_SWAPTION.presentValueTheta(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS); double forward = PRICER_SWAP.parRate(RSWAP_REC, RATE_PROVIDER); double annuityCash = PRICER_SWAP.getLegPricer().annuityCash(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), forward); double volatility = VOLS.volatility(SWAPTION_REC_LONG.getExpiry(), SWAP_TENOR_YEAR, STRIKE, forward); double discount = RATE_PROVIDER.discountFactor(USD, SETTLE_DATE); NormalFunctionData normalData = NormalFunctionData.of(forward, annuityCash * discount, volatility); double expiry = VOLS.relativeTime(SWAPTION_REC_LONG.getExpiry()); EuropeanVanillaOption optionRec = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); EuropeanVanillaOption optionPay = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.CALL); double pvThetaRecExpected = NORMAL.getTheta(optionRec, normalData); double pvThetaPayExpected = -NORMAL.getTheta(optionPay, normalData); assertEquals(pvThetaRecComputed.getCurrency(), USD); assertEquals(pvThetaRecComputed.getAmount(), pvThetaRecExpected, NOTIONAL * TOL); assertEquals(pvThetaPayComputed.getCurrency(), USD); assertEquals(pvThetaPayComputed.getAmount(), pvThetaPayExpected, NOTIONAL * TOL); }
public void greeksTest() { double tol = 1.0e-12; double eps = 1.0e-5; EuropeanVanillaOption[] options = new EuropeanVanillaOption[] { ITM_CALL, ITM_PUT, OTM_CALL, OTM_PUT, ATM_CALL, ATM_PUT}; for (EuropeanVanillaOption option : options) { // consistency with getPriceFunction for first order derivatives ValueDerivatives price = FUNCTION.getPriceAdjoint(option, VOL_DATA); double delta = FUNCTION.getDelta(option, VOL_DATA); double vega = FUNCTION.getVega(option, VOL_DATA); assertEquals(price.getDerivative(0), delta, tol); assertEquals(price.getDerivative(1), vega, tol); // testing second order derivative against finite difference approximation NormalFunctionData dataUp = NormalFunctionData.of(F + eps, DF, SIGMA); NormalFunctionData dataDw = NormalFunctionData.of(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(gamma, ref, eps); EuropeanVanillaOption optionUp = EuropeanVanillaOption.of(option.getStrike(), T + eps, option.getPutCall()); EuropeanVanillaOption optionDw = EuropeanVanillaOption.of(option.getStrike(), T - eps, option.getPutCall()); double priceTimeUp = FUNCTION.getPriceFunction(optionUp).apply(VOL_DATA); double priceTimeDw = FUNCTION.getPriceFunction(optionDw).apply(VOL_DATA); ref = -0.5 * (priceTimeUp - priceTimeDw) / eps; double theta = FUNCTION.getTheta(option, VOL_DATA); assertEquals(theta, ref, eps); } }
public void present_value_formula() { double forward = PRICER_SWAP.parRate(RSWAP_REC, MULTI_USD); double pvbp = PRICER_SWAP.getLegPricer().pvbp(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), MULTI_USD); double volatility = NORMAL_VOLS_USD_STD.volatility(SWAPTION_LONG_REC.getExpiry(), SWAP_TENOR_YEAR, STRIKE, forward); NormalFunctionData normalData = NormalFunctionData.of(forward, Math.abs(pvbp), volatility); double expiry = NORMAL_VOLS_USD_STD.relativeTime(SWAPTION_LONG_REC.getExpiry()); EuropeanVanillaOption option = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); double pvExpected = NORMAL.getPriceFunction(option).apply(normalData); CurrencyAmount pvComputed = PRICER_SWAPTION_NORMAL.presentValue(SWAPTION_LONG_REC, MULTI_USD, NORMAL_VOLS_USD_STD); assertEquals(pvComputed.getCurrency(), USD); assertEquals(pvComputed.getAmount(), pvExpected, TOLERANCE_PV); }
public void delta_from_future_price() { IborIndexRates mockIbor = mock(IborIndexRates.class); SimpleRatesProvider prov = new SimpleRatesProvider(); prov.setIborRates(mockIbor); when(mockIbor.rate(OPTION.getUnderlyingFuture().getIborRate().getObservation())).thenReturn(RATE); double futurePrice = 0.9875; double strike = OPTION.getStrikePrice(); double timeToExpiry = ACT_365F.relativeYearFraction(VAL_DATE, OPTION.getExpiryDate()); double priceSimpleMoneyness = strike - futurePrice; double normalVol = PARAMETERS_PRICE.zValue(timeToExpiry, priceSimpleMoneyness); EuropeanVanillaOption option = EuropeanVanillaOption.of(strike, timeToExpiry, OPTION.getPutCall()); NormalFunctionData normalPoint = NormalFunctionData.of(futurePrice, 1.0, normalVol); double optionDeltaExpected = NORMAL_FUNCTION.getDelta(option, normalPoint); double optionDeltaComputed = OPTION_PRICER.deltaStickyStrike(OPTION, prov, VOL_SIMPLE_MONEY_PRICE, futurePrice); assertEquals(optionDeltaComputed, optionDeltaExpected, TOLERANCE_PRICE); }
public void test_presentValue() { CurrencyAmount pvRecComputed = PRICER_SWAPTION.presentValue(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS); CurrencyAmount pvPayComputed = PRICER_SWAPTION.presentValue(SWAPTION_PAY_SHORT, RATE_PROVIDER, VOLS); double forward = PRICER_SWAP.parRate(RSWAP_REC, RATE_PROVIDER); double annuityCash = PRICER_SWAP.getLegPricer().annuityCash(RSWAP_REC.getLegs(SwapLegType.FIXED).get(0), forward); double volatility = VOLS.volatility(SWAPTION_REC_LONG.getExpiry(), SWAP_TENOR_YEAR, STRIKE, forward); double discount = RATE_PROVIDER.discountFactor(USD, SETTLE_DATE); NormalFunctionData normalData = NormalFunctionData.of(forward, annuityCash * discount, volatility); double expiry = VOLS.relativeTime(SWAPTION_REC_LONG.getExpiry()); EuropeanVanillaOption optionRec = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.PUT); EuropeanVanillaOption optionPay = EuropeanVanillaOption.of(STRIKE, expiry, PutCall.CALL); double pvRecExpected = NORMAL.getPriceFunction(optionRec).apply(normalData); double pvPayExpected = -NORMAL.getPriceFunction(optionPay).apply(normalData); assertEquals(pvRecComputed.getCurrency(), USD); assertEquals(pvRecComputed.getAmount(), pvRecExpected, NOTIONAL * TOL); assertEquals(pvPayComputed.getCurrency(), USD); assertEquals(pvPayComputed.getAmount(), pvPayExpected, NOTIONAL * TOL); }
public void price_from_future_price() { IborIndexRates mockIbor = mock(IborIndexRates.class); SimpleRatesProvider prov = new SimpleRatesProvider(); prov.setIborRates(mockIbor); when(mockIbor.rate(OPTION.getUnderlyingFuture().getIborRate().getObservation())).thenReturn(RATE); double futurePrice = 0.9875; double strike = OPTION.getStrikePrice(); double timeToExpiry = ACT_365F.relativeYearFraction(VAL_DATE, OPTION.getExpiryDate()); double priceSimpleMoneyness = strike - futurePrice; double normalVol = PARAMETERS_PRICE.zValue(timeToExpiry, priceSimpleMoneyness); EuropeanVanillaOption option = EuropeanVanillaOption.of(strike, timeToExpiry, OPTION.getPutCall()); NormalFunctionData normalPoint = NormalFunctionData.of(futurePrice, 1.0, normalVol); double optionPriceExpected = NORMAL_FUNCTION.getPriceFunction(option).apply(normalPoint); double optionPriceComputed = OPTION_PRICER.price(OPTION, prov, VOL_SIMPLE_MONEY_PRICE, futurePrice); assertEquals(optionPriceComputed, optionPriceExpected, TOLERANCE_PRICE); }