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));
(1.0d / 24.0d + s2t / 2835.0d) * factor2Bar; blackVolatilityBar += 2.0d * blackVolatility * timeToExpiry * s2tBar; return ValueDerivatives.of(normalVol, DoubleArray.of(blackVolatilityBar)); double s2tBar = -factor2 * factor2 * ((1.0d - lnFK * lnFK / 120.0d) / 24.0d + s2t / 2835.0d) * factor2Bar; blackVolatilityBar += 2.0d * blackVolatility * timeToExpiry * s2tBar; return ValueDerivatives.of(normalVol, DoubleArray.of(blackVolatilityBar));
public void test_serialization() { ValueDerivatives test = ValueDerivatives.of(VALUE, DERIVATIVES); assertSerialization(test); }
/** * 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)); }
/** * 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)); }
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)); }
@Override public ValueDerivatives apply(DoublesPair x) { return ValueDerivatives.of(surface1.zValue(x), surface1.zValueParameterSensitivity(x).getSensitivity()); } });
@Override public ValueDerivatives apply(DoublesPair x) { double price = BlackFormulaRepository.price(spot, x.getSecond(), x.getFirst(), constantVol, true); return ValueDerivatives.of(price, DoubleArray.EMPTY); } };
/** * Calculates volatility and the adjoint (volatility sensitivity to forward, strike and model parameters). * <p> * By default the derivatives are computed by central finite difference approximation. * This should be overridden in each subclass. * * @param forward the forward value of the underlying * @param strike the strike value of the option * @param timeToExpiry the time to expiry of the option * @param data the model data * @return the volatility and associated derivatives */ public ValueDerivatives volatilityAdjoint(double forward, double strike, double timeToExpiry, T data) { ArgChecker.isTrue(forward >= 0.0, "forward must be greater than zero"); double[] res = new double[2 + data.getNumberOfParameters()]; // fwd, strike, the model parameters double volatility = volatility(forward, strike, timeToExpiry, data); res[0] = forwardBar(forward, strike, timeToExpiry, data); res[1] = strikeBar(forward, strike, timeToExpiry, data); Function<T, Double> func = getVolatilityFunction(forward, strike, timeToExpiry); double[] modelAdjoint = paramBar(func, data); System.arraycopy(modelAdjoint, 0, res, 2, data.getNumberOfParameters()); return ValueDerivatives.of(volatility, DoubleArray.ofUnsafe(res)); }
.plus(priceSensi.multipliedBy(q * factor)) .plus(divK2Sensi.multipliedBy(-0.5 * localVol / divK2)); return ValueDerivatives.of(localVol, localVolSensi);
.impliedVolatilityFromBlackApproximatedAdjoint(forward, strike, timeToExpiry, impliedVolatilityBlack).getDerivative(0); double derivative = 1.0 / derivativeInverse; return ValueDerivatives.of(impliedVolatilityBlack, DoubleArray.of(derivative));
numerator += discountedCashFlowIbor.get(loopcf) * exp; return ValueDerivatives.of(-numerator / denominator, DoubleArray.ofUnsafe(swapRateDdcfi1));
swapRateDdcff1[loopcf] = ratio * expD[loopcf]; return ValueDerivatives.of(-numerator / denominator, DoubleArray.ofUnsafe(swapRateDdcff1));
swapRateDaf1[loopcf] = ratio * expD[loopcf] * (-x - alphaFixed.get(loopcf)); return ValueDerivatives.of(-numerator / denominator, DoubleArray.ofUnsafe(swapRateDaf1));
numerator += discountedCashFlowIbor.get(loopcf) * exp; return ValueDerivatives.of(-numerator / denominator, DoubleArray.ofUnsafe(swapRateDai1));
return ValueDerivatives.of(price, DoubleArray.ofUnsafe(priceDerivativeSabr));
@Override public ValueDerivatives apply(DoublesPair x) { double value = 1.5 * SURFACE_ORG.zValue(x) * x.getFirst() * x.getSecond(); DoubleArray derivatives = SURFACE_ORG.zValueParameterSensitivity(x).multipliedBy(1.5 * x.getFirst() * x.getSecond()).getSensitivity(); return ValueDerivatives.of(value, derivatives); } };
/** * Compute option price and delta under the specified trinomial tree gird. * <p> * The delta is the first derivative of the price with respect to spot, and approximated by the data embedded in * the trinomial tree. * * @param function the option * @param data the trinomial tree data * @return the option price and spot delta */ public ValueDerivatives optionPriceAdjoint( OptionFunction function, RecombiningTrinomialTreeData data) { int nSteps = data.getNumberOfSteps(); ArgChecker.isTrue(nSteps == function.getNumberOfSteps(), "mismatch in number of steps"); DoubleArray values = function.getPayoffAtExpiryTrinomial(data.getStateValueAtLayer(nSteps)); double delta = 0d; for (int i = nSteps - 1; i > -1; --i) { values = function.getNextOptionValues( data.getDiscountFactorAtLayer(i), data.getProbabilityAtLayer(i), data.getStateValueAtLayer(i), values, i); if (i == 1) { DoubleArray stateValue = data.getStateValueAtLayer(1); double d1 = (values.get(2) - values.get(1)) / (stateValue.get(2) - stateValue.get(1)); double d2 = (values.get(1) - values.get(0)) / (stateValue.get(1) - stateValue.get(0)); delta = 0.5 * (d1 + d2); } } return ValueDerivatives.of(values.get(0), DoubleArray.of(delta)); }