private double[] toArray(ValueDerivatives valueDerivatives) { double[] derivatives = valueDerivatives.getDerivatives().toArray(); double[] res = new double[derivatives.length + 1]; res[0] = valueDerivatives.getValue(); System.arraycopy(derivatives, 0, res, 1, derivatives.length); return res; }
@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; }
ValueDerivatives volatilityA = sabrFunction.volatilityAdjoint(forward, strike, timeToExpiry, sabrData); ValueDerivatives pA = BlackFormulaRepository.priceAdjoint( forward, strike, timeToExpiry, volatilityA.getValue(), putCall == PutCall.CALL); price = pA.getValue(); for (int loopparam = 0; loopparam < 4; loopparam++) { priceDerivativeSabr[loopparam] = pA.getDerivative(3) * volatilityA.getDerivative(loopparam + 2); return ValueDerivatives.of(price, DoubleArray.ofUnsafe(priceDerivativeSabr));
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)); }
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); } }
@Override public Double apply(Double x) { double[] kD = kpkpp(x); // Implementation note: kD[0] contains the first derivative of k; kD[1] the second derivative of k. double xShifted = Math.max(x + shift, 0d); // handle tiny but negative number DoubleArray priceDerivativeSabr = getSabrExtrapolation().priceAdjointSabr(xShifted, putCall).getDerivatives(); return priceDerivativeSabr.get(i) * (factor * (kD[1] * (x - strike) + 2d * kD[0])); } };
/** * Computes the derivative of the conventional cash annuity with respect to the yield from a swap leg. * <p> * The computation is relevant only for standard swaps with constant notional and regular payments. * The swap leg must be a fixed leg. However, this is not checked internally. * * @param fixedLeg the fixed leg of the swap * @param yield the yield * @return the cash annuity */ public ValueDerivatives annuityCashDerivative(ResolvedSwapLeg fixedLeg, double yield) { int nbFixedPeriod = fixedLeg.getPaymentPeriods().size(); SwapPaymentPeriod paymentPeriod = fixedLeg.getPaymentPeriods().get(0); ArgChecker.isTrue(paymentPeriod instanceof RatePaymentPeriod, "payment period should be RatePaymentPeriod"); RatePaymentPeriod ratePaymentPeriod = (RatePaymentPeriod) paymentPeriod; int nbFixedPaymentYear = (int) Math.round(1d / ratePaymentPeriod.getDayCount().yearFraction(ratePaymentPeriod.getStartDate(), ratePaymentPeriod.getEndDate())); double notional = Math.abs(ratePaymentPeriod.getNotional()); ValueDerivatives annuityUnit = annuityCash1(nbFixedPaymentYear, nbFixedPeriod, yield); return ValueDerivatives.of(annuityUnit.getValue() * notional, annuityUnit.getDerivatives().multipliedBy(notional)); }
/** * 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); }
/** * Computes the log-normal (Black) implied volatility of an out-the-money European option starting * from an initial guess and the derivative of the volatility w.r.t. the price. * * @param otmPrice The forward price, which is the market price divided by the numeraire, * for example the zero bond p(0,T) for the T-forward measure * This MUST be an OTM price, i.e. a call price for strike >= forward and a put price otherwise. * * @param forward the forward value of the underlying * @param strike the strike * @param timeToExpiry the time to expiry * @param volGuess a guess of the implied volatility * @return log-normal (Black) implied volatility and derivative with respect to the price */ public static ValueDerivatives impliedVolatilityAdjoint( double otmPrice, double forward, double strike, double timeToExpiry, double volGuess) { double impliedVolatility = impliedVolatility(otmPrice, forward, strike, timeToExpiry, volGuess); boolean isCall = strike >= forward; ValueDerivatives price = priceAdjoint(forward, strike, timeToExpiry, impliedVolatility, isCall); double dpricedvol = price.getDerivative(3); double dvoldprice = 1.0d / dpricedvol; return ValueDerivatives.of(impliedVolatility, DoubleArray.of(dvoldprice)); }
@Override public double zValue(double x, double y) { return deformationFunction.apply(DoublesPair.of(x, y)).getValue(); }
/** * Obtains an instance from a value and array of derivatives. * * @param value the value * @param derivatives the derivatives of the value * @return the object */ public static ValueDerivatives of(double value, DoubleArray derivatives) { return new ValueDerivatives(value, derivatives); }
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); } }
double derivative2 = -2 * derivative1 / yield; derivative2 -= tau * tau * nbPeriods * (nbPeriods + 1) * dfEnd / ((1d + yieldPerPeriod) * (1d + yieldPerPeriod) * yield); return ValueDerivatives.of(annuity, DoubleArray.of(derivative1, derivative2)); derivative1 *= tau * tau; derivative2 *= tau * tau * tau; return ValueDerivatives.of(annuity, DoubleArray.of(derivative1, derivative2));
@Override public UnitParameterSensitivity zValueParameterSensitivity(double x, double y) { return getMetadata().getParameterMetadata().isPresent() ? UnitParameterSensitivity.of( getMetadata().getSurfaceName(), getMetadata().getParameterMetadata().get(), deformationFunction.apply(DoublesPair.of(x, y)).getDerivatives()) : UnitParameterSensitivity.of( getMetadata().getSurfaceName(), deformationFunction.apply(DoublesPair.of(x, y)).getDerivatives()); }
/** * 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); }
double impliedVolatilityBlack = ROOT_FINDER.getRoot(func, guess); double derivativeInverse = NormalFormulaRepository .impliedVolatilityFromBlackApproximatedAdjoint(forward, strike, timeToExpiry, impliedVolatilityBlack).getDerivative(0); double derivative = 1.0 / derivativeInverse; return ValueDerivatives.of(impliedVolatilityBlack, DoubleArray.of(derivative));
/** * Calculates the price of the FX barrier option product. * <p> * The price of the product is the value on the valuation date for one unit of the base currency * and is expressed in the counter currency. The price does not take into account the long/short flag. * See {@linkplain #presentValue(ResolvedFxSingleBarrierOption, RatesProvider, BlackFxOptionVolatilities, RecombiningTrinomialTreeData) presnetValue} * for scaling and currency. * <p> * This assumes the tree is already calibrated and the tree data is stored as {@code RecombiningTrinomialTreeData}. * The tree data should be consistent with the pricer and other inputs, see {@link #validateData}. * * @param option the option product * @param ratesProvider the rates provider * @param volatilities the Black volatility provider * @param treeData the trinomial tree data * @return the price of the product */ public double price( ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities, RecombiningTrinomialTreeData treeData) { return priceDerivatives(option, ratesProvider, volatilities, treeData).getValue(); }
@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; }