/** * Obtains an instance. * * @param strike the strike * @param timeToExpiry the time to expiry, year fraction * @param putCall whether the option is put or call. * @return the option definition */ public static EuropeanVanillaOption of(double strike, double timeToExpiry, PutCall putCall) { return new EuropeanVanillaOption(strike, timeToExpiry, putCall); }
/** * 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); }
private double impliedVolatility( NormalFunctionData data, EuropeanVanillaOption option, double price) { return NormalFormulaRepository.impliedVolatility( price, data.getForward(), option.getStrike(), option.getTimeToExpiry(), data.getNormalVolatility(), data.getNumeraire(), option.getPutCall()); }
private EuropeanVanillaOption withStrike(EuropeanVanillaOption option, double strike) { return EuropeanVanillaOption.of(strike, option.getTimeToExpiry(), option.getPutCall()); }
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()); }
@Override public Double apply(SabrFormulaData data) { ArgChecker.notNull(data, "data"); return FUNCTION.volatility(forward, option.getStrike(), option.getTimeToExpiry(), data); } };
EuropeanVanillaOption.of(STRIKE_MID, EXPIRY_TIME, PutCall.CALL), EuropeanVanillaOption.of(STRIKE_MID, EXPIRY_TIME, PutCall.PUT), EuropeanVanillaOption.of(STRIKE_HIGH, EXPIRY_TIME, PutCall.CALL), EuropeanVanillaOption.of(STRIKE_HIGH, EXPIRY_TIME, PutCall.PUT), EuropeanVanillaOption.of(STRIKE_LOW, EXPIRY_TIME, PutCall.CALL), EuropeanVanillaOption.of(STRIKE_LOW, EXPIRY_TIME, PutCall.PUT) }; int n = options.length; double priceDINew = BARRIER_PRICER.price(SPOT, options[j].getStrike(), EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, options[j].isCall(), BARRIER_DOWN_IN); ValueDerivatives priceDIAdjointNew = BARRIER_PRICER.priceAdjoint(SPOT, options[j].getStrike(), EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, options[j].isCall(), BARRIER_DOWN_IN); double priceDIRb = rebate.price(SPOT, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, BARRIER_DOWN_OUT); ValueDerivatives priceDIAdjointRb = double priceDONew = BARRIER_PRICER.price(SPOT, options[j].getStrike(), EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, options[j].isCall(), BARRIER_DOWN_OUT); ValueDerivatives priceDOAdjointNew = BARRIER_PRICER.priceAdjoint(SPOT, options[j].getStrike(), EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, options[j].isCall(), BARRIER_DOWN_OUT); double priceDORb = rebate.price(SPOT, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, BARRIER_DOWN_IN); double priceUINew = BARRIER_PRICER.price(SPOT, options[j].getStrike(), EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, options[j].isCall(), BARRIER_UP_IN); ValueDerivatives priceUIAdjointNew = BARRIER_PRICER.priceAdjoint(SPOT, options[j].getStrike(), EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, options[j].isCall(), BARRIER_UP_IN); double priceUIRb = rebate.price(SPOT, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, BARRIER_UP_OUT); ValueDerivatives priceUIAdjointRb =
double strike = optionData.getStrike(); if (strike >= delta) { fdType = FiniteDifferenceType.CENTRAL;
public void test_serialization() { EuropeanVanillaOption test = EuropeanVanillaOption.of(STRIKE, TIME, CALL); assertSerialization(test); }
private void volatilityAdjoint2ForInstrument(EuropeanVanillaOption option, double tolerance1, double tolerance2) { double volatility = FUNCTION.volatility(F, option.getStrike(), option.getTimeToExpiry(), DATA); double[] volatilityAdjoint = toArray(FUNCTION.volatilityAdjoint(F, option.getStrike(), option.getTimeToExpiry(), DATA)); double[] volD = new double[6]; double[][] volD2 = new double[2][2]; double vol = FUNCTION.volatilityAdjoint2(F, option.getStrike(), option.getTimeToExpiry(), DATA, volD, volD2); assertEquals(volatility, vol, tolerance1); double volatilityFP = FUNCTION.volatility(F + deltaF, option.getStrike(), option.getTimeToExpiry(), DATA); double volatilityFM = FUNCTION.volatility(F - deltaF, option.getStrike(), option.getTimeToExpiry(), DATA); double derivativeFF_FD = (volatilityFP + volatilityFM - 2 * volatility) / (deltaF * deltaF); assertEquals(derivativeFF_FD, volD2[0][0], tolerance2); double volatilityKP = FUNCTION.volatility(F, option.getStrike() + deltaK, option.getTimeToExpiry(), DATA); double volatilityKM = FUNCTION.volatility(F, option.getStrike() - deltaK, option.getTimeToExpiry(), DATA); double derivativeKK_FD = (volatilityKP + volatilityKM - 2 * volatility) / (deltaK * deltaK); assertEquals(derivativeKK_FD, volD2[1][1], tolerance2); double volatilityFPKP = FUNCTION.volatility(F + deltaF, option.getStrike() + deltaK, option.getTimeToExpiry(), DATA); double derivativeFK_FD = (volatilityFPKP + volatility - volatilityFP - volatilityKP) / (deltaF * deltaK); assertEquals(derivativeFK_FD, volD2[0][1], tolerance2);
double strikeOut = 0.12; double shiftK = 0.000001; EuropeanVanillaOption optionIn = EuropeanVanillaOption.of(strikeIn, TIME_TO_EXPIRY, PutCall.CALL); EuropeanVanillaOption optionAt = EuropeanVanillaOption.of(strikeAt, TIME_TO_EXPIRY, PutCall.CALL); EuropeanVanillaOption optionOut = EuropeanVanillaOption.of(strikeOut, TIME_TO_EXPIRY, PutCall.CALL); EuropeanVanillaOption optionInKP = EuropeanVanillaOption.of(strikeIn + shiftK, TIME_TO_EXPIRY, PutCall.CALL); EuropeanVanillaOption optionAtKP = EuropeanVanillaOption.of(strikeAt + shiftK, TIME_TO_EXPIRY, PutCall.CALL); EuropeanVanillaOption optionOutKP = EuropeanVanillaOption.of(strikeOut + shiftK, TIME_TO_EXPIRY, PutCall.CALL); double priceIn = SABR_EXTRAPOLATION.price(optionIn.getStrike(), optionIn.getPutCall()); double priceInKP = SABR_EXTRAPOLATION.price(optionInKP.getStrike(), optionInKP.getPutCall()); double priceInDK = SABR_EXTRAPOLATION.priceDerivativeStrike(optionIn.getStrike(), optionIn.getPutCall()); double priceInDFExpected = (priceInKP - priceIn) / shiftK; assertEquals(priceInDFExpected, priceInDK, 1E-5); double priceAt = SABR_EXTRAPOLATION.price(optionAt.getStrike(), optionAt.getPutCall()); double priceAtKP = SABR_EXTRAPOLATION.price(optionAtKP.getStrike(), optionAtKP.getPutCall()); double priceAtDK = SABR_EXTRAPOLATION.priceDerivativeStrike(optionAt.getStrike(), optionAt.getPutCall()); double priceAtDFExpected = (priceAtKP - priceAt) / shiftK; assertEquals(priceAtDFExpected, priceAtDK, 1E-5); double priceOut = SABR_EXTRAPOLATION.price(optionOut.getStrike(), optionOut.getPutCall()); double priceOutKP = SABR_EXTRAPOLATION.price(optionOutKP.getStrike(), optionOutKP.getPutCall()); double priceOutDK = SABR_EXTRAPOLATION.priceDerivativeStrike(optionOut.getStrike(), optionOut.getPutCall()); double priceOutDFExpected = (priceOutKP - priceOut) / shiftK; assertEquals(priceOutDFExpected, priceOutDK, 1E-5);
@SuppressWarnings("synthetic-access") @Override public Double apply(NormalFunctionData data) { ArgChecker.notNull(data, "data"); return data.getNumeraire() * NormalFormulaRepository.price( data.getForward(), option.getStrike(), option.getTimeToExpiry(), data.getNormalVolatility(), option.getPutCall()); } };
public void testNegativeTime() { assertThrowsIllegalArg(() -> EuropeanVanillaOption.of(STRIKE, -TIME, CALL)); }
private void testVolatilityAdjoint(double forward, EuropeanVanillaOption optionData, SabrFormulaData sabrData, double eps, double tol) { double volatility = FUNCTION.volatility(forward, optionData.getStrike(), optionData.getTimeToExpiry(), sabrData); double[] volatilityAdjoint = toArray(FUNCTION.volatilityAdjoint( forward, optionData.getStrike(), optionData.getTimeToExpiry(), sabrData)); assertEquals(volatility, volatilityAdjoint[0], tol); assertEqualsRelTol("Forward Sensitivity" + sabrData.toString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Forward, eps), volatilityAdjoint[1], tol); assertEqualsRelTol("Strike Sensitivity" + sabrData.toString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Strike, eps), volatilityAdjoint[2], tol); assertEqualsRelTol("Alpha Sensitivity" + sabrData.toString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Alpha, eps), volatilityAdjoint[3], tol); assertEqualsRelTol("Beta Sensitivity" + sabrData.toString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Beta, eps), volatilityAdjoint[4], tol); assertEqualsRelTol("Rho Sensitivity" + sabrData.toString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Rho, eps), volatilityAdjoint[5], tol); assertEqualsRelTol("Nu Sensitivity" + sabrData.toString(), fdSensitivity(optionData, forward, sabrData, SabrParameter.Nu, eps), volatilityAdjoint[6], tol); }
/** * 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); } }
/** * Computes forward delta of an option in the normally distributed assets hypothesis (Bachelier model). * * @param option the option description * @param data the model data * @return delta */ public double getDelta(EuropeanVanillaOption option, NormalFunctionData data) { ArgChecker.notNull(option, "option"); ArgChecker.notNull(data, "data"); return data.getNumeraire() * NormalFormulaRepository.delta( data.getForward(), option.getStrike(), option.getTimeToExpiry(), data.getNormalVolatility(), 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)); }
double strikeOut = 0.12; double shiftK = 0.000001; EuropeanVanillaOption optionIn = EuropeanVanillaOption.of(strikeIn, TIME_TO_EXPIRY, PutCall.PUT); EuropeanVanillaOption optionAt = EuropeanVanillaOption.of(strikeAt, TIME_TO_EXPIRY, PutCall.PUT); EuropeanVanillaOption optionOut = EuropeanVanillaOption.of(strikeOut, TIME_TO_EXPIRY, PutCall.PUT); EuropeanVanillaOption optionInKP = EuropeanVanillaOption.of(strikeIn + shiftK, TIME_TO_EXPIRY, PutCall.PUT); EuropeanVanillaOption optionAtKP = EuropeanVanillaOption.of(strikeAt + shiftK, TIME_TO_EXPIRY, PutCall.PUT); EuropeanVanillaOption optionOutKP = EuropeanVanillaOption.of(strikeOut + shiftK, TIME_TO_EXPIRY, PutCall.PUT); double priceIn = SABR_EXTRAPOLATION.price(optionIn.getStrike(), optionIn.getPutCall()); double priceInKP = SABR_EXTRAPOLATION.price(optionInKP.getStrike(), optionInKP.getPutCall()); double priceInDK = SABR_EXTRAPOLATION.priceDerivativeStrike(optionIn.getStrike(), optionIn.getPutCall()); double priceInDFExpected = (priceInKP - priceIn) / shiftK; assertEquals(priceInDFExpected, priceInDK, 1E-5); double priceAt = SABR_EXTRAPOLATION.price(optionAt.getStrike(), optionAt.getPutCall()); double priceAtKP = SABR_EXTRAPOLATION.price(optionAtKP.getStrike(), optionAtKP.getPutCall()); double priceAtDK = SABR_EXTRAPOLATION.priceDerivativeStrike(optionAt.getStrike(), optionAt.getPutCall()); double priceAtDFExpected = (priceAtKP - priceAt) / shiftK; assertEquals(priceAtDFExpected, priceAtDK, 1E-5); double priceOut = SABR_EXTRAPOLATION.price(optionOut.getStrike(), optionOut.getPutCall()); double priceOutKP = SABR_EXTRAPOLATION.price(optionOutKP.getStrike(), optionOutKP.getPutCall()); double priceOutDK = SABR_EXTRAPOLATION.priceDerivativeStrike(optionOut.getStrike(), optionOut.getPutCall()); double priceOutDFExpected = (priceOutKP - priceOut) / shiftK; assertEquals(priceOutDFExpected, priceOutDK, 1E-5);
/** * Computes theta of an option in the normally distributed assets hypothesis (Bachelier model). * * @param option the option description * @param data the model data * @return theta */ public double getTheta(EuropeanVanillaOption option, NormalFunctionData data) { ArgChecker.notNull(option, "option"); ArgChecker.notNull(data, "data"); return data.getNumeraire() * NormalFormulaRepository.theta( data.getForward(), option.getStrike(), option.getTimeToExpiry(), data.getNormalVolatility(), option.getPutCall()); }