private void testDerivatives(double strike, boolean isCall, SimpleConstantContinuousBarrier barrier) { ValueDerivatives computed = BARRIER_PRICER.priceAdjoint( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, isCall, barrier); double spotUp = BARRIER_PRICER.price( SPOT + EPS_FD, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, isCall, barrier); double spotDw = BARRIER_PRICER.price( SPOT - EPS_FD, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, isCall, barrier); double strikeUp = BARRIER_PRICER.price( SPOT, strike + EPS_FD, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, isCall, barrier); double strikeDw = BARRIER_PRICER.price( SPOT, strike - EPS_FD, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, isCall, barrier); double rateUp = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM + EPS_FD, VOLATILITY, isCall, barrier); double rateDw = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM - EPS_FD, VOLATILITY, isCall, barrier); double costUp = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY + EPS_FD, RATE_DOM, VOLATILITY, isCall, barrier); double costDw = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY - EPS_FD, RATE_DOM, VOLATILITY, isCall, barrier); double volUp = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY + EPS_FD, isCall, barrier); double volDw = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY - EPS_FD, isCall, barrier); double timeUp = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME + EPS_FD, COST_OF_CARRY, RATE_DOM, VOLATILITY, isCall, barrier); double timeDw = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME - EPS_FD, COST_OF_CARRY, RATE_DOM, VOLATILITY, isCall, barrier); ValueDerivatives spotUp1 = BARRIER_PRICER.priceAdjoint( SPOT + EPS_FD, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, isCall, barrier); ValueDerivatives spotDw1 = BARRIER_PRICER.priceAdjoint(
double y1 = Math.log(h * h / spot / strike) / sigmaT + m1; double y2 = Math.log(h / spot) / sigmaT + m1; double xA = getA(spot, strike, df1, df2, x1, sigmaT, phi); double xB = getA(spot, strike, df1, df2, x2, sigmaT, phi); double xC = getC(spot, strike, df1, df2, y1, sigmaT, h, mu, phi, eta); double xD = getC(spot, strike, df1, df2, y2, sigmaT, h, mu, phi, eta); if (isKnockIn) { // KnockIn if (isDown) {
double[] aDerivFirst = new double[6]; double[][] aDerivSecond = new double[2][2]; double xA = getAAdjoint(spot, strike, df1, df2, x1, lognormalVolT, phi, aDerivFirst, aDerivSecond); double[] bDerivFirst = new double[6]; double[][] bDerivSecond = new double[2][2]; double xB = getAAdjoint(spot, strike, df1, df2, x2, lognormalVolT, phi, bDerivFirst, bDerivSecond); double[] cDerivFirst = new double[7]; double[][] cDerivSecond = new double[2][2]; double xC = getCAdjoint(spot, strike, df1, df2, y1, lognormalVolT, h, mu, phi, eta, cDerivFirst, cDerivSecond); double[] dDerivFirst = new double[7]; double[][] dDerivSecond = new double[2][2]; double xD = getCAdjoint(spot, strike, df1, df2, y2, lognormalVolT, h, mu, phi, eta, dDerivFirst, dDerivSecond); double xDBar = 0d; double xCBar = 0d;
double callUpIn = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, BARRIER_UP_IN); double callUpOut = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, BARRIER_UP_OUT); double callDownIn = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, BARRIER_DOWN_IN); double callDownOut = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, BARRIER_DOWN_OUT); assertRelative(callUpIn + callUpOut, callVanilla); double putUpIn = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, BARRIER_UP_IN); double putUpOut = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, BARRIER_UP_OUT); double putDownIn = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, BARRIER_DOWN_IN); double putDownOut = BARRIER_PRICER.price( SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, BARRIER_DOWN_OUT); assertRelative(putUpIn + putUpOut, putVanilla);
double expectedAsset = ASSET_REBATE_PRICER .priceAdjoint(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKI).getDerivative(3); double expectedCall = BARRIER_PRICER.priceAdjoint(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, true, BARRIER_UKI).getDerivative(4) + rebateRate * expectedCash; double expectedPut = BARRIER_PRICER.priceAdjoint(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, false, BARRIER_UKO).getDerivative(4) + rebateRate * expectedAsset; assertEquals(computedVegaCall, expectedCall, TOL);
/** * Upper barrier level is very high: knock-in is close to 0, knock-out is close to vanilla. */ public void largeBarrierTest() { SimpleConstantContinuousBarrier upIn = SimpleConstantContinuousBarrier.of(BarrierType.UP, KnockType.KNOCK_IN, 1.0e4); SimpleConstantContinuousBarrier upOut = SimpleConstantContinuousBarrier.of(BarrierType.UP, KnockType.KNOCK_OUT, 1.0e4); for (double strike : STRIKES) { // call double callVanilla = BlackFormulaRepository.price(FWD_FX, strike, EXPIRY_TIME, VOLATILITY, true) * DF_DOM; double callUpIn = BARRIER_PRICER.price(SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, upIn); double callUpOut = BARRIER_PRICER.price(SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, upOut); assertRelative(callUpIn, 0d); assertRelative(callUpOut, callVanilla); // put double putVanilla = BlackFormulaRepository.price(FWD_FX, strike, EXPIRY_TIME, VOLATILITY, false) * DF_DOM; double putUpIn = BARRIER_PRICER.price(SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, upIn); double putUpOut = BARRIER_PRICER.price(SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, upOut); assertRelative(putUpIn, 0d); assertRelative(putUpOut, putVanilla); } }
public void test_gamma_presentValueGamma() { double computedGammaCall = PRICER.gamma(CALL_UKI, RATE_PROVIDER, VOLS); double computedGammaPut = PRICER.gamma(PUT_UKO_BASE, RATE_PROVIDER, VOLS); CurrencyAmount computedPvGammaCall = PRICER.presentValueGamma(CALL_UKI, RATE_PROVIDER, VOLS); CurrencyAmount computedPvGammaPut = PRICER.presentValueGamma(PUT_UKO_BASE, RATE_PROVIDER, VOLS); double rateBase = RATE_PROVIDER.discountFactors(EUR).zeroRate(PAY_DATE); double rateCounter = RATE_PROVIDER.discountFactors(USD).zeroRate(PAY_DATE); double costOfCarry = rateCounter - rateBase; double forward = RATE_PROVIDER.fxForwardRates(CURRENCY_PAIR).rate(EUR, PAY_DATE); double volatility = VOLS.volatility(CURRENCY_PAIR, EXPIRY_DATETIME, STRIKE_RATE, forward); double timeToExpiry = VOLS.relativeTime(EXPIRY_DATETIME); double rebateRate = REBATE_AMOUNT / NOTIONAL; double expectedCash = CASH_REBATE_PRICER .priceAdjoint(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKO).getDerivative(5); double expectedAsset = ASSET_REBATE_PRICER .priceAdjoint(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKI).getDerivative(5); double expectedGammaCall = BARRIER_PRICER.priceAdjoint(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, true, BARRIER_UKI).getDerivative(6) + rebateRate * expectedCash; double expectedGammaPut = BARRIER_PRICER.priceAdjoint(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, false, BARRIER_UKO).getDerivative(6) + rebateRate * expectedAsset; assertEquals(computedGammaCall, expectedGammaCall, TOL); assertEquals(computedGammaPut, expectedGammaPut, TOL); assertEquals(computedPvGammaCall.getCurrency(), USD); assertEquals(computedPvGammaPut.getCurrency(), USD); assertEquals(computedPvGammaCall.getAmount(), expectedGammaCall * NOTIONAL, TOL); assertEquals(computedPvGammaPut.getAmount(), -expectedGammaPut * NOTIONAL, TOL); }
/** * Barrier event has occured already. */ public void illegalBarrierLevelTest() { assertThrowsIllegalArg(() -> BARRIER_PRICER.price(BARRIER_UP_IN.getBarrierLevel() + 0.1, STRIKE_MID, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, BARRIER_UP_IN)); assertThrowsIllegalArg(() -> BARRIER_PRICER.price(BARRIER_DOWN_OUT.getBarrierLevel() - 0.1, STRIKE_MID, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, BARRIER_DOWN_OUT)); assertThrowsIllegalArg(() -> BARRIER_PRICER.priceAdjoint(BARRIER_UP_IN.getBarrierLevel() + 0.1, STRIKE_MID, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, BARRIER_UP_IN)); assertThrowsIllegalArg(() -> BARRIER_PRICER.priceAdjoint(BARRIER_DOWN_OUT.getBarrierLevel() - 0.1, STRIKE_MID, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, BARRIER_DOWN_OUT)); }
/** * Lower barrier level is very small: knock-in is close to 0, knock-out is close to vanilla. */ public void smallBarrierTest() { SimpleConstantContinuousBarrier dwIn = SimpleConstantContinuousBarrier.of(BarrierType.DOWN, KnockType.KNOCK_IN, 0.1d); SimpleConstantContinuousBarrier dwOut = SimpleConstantContinuousBarrier.of(BarrierType.DOWN, KnockType.KNOCK_OUT, 0.1d); for (double strike : STRIKES) { // call double callVanilla = BlackFormulaRepository.price(FWD_FX, strike, EXPIRY_TIME, VOLATILITY, true) * DF_DOM; double callDwIn = BARRIER_PRICER.price(SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, dwIn); double callDwOut = BARRIER_PRICER.price(SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, true, dwOut); assertRelative(callDwIn, 0d); assertRelative(callDwOut, callVanilla); // put double putVanilla = BlackFormulaRepository.price(FWD_FX, strike, EXPIRY_TIME, VOLATILITY, false) * DF_DOM; double putDwIn = BARRIER_PRICER.price(SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, dwIn); double putDwOut = BARRIER_PRICER.price(SPOT, strike, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, false, dwOut); assertRelative(putDwIn, 0d); assertRelative(putDwOut, putVanilla); } }
public void test_delta_presentValueDelta() { double computedDeltaCall = PRICER.delta(CALL_UKI, RATE_PROVIDER, VOLS); double computedDeltaPut = PRICER.delta(PUT_UKO_BASE, RATE_PROVIDER, VOLS); CurrencyAmount computedPvDeltaCall = PRICER.presentValueDelta(CALL_UKI, RATE_PROVIDER, VOLS); CurrencyAmount computedPvDeltaPut = PRICER.presentValueDelta(PUT_UKO_BASE, RATE_PROVIDER, VOLS); double rateBase = RATE_PROVIDER.discountFactors(EUR).zeroRate(PAY_DATE); double rateCounter = RATE_PROVIDER.discountFactors(USD).zeroRate(PAY_DATE); double costOfCarry = rateCounter - rateBase; double forward = RATE_PROVIDER.fxForwardRates(CURRENCY_PAIR).rate(EUR, PAY_DATE); double volatility = VOLS.volatility(CURRENCY_PAIR, EXPIRY_DATETIME, STRIKE_RATE, forward); double timeToExpiry = VOLS.relativeTime(EXPIRY_DATETIME); double rebateRate = REBATE_AMOUNT / NOTIONAL; double expectedCash = CASH_REBATE_PRICER .priceAdjoint(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKO).getDerivative(0); double expectedAsset = ASSET_REBATE_PRICER .priceAdjoint(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKI).getDerivative(0); double expectedDeltaCall = BARRIER_PRICER.priceAdjoint(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, true, BARRIER_UKI).getDerivative(0) + rebateRate * expectedCash; double expectedDeltaPut = BARRIER_PRICER.priceAdjoint(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, false, BARRIER_UKO).getDerivative(0) + rebateRate * expectedAsset; assertEquals(computedDeltaCall, expectedDeltaCall, TOL); assertEquals(computedDeltaPut, expectedDeltaPut, TOL); assertEquals(computedPvDeltaCall.getCurrency(), USD); assertEquals(computedPvDeltaPut.getCurrency(), USD); assertEquals(computedPvDeltaCall.getAmount(), expectedDeltaCall * NOTIONAL, TOL); assertEquals(computedPvDeltaPut.getAmount(), -expectedDeltaPut * NOTIONAL, TOL); }
private void testSmallValues(double strike, boolean isCall, SimpleConstantContinuousBarrier barrier) { // small parameters double volUp = 2.0e-3; double volDw = 1.0e-3; double time = 1.0e-2; // price double optUp = BARRIER_PRICER.price(SPOT, strike, time, COST_OF_CARRY, RATE_DOM, volUp, isCall, barrier); double optDw = BARRIER_PRICER.price(SPOT, strike, time, COST_OF_CARRY, RATE_DOM, volDw, isCall, barrier); assertRelative(optUp, optDw); // price adjoint ValueDerivatives optUpAdj = BARRIER_PRICER.priceAdjoint(SPOT, strike, time, COST_OF_CARRY, RATE_DOM, volUp, isCall, barrier); ValueDerivatives optDwAdj = BARRIER_PRICER.priceAdjoint(SPOT, strike, time, COST_OF_CARRY, RATE_DOM, volDw, isCall, barrier); assertRelative(optUpAdj.getValue(), optDwAdj.getValue()); for (int i = 0; i < 6; ++i) { assertRelative(optUpAdj.getDerivative(i), optDwAdj.getDerivative(i)); } }
public void test_trinomialTree_down() { int nSteps = 133; LatticeSpecification lattice = new CoxRossRubinsteinLatticeSpecification(); DoubleArray rebate = DoubleArray.of(nSteps + 1, i -> REBATE_AMOUNT); double barrierLevel = 76d; double tol = 1.0e-2; for (boolean isCall : new boolean[] {true, false }) { for (double strike : STRIKES) { for (double interest : INTERESTS) { for (double vol : VOLS) { for (double dividend : DIVIDENDS) { OptionFunction function = ConstantContinuousSingleBarrierKnockoutFunction.of( strike, TIME, PutCall.ofPut(!isCall), nSteps, BarrierType.DOWN, barrierLevel, rebate); SimpleConstantContinuousBarrier barrier = SimpleConstantContinuousBarrier.of(BarrierType.DOWN, KnockType.KNOCK_OUT, barrierLevel); double exact = REBATE_AMOUNT * REBATE_PRICER.price(SPOT, TIME, interest - dividend, interest, vol, barrier.inverseKnockType()) + BARRIER_PRICER.price(SPOT, strike, TIME, interest - dividend, interest, vol, isCall, barrier); double computed = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT, vol, interest, dividend); assertEquals(computed, exact, Math.max(exact, 1d) * tol); } } } } } }
public void test_theta_presentValueTheta() { double computedThetaCall = PRICER.theta(CALL_UKI, RATE_PROVIDER, VOLS); double computedThetaPut = PRICER.theta(PUT_UKO_BASE, RATE_PROVIDER, VOLS); CurrencyAmount computedPvThetaCall = PRICER.presentValueTheta(CALL_UKI, RATE_PROVIDER, VOLS); CurrencyAmount computedPvThetaPut = PRICER.presentValueTheta(PUT_UKO_BASE, RATE_PROVIDER, VOLS); double rateBase = RATE_PROVIDER.discountFactors(EUR).zeroRate(PAY_DATE); double rateCounter = RATE_PROVIDER.discountFactors(USD).zeroRate(PAY_DATE); double costOfCarry = rateCounter - rateBase; double forward = RATE_PROVIDER.fxForwardRates(CURRENCY_PAIR).rate(EUR, PAY_DATE); double volatility = VOLS.volatility(CURRENCY_PAIR, EXPIRY_DATETIME, STRIKE_RATE, forward); double timeToExpiry = VOLS.relativeTime(EXPIRY_DATETIME); double rebateRate = REBATE_AMOUNT / NOTIONAL; double expectedCash = CASH_REBATE_PRICER .priceAdjoint(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKO).getDerivative(4); double expectedAsset = ASSET_REBATE_PRICER .priceAdjoint(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKI).getDerivative(4); double expectedThetaCall = BARRIER_PRICER.priceAdjoint(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, true, BARRIER_UKI).getDerivative(5) + rebateRate * expectedCash; double expectedThetaPut = BARRIER_PRICER.priceAdjoint(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, false, BARRIER_UKO).getDerivative(5) + rebateRate * expectedAsset; expectedThetaCall *= -1d; expectedThetaPut *= -1d; assertEquals(computedThetaCall, expectedThetaCall, TOL); assertEquals(computedThetaPut, expectedThetaPut, TOL); assertEquals(computedPvThetaCall.getCurrency(), USD); assertEquals(computedPvThetaPut.getCurrency(), USD); assertEquals(computedPvThetaCall.getAmount(), expectedThetaCall * NOTIONAL, TOL); assertEquals(computedPvThetaPut.getAmount(), -expectedThetaPut * NOTIONAL, TOL); }
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); assertRelative(priceDIExp[j], priceDIAdjointNew.getValue() + priceDIAdjointRb.getValue() * REBATE); 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 = assertRelative(priceDOExp[j], priceDOAdjointNew.getValue() + priceDOAdjointRb.getValue() * REBATE); 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); double priceUONew = BARRIER_PRICER.price(SPOT, options[j].getStrike(), EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, options[j].isCall(), BARRIER_UP_OUT); ValueDerivatives priceUOAdjointNew = BARRIER_PRICER.priceAdjoint(SPOT, options[j].getStrike(), EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, options[j].isCall(), BARRIER_UP_OUT); double priceUORb = rebate.price(SPOT, EXPIRY_TIME, COST_OF_CARRY, RATE_DOM, VOLATILITY, BARRIER_UP_IN);
public void test_price_presentValue() { double computedPriceCall = PRICER.price(CALL_UKI, RATE_PROVIDER, VOLS); double computedPricePut = PRICER.price(PUT_UKO_BASE, RATE_PROVIDER, VOLS); CurrencyAmount computedPvCall = PRICER.presentValue(CALL_UKI, RATE_PROVIDER, VOLS); CurrencyAmount computedPvPut = PRICER.presentValue(PUT_UKO_BASE, RATE_PROVIDER, VOLS); double rateBase = RATE_PROVIDER.discountFactors(EUR).zeroRate(PAY_DATE); double rateCounter = RATE_PROVIDER.discountFactors(USD).zeroRate(PAY_DATE); double costOfCarry = rateCounter - rateBase; double forward = RATE_PROVIDER.fxForwardRates(CURRENCY_PAIR).rate(EUR, PAY_DATE); double volatility = VOLS.volatility(CURRENCY_PAIR, EXPIRY_DATETIME, STRIKE_RATE, forward); double timeToExpiry = VOLS.relativeTime(EXPIRY_DATETIME); double rebateRate = REBATE_AMOUNT / NOTIONAL; double expectedCash = CASH_REBATE_PRICER.price(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKO); double expectedAsset = ASSET_REBATE_PRICER.price(SPOT, timeToExpiry, costOfCarry, rateCounter, volatility, BARRIER_UKI); double expectedPriceCall = BARRIER_PRICER.price(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, true, BARRIER_UKI) + rebateRate * expectedCash; double expectedPricePut = BARRIER_PRICER.price(SPOT, STRIKE_RATE, timeToExpiry, costOfCarry, rateCounter, volatility, false, BARRIER_UKO) + rebateRate * expectedAsset; assertEquals(computedPriceCall, expectedPriceCall, TOL); assertEquals(computedPricePut, expectedPricePut, TOL); assertEquals(computedPvCall.getCurrency(), USD); assertEquals(computedPvPut.getCurrency(), USD); assertEquals(computedPvCall.getAmount(), expectedPriceCall * NOTIONAL, TOL); assertEquals(computedPvPut.getAmount(), -expectedPricePut * NOTIONAL, TOL); }
double volatility = volatilities.volatility(currencyPair, underlyingOption.getExpiry(), strike, forward); double timeToExpiry = volatilities.relativeTime(underlyingOption.getExpiry()); ValueDerivatives valueDerivatives = BARRIER_PRICER.priceAdjoint( todayFx, strike, timeToExpiry, costOfCarry, rateCounter, volatility, underlyingOption.getPutCall().isCall(), barrier); if (!option.getRebate().isPresent()) {
public void test_trinomialTree_up() { int nSteps = 133; LatticeSpecification lattice = new CoxRossRubinsteinLatticeSpecification(); DoubleArray rebate = DoubleArray.of(nSteps + 1, i -> REBATE_AMOUNT); double barrierLevel = 135d; double tol = 1.0e-2; for (boolean isCall : new boolean[] {true, false }) { for (double strike : STRIKES) { for (double interest : INTERESTS) { for (double vol : VOLS) { for (double dividend : DIVIDENDS) { OptionFunction function = ConstantContinuousSingleBarrierKnockoutFunction.of( strike, TIME, PutCall.ofPut(!isCall), nSteps, BarrierType.UP, barrierLevel, rebate); SimpleConstantContinuousBarrier barrier = SimpleConstantContinuousBarrier.of(BarrierType.UP, KnockType.KNOCK_OUT, barrierLevel); double exact = REBATE_AMOUNT * REBATE_PRICER.price(SPOT, TIME, interest - dividend, interest, vol, barrier.inverseKnockType()) +BARRIER_PRICER.price(SPOT, strike, TIME, interest - dividend, interest, vol, isCall, barrier); double computed = TRINOMIAL_TREE.optionPrice(function, lattice, SPOT, vol, interest, dividend); assertEquals(computed, exact, Math.max(exact, 1d) * tol); } } } } } }
double volatility = volatilities.volatility(currencyPair, underlyingOption.getExpiry(), strike, forward); double timeToExpiry = volatilities.relativeTime(underlyingOption.getExpiry()); double price = BARRIER_PRICER.price( todayFx, strike, timeToExpiry, costOfCarry, rateCounter, volatility, underlyingOption.getPutCall().isCall(), barrier); if (option.getRebate().isPresent()) {