public void test_serialization() { EuropeanVanillaOption test = EuropeanVanillaOption.of(STRIKE, TIME, CALL); assertSerialization(test); }
public void testNegativeTime() { assertThrowsIllegalArg(() -> EuropeanVanillaOption.of(STRIKE, -TIME, CALL)); }
public void test_of() { EuropeanVanillaOption test = EuropeanVanillaOption.of(STRIKE, TIME, CALL); assertEquals(test.getStrike(), STRIKE, 0d); assertEquals(test.getTimeToExpiry(), TIME, 0d); assertEquals(test.getPutCall(), CALL); assertTrue(test.isCall()); }
private EuropeanVanillaOption withStrike(EuropeanVanillaOption option, double strike) { return EuropeanVanillaOption.of(strike, option.getTimeToExpiry(), option.getPutCall()); }
public void intrinsic_price() { NormalFunctionData data = NormalFunctionData.of(1.0, 1.0, 0.01); EuropeanVanillaOption option1 = EuropeanVanillaOption.of(0.5, 1.0, PutCall.CALL); assertThrowsIllegalArg(() -> impliedVolatility(data, option1, 1e-6)); EuropeanVanillaOption option2 = EuropeanVanillaOption.of(1.5, 1.0, PutCall.PUT); assertThrowsIllegalArg(() -> impliedVolatility(data, option2, 1e-6)); }
/** * Tests that the smile and its derivatives are smooth enough in SABR model with extrapolation. */ public void smileSmooth() { int nbPts = 100; double rangeStrike = 0.02; double[] price = new double[nbPts + 1]; double[] strike = new double[nbPts + 1]; for (int looppts = 0; looppts <= nbPts; looppts++) { strike[looppts] = CUT_OFF_STRIKE - rangeStrike + looppts * 2.0 * rangeStrike / nbPts; EuropeanVanillaOption option = EuropeanVanillaOption.of(strike[looppts], TIME_TO_EXPIRY, PutCall.CALL); price[looppts] = SABR_EXTRAPOLATION.price(option.getStrike(), option.getPutCall()); } double[] priceD = new double[nbPts]; double[] priceD2 = new double[nbPts]; for (int looppts = 1; looppts < nbPts; looppts++) { priceD[looppts] = (price[looppts + 1] - price[looppts - 1]) / (strike[looppts + 1] - strike[looppts - 1]); priceD2[looppts] = (price[looppts + 1] + price[looppts - 1] - 2 * price[looppts]) / ((strike[looppts + 1] - strike[looppts]) * (strike[looppts + 1] - strike[looppts])); } for (int looppts = 2; looppts < nbPts; looppts++) { assertEquals(priceD[looppts - 1], priceD[looppts], 1.5E-3); assertEquals(priceD2[looppts - 1], priceD2[looppts], 1.5E-1); } }
/** * Tests the price put/call parity for options in SABR model with extrapolation. */ public void pricePutCallParity() { double strikeIn = 0.08; double strikeAt = CUT_OFF_STRIKE; double strikeOut = 0.12; EuropeanVanillaOption callIn = EuropeanVanillaOption.of(strikeIn, TIME_TO_EXPIRY, PutCall.CALL); EuropeanVanillaOption putIn = EuropeanVanillaOption.of(strikeIn, TIME_TO_EXPIRY, PutCall.PUT); EuropeanVanillaOption callAt = EuropeanVanillaOption.of(strikeAt, TIME_TO_EXPIRY, PutCall.CALL); EuropeanVanillaOption putAt = EuropeanVanillaOption.of(strikeAt, TIME_TO_EXPIRY, PutCall.PUT); EuropeanVanillaOption callOut = EuropeanVanillaOption.of(strikeOut, TIME_TO_EXPIRY, PutCall.CALL); EuropeanVanillaOption putOut = EuropeanVanillaOption.of(strikeOut, TIME_TO_EXPIRY, PutCall.PUT); double priceCallIn = SABR_EXTRAPOLATION.price(callIn.getStrike(), callIn.getPutCall()); double pricePutIn = SABR_EXTRAPOLATION.price(putIn.getStrike(), putIn.getPutCall()); assertEquals(FORWARD - strikeIn, priceCallIn - pricePutIn, TOLERANCE_PRICE); double priceCallAt = SABR_EXTRAPOLATION.price(callAt.getStrike(), callAt.getPutCall()); double pricePutAt = SABR_EXTRAPOLATION.price(putAt.getStrike(), putAt.getPutCall()); assertEquals(FORWARD - strikeAt, priceCallAt - pricePutAt, TOLERANCE_PRICE); double priceCallOut = SABR_EXTRAPOLATION.price(callOut.getStrike(), callOut.getPutCall()); double pricePutOut = SABR_EXTRAPOLATION.price(putOut.getStrike(), putOut.getPutCall()); assertEquals(FORWARD - strikeOut, priceCallOut - pricePutOut, TOLERANCE_PRICE); }
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 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); }
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 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 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 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 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 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_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 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); }