/** * Calculates the vega of the FX barrier option product. * <p> * The delta is the first derivative of {@link #price} with respect to Black volatility. * * @param option the option product * @param ratesProvider the rates provider * @param volatilities the Black volatility provider * @return the vega of the product */ public double vega( ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { ValueDerivatives priceDerivatives = priceDerivatives(option, ratesProvider, volatilities); return priceDerivatives.getDerivative(4); }
public void test_of() { ValueDerivatives test = ValueDerivatives.of(VALUE, DERIVATIVES); assertEquals(test.getValue(), VALUE, 0); assertEquals(test.getDerivatives(), DERIVATIVES); assertEquals(test.getDerivative(0), DERIVATIVES.get(0)); assertEquals(test.getDerivative(1), DERIVATIVES.get(1)); assertEquals(test.getDerivative(2), DERIVATIVES.get(2)); }
/** * Calculates the gamma of the FX barrier option product. * <p> * The delta is the second derivative of {@link #price} with respect to spot. * * @param option the option product * @param ratesProvider the rates provider * @param volatilities the Black volatility provider * @return the gamma of the product */ public double gamma( ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { ValueDerivatives priceDerivatives = priceDerivatives(option, ratesProvider, volatilities); return priceDerivatives.getDerivative(6); }
public void implied_volatility_from_normal_adjoint() { double shiftFd = 1.0E-6; for (int i = 0; i < N; i++) { double ivBlackComputed = BlackFormulaRepository .impliedVolatilityFromNormalApproximated(FORWARD, STRIKES[i], TIME_TO_EXPIRY, SIGMA_NORMAL[i]); ValueDerivatives ivBlackAdj = BlackFormulaRepository .impliedVolatilityFromNormalApproximatedAdjoint(FORWARD, STRIKES[i], TIME_TO_EXPIRY, SIGMA_NORMAL[i]); assertEquals(ivBlackComputed, ivBlackAdj.getValue(), TOLERANCE_1); assertEquals(1, ivBlackAdj.getDerivatives().size()); double ivBlackComputedP = BlackFormulaRepository .impliedVolatilityFromNormalApproximated(FORWARD, STRIKES[i], TIME_TO_EXPIRY, SIGMA_NORMAL[i] + shiftFd); double ivBlackComputedM = BlackFormulaRepository .impliedVolatilityFromNormalApproximated(FORWARD, STRIKES[i], TIME_TO_EXPIRY, SIGMA_NORMAL[i] - shiftFd); double derivativeApproximated = (ivBlackComputedP - ivBlackComputedM) / (2 * shiftFd); assertEquals(derivativeApproximated, ivBlackAdj.getDerivative(0), TOLERANCE_VOL_DELTA); } }
/** * Calculates the theta of the FX barrier option product. * <p> * The theta is the negative of the first derivative of {@link #price} with respect to time parameter. * * @param option the option product * @param ratesProvider the rates provider * @param volatilities the Black volatility provider * @return the theta of the product */ public double theta( ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { ValueDerivatives priceDerivatives = priceDerivatives(option, ratesProvider, volatilities); return -priceDerivatives.getDerivative(5); }
public void implied_volatility_adjoint() { double shiftFd = 1.0E-6; for (int i = 0; i < N; i++) { double impliedVol = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i]); ValueDerivatives impliedVolAdj = NormalFormulaRepository.impliedVolatilityFromBlackApproximatedAdjoint(FORWARD, STRIKES[i], T, SIGMA_BLACK[i]); assertEquals(impliedVolAdj.getValue(), impliedVol, TOLERANCE_VOL); double impliedVolP = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i] + shiftFd); double impliedVolM = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i] - shiftFd); double derivativeApproximated = (impliedVolP - impliedVolM) / (2 * shiftFd); assertEquals(impliedVolAdj.getDerivatives().size(), 1); assertEquals(impliedVolAdj.getDerivative(0), derivativeApproximated, TOLERANCE_VOL); } }
@Override protected double doFirstDerivative(double xValue) { ArgChecker.isTrue(Math.abs(xValue) > SMALL, "magnitude of xValue must not be small"); ValueDerivatives resValue = FUNCTION.evaluateAndDifferentiate(poly, xValue); return -resValue.getValue() / (xValue * xValue) + resValue.getDerivative(0) / xValue; }
@Override protected double doFirstDerivative(double xValue) { ArgChecker.isTrue(Math.abs(xValue) > SMALL, "magnitude of xValue must not be small"); ValueDerivatives resValue = FUNCTION.evaluateAndDifferentiate(poly, xValue); return -resValue.getValue() / (xValue * xValue) + resValue.getDerivative(0) / xValue; }
@Override protected double doFirstDerivative(double xValue) { ArgChecker.isTrue(Math.abs(xValue) > SMALL, "magnitude of xValue must not be small"); ValueDerivatives resValue = FUNCTION.evaluateAndDifferentiate(poly, xValue); return -resValue.getValue() / (xValue * xValue) + resValue.getDerivative(0) / xValue; }
public void annuity_cash_3() { double shift = 1.0E-7; for (int looprate = 0; looprate < RATES.length; looprate++) { ValueDerivatives annuityExpected = PRICER_LEG.annuityCash2(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate]); ValueDerivatives annuityComputed = PRICER_LEG.annuityCash3(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate]); ValueDerivatives annuityP = PRICER_LEG.annuityCash2(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate] + shift); ValueDerivatives annuityM = PRICER_LEG.annuityCash2(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate] - shift); double derivative3Expected = (annuityP.getDerivative(1) - annuityM.getDerivative(1)) / (2.0d * shift); assertEquals(annuityComputed.getValue(), annuityExpected.getValue(), TOLERANCE_ANNUITY_1); assertEquals(annuityComputed.getDerivative(0), annuityExpected.getDerivative(0), TOLERANCE_ANNUITY_1); assertEquals(annuityComputed.getDerivative(1), annuityExpected.getDerivative(1), TOLERANCE_ANNUITY_2); assertEquals(annuityComputed.getDerivative(2), derivative3Expected, TOLERANCE_ANNUITY_3, "rate: " + looprate); } }
public void annuity_cash_2() { double shift = 1.0E-7; for (int looprate = 0; looprate < RATES.length; looprate++) { ValueDerivatives annuityExpected = PRICER_LEG.annuityCash1(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate]); ValueDerivatives annuityComputed = PRICER_LEG.annuityCash2(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate]); ValueDerivatives annuityP = PRICER_LEG.annuityCash1(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate] + shift); ValueDerivatives annuityM = PRICER_LEG.annuityCash1(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate] - shift); double derivative2Expected = (annuityP.getDerivative(0) - annuityM.getDerivative(0)) / (2.0d * shift); assertEquals(annuityComputed.getValue(), annuityExpected.getValue(), TOLERANCE_ANNUITY_1); assertEquals(annuityComputed.getDerivative(0), annuityExpected.getDerivative(0), TOLERANCE_ANNUITY_1); assertEquals(annuityComputed.getDerivative(1), derivative2Expected, TOLERANCE_ANNUITY_2); } }
/** *Test the alpha = 0 edge case. Implied vol is zero for alpha = 0, and except in the ATM case, the alpha sensitivity is infinite. We *choose to (arbitrarily) return 1e7 in this case. */ @Test public void testVolatilityAdjointAlpha0() { double eps = 1e-5; double tol = 1e-6; SabrFormulaData data = DATA.withAlpha(0.0); testVolatilityAdjoint(F, CALL_ATM, data, eps, tol); double volatility = FUNCTION.volatility(F, STRIKE_ITM, T, data); ValueDerivatives volatilityAdjoint = FUNCTION.volatilityAdjoint(F, STRIKE_ITM, T, data); assertEquals(volatility, volatilityAdjoint.getValue(), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(0), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(1), tol); assertEquals(1e7, volatilityAdjoint.getDerivative(2), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(3), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(4), tol); assertEquals(0.0, volatilityAdjoint.getDerivative(5), tol); }
/** * Calculates the delta of the FX barrier option product. * <p> * The delta is the first derivative of {@link #price} with respect to spot. * * @param option the option product * @param ratesProvider the rates provider * @param volatilities the Black volatility provider * @return the delta of the product */ public double delta( ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { if (volatilities.relativeTime(option.getUnderlyingOption().getExpiry()) < 0d) { return 0d; } ValueDerivatives priceDerivatives = priceDerivatives(option, ratesProvider, volatilities); return priceDerivatives.getDerivative(0); }
public void test_annuityCashDerivative_onePeriod() { double yield = 0.01; DiscountingSwapLegPricer test = DiscountingSwapLegPricer.DEFAULT; double computed = test.annuityCashDerivative(FIXED_SWAP_LEG_REC_USD, yield).getDerivative(0); double expected = 0.5 * (test.annuityCash(FIXED_SWAP_LEG_REC_USD, yield + FD_SHIFT) - test.annuityCash(FIXED_SWAP_LEG_REC_USD, yield - FD_SHIFT)) / FD_SHIFT; assertEquals(computed, expected, SwapDummyData.NOTIONAL * FD_SHIFT); }
public void annuity_cash_1() { double shift = 1.0E-7; for (int looprate = 0; looprate < RATES.length; looprate++) { double annuityExpected = PRICER_LEG.annuityCash(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate]); ValueDerivatives annuityComputed = PRICER_LEG.annuityCash1(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate]); assertEquals(annuityComputed.getValue(), annuityExpected, TOLERANCE_ANNUITY); double annuityP = PRICER_LEG.annuityCash(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate] + shift); double annuityM = PRICER_LEG.annuityCash(NB_PERIODS_PER_YEAR, NB_PERIODS, RATES[looprate] - shift); double derivative1Expected = (annuityP - annuityM) / (2.0d * shift); assertEquals(annuityComputed.getDerivative(0), derivative1Expected, TOLERANCE_ANNUITY_1, "Rate: " + looprate); } }
/** * Tests the strikes computations. */ public void strike() { double[] strike = SMILE.strike(FORWARD).toArrayUnsafe(); DoubleArray volatility = SMILE.getVolatility(); int nbDelta = DELTA.size(); for (int loopdelta = 0; loopdelta < nbDelta; loopdelta++) { ValueDerivatives dPut = BlackFormulaRepository.priceAdjoint( FORWARD, strike[loopdelta], TIME_TO_EXPIRY, volatility.get(loopdelta), false); assertEquals(-DELTA.get(loopdelta), dPut.getDerivative(0), 1e-8, "Strike: Put " + loopdelta); ValueDerivatives dCall = BlackFormulaRepository.priceAdjoint( FORWARD, strike[2 * nbDelta - loopdelta], TIME_TO_EXPIRY, volatility.get(2 * nbDelta - loopdelta), true); assertEquals(DELTA.get(loopdelta), dCall.getDerivative(0), 1e-8, "Strike: Call " + loopdelta); } ValueDerivatives dPut = BlackFormulaRepository.priceAdjoint( FORWARD, strike[nbDelta], TIME_TO_EXPIRY, volatility.get(nbDelta), false); ValueDerivatives dCall = BlackFormulaRepository.priceAdjoint( FORWARD, strike[nbDelta], TIME_TO_EXPIRY, volatility.get(nbDelta), true); assertEquals(0.0, dCall.getDerivative(0) + dPut.getDerivative(0), 1e-8, "Strike: ATM"); }
public void test_annuityCashDerivative_twoPeriods() { ResolvedSwapLeg leg = ResolvedSwapLeg.builder() .type(FIXED) .payReceive(PAY) .paymentPeriods(FIXED_RATE_PAYMENT_PERIOD_PAY_USD, FIXED_RATE_PAYMENT_PERIOD_PAY_USD_2) .build(); double yield = 0.01; DiscountingSwapLegPricer test = DiscountingSwapLegPricer.DEFAULT; double computed = test.annuityCashDerivative(leg, yield).getDerivative(0); double expected = 0.5 / FD_SHIFT * (test.annuityCash(leg, yield + FD_SHIFT) - test.annuityCash(leg, yield - FD_SHIFT)); assertEquals(computed, expected, SwapDummyData.NOTIONAL * FD_SHIFT); }
/** * smoothly connected to limiting cases. */ public void smallsigmaTTest() { for (SimpleConstantContinuousBarrier barrier : BARRIERS) { double volUp = 2.0e-3; double volDw = 1.0e-3; double time = 1.0e-2; double optUp = PRICER.price(SPOT, time, COST_OF_CARRY, RATE_DOM, volUp, barrier); double optDw = PRICER.price(SPOT, time, COST_OF_CARRY, RATE_DOM, volDw, barrier); assertRelative(optUp, optDw); ValueDerivatives optUpAdj = PRICER.priceAdjoint(SPOT, time, COST_OF_CARRY, RATE_DOM, volUp, barrier); ValueDerivatives optDwAdj = PRICER.priceAdjoint(SPOT, time, COST_OF_CARRY, RATE_DOM, volDw, barrier); assertRelative(optUpAdj.getValue(), optDwAdj.getValue()); for (int i = 0; i < 6; ++i) { assertRelative(optUpAdj.getDerivative(i), optDwAdj.getDerivative(i)); } } }
/** * smoothly connected to limiting cases. */ public void smallsigmaTTest() { for (SimpleConstantContinuousBarrier barrier : BARRIERS) { double volUp = 2.0e-3; double volDw = 1.0e-3; double time = 1.0e-2; double optUp = PRICER.price(SPOT, time, COST_OF_CARRY, RATE_DOM, volUp, barrier); double optDw = PRICER.price(SPOT, time, COST_OF_CARRY, RATE_DOM, volDw, barrier); assertRelative(optUp, optDw, 1.0e-3); ValueDerivatives optUpAdj = PRICER.priceAdjoint(SPOT, time, COST_OF_CARRY, RATE_DOM, volUp, barrier); ValueDerivatives optDwAdj = PRICER.priceAdjoint(SPOT, time, COST_OF_CARRY, RATE_DOM, volDw, barrier); assertRelative(optUpAdj.getValue(), optDwAdj.getValue(), 1.0e-3); for (int i = 0; i < 6; ++i) { assertRelative(optUpAdj.getDerivative(i), optDwAdj.getDerivative(i), 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)); } }