/** * Computes the option security price curve sensitivity. The future price is computed without * convexity adjustment. It is supposed that for a given strike the volatility does not change * with the curves (sticky strike). * * @param security The future option security. * @param normalData The normal volatility and multi-curves provider. * @return The security price curve sensitivity. */ @Override public MulticurveSensitivity priceCurveSensitivity( final InterestRateFutureOptionMarginSecurity security, final NormalSTIRFuturesSmileProviderInterface normalData) { ArgumentChecker.notNull(security, "Option security"); ArgumentChecker.notNull(normalData, "Normal data"); // Forward sweep final double priceFuture = METHOD_FUTURE.price(security.getUnderlyingFuture(), normalData.getMulticurveProvider()); final EuropeanVanillaOption option = new EuropeanVanillaOption( security.getStrike(), security.getExpirationTime(), security.isCall()); final double delay = security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime(); final double volatility = normalData.getVolatility(security.getExpirationTime(), security.getStrike(), delay); final NormalFunctionData normalPoint = new NormalFunctionData(priceFuture, 1.0, volatility); // Backward sweep final double[] priceAdjoint = new double[3]; NORMAL_FUNCTION.getPriceAdjoint(option, normalPoint, priceAdjoint); final double priceBar = 1.0; final double priceFutureBar = priceAdjoint[0] * priceBar; final MulticurveSensitivity priceFutureDerivative = METHOD_FUTURE.priceCurveSensitivity( security.getUnderlyingFuture(), normalData.getMulticurveProvider()); return priceFutureDerivative.multipliedBy(priceFutureBar); }
/** * Computes the option security price volatility sensitivity. The future price is computed without * convexity adjustment. * * @param security The future option security. * @param normalData The normal volatility and multi-curves provider. * @return The security price Black volatility sensitivity. */ public SurfaceValue priceNormalSensitivity( final InterestRateFutureOptionMarginSecurity security, final NormalSTIRFuturesSmileProviderInterface normalData) { ArgumentChecker.notNull(security, "Option security"); ArgumentChecker.notNull(normalData, "Normal data"); // Forward sweep final double priceFuture = METHOD_FUTURE.price(security.getUnderlyingFuture(), normalData.getMulticurveProvider()); final double strike = security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, security.getExpirationTime(), security.isCall()); final double delay = security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime(); final double volatility = normalData.getVolatility(security.getExpirationTime(), security.getStrike(), delay); final NormalFunctionData normalPoint = new NormalFunctionData(priceFuture, 1.0, volatility); // Backward sweep final double[] priceAdjoint = new double[3]; NORMAL_FUNCTION.getPriceAdjoint(option, normalPoint, priceAdjoint); final double priceBar = 1.0; final double volatilityBar = priceAdjoint[1] * priceBar; final DoublesPair expiryStrikeDelay = new DoublesPair(security.getExpirationTime(), strike); final SurfaceValue sensi = SurfaceValue.from(expiryStrikeDelay, volatilityBar); return sensi; }
/** * Computes the option security price curve sensitivity. The future price is computed without * convexity adjustment. * * @param security The future option security. * @param sabrData The SABR data bundle. * @return The security price curve sensitivity. */ public PresentValueSABRSensitivityDataBundle priceSABRSensitivity( final InterestRateFutureOptionMarginSecurity security, final SABRInterestRateDataBundle sabrData) { final PresentValueSABRSensitivityDataBundle sensi = new PresentValueSABRSensitivityDataBundle(); // Forward sweep final double priceFuture = METHOD_FUTURE.price(security.getUnderlyingFuture(), sabrData); final double rateStrike = 1.0 - security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(rateStrike, security.getExpirationTime(), !security.isCall()); final double forward = 1 - priceFuture; final double delay = security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime(); final double[] volatilityAdjoint = sabrData .getSABRParameter() .getVolatilityAdjoint(security.getExpirationTime(), delay, rateStrike, forward); final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatilityAdjoint[0]); final double[] priceAdjoint = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); // Backward sweep final double priceBar = 1.0; final double volatilityBar = priceAdjoint[2] * priceBar; final DoublesPair expiryDelay = new DoublesPair(security.getExpirationTime(), delay); sensi.addAlpha(expiryDelay, volatilityAdjoint[3] * volatilityBar); sensi.addBeta(expiryDelay, volatilityAdjoint[4] * volatilityBar); sensi.addRho(expiryDelay, volatilityAdjoint[5] * volatilityBar); sensi.addNu(expiryDelay, volatilityAdjoint[6] * volatilityBar); return sensi; }
/** * Computes the option security price curve sensitivity. The future price is computed without * convexity adjustment. * * @param security The future option security. * @param sabrData The SABR data bundle. * @return The security price curve sensitivity. */ public InterestRateCurveSensitivity priceCurveSensitivity( final InterestRateFutureOptionMarginSecurity security, final SABRInterestRateDataBundle sabrData) { // Forward sweep final double priceFuture = METHOD_FUTURE.price(security.getUnderlyingFuture(), sabrData); final double rateStrike = 1.0 - security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(rateStrike, security.getExpirationTime(), !security.isCall()); final double forward = 1 - priceFuture; final double delay = security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime(); final double[] volatilityAdjoint = sabrData .getSABRParameter() .getVolatilityAdjoint(security.getExpirationTime(), delay, rateStrike, forward); final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatilityAdjoint[0]); final double[] priceAdjoint = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); // Backward sweep final double priceBar = 1.0; final double volatilityBar = priceAdjoint[2] * priceBar; final double forwardBar = priceAdjoint[1] * priceBar + volatilityAdjoint[1] * volatilityBar; final double priceFutureBar = -forwardBar; final InterestRateCurveSensitivity priceFutureDerivative = METHOD_FUTURE.priceCurveSensitivity(security.getUnderlyingFuture(), sabrData); return priceFutureDerivative.multipliedBy(priceFutureBar); }
/** * Computes the option security price from future price. * * @param security The future option security. * @param normalData The normal volatility and multi-curves provider. * @param priceFuture The price of the underlying future. * @return The security price. */ public double priceFromFuturePrice( final InterestRateFutureOptionMarginSecurity security, final NormalSTIRFuturesSmileProviderInterface normalData, final double priceFuture) { ArgumentChecker.notNull(security, "Option security"); ArgumentChecker.notNull(normalData, "Normal data"); final EuropeanVanillaOption option = new EuropeanVanillaOption( security.getStrike(), security.getExpirationTime(), security.isCall()); final double delay = security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime(); final double volatility = normalData.getVolatility(security.getExpirationTime(), security.getStrike(), delay); final NormalFunctionData normalPoint = new NormalFunctionData(priceFuture, 1.0, volatility); final double priceSecurity = NORMAL_FUNCTION.getPriceFunction(option).evaluate(normalPoint); return priceSecurity; }
/** * Interpolates and returns the option's implied volatility The future price is computed without * convexity adjustment. * * @param security The future option security. * @param normalData The normal volatility and multi-curves provider. * @return Lognormal Implied Volatility. */ public double impliedVolatility( final InterestRateFutureOptionMarginSecurity security, final NormalSTIRFuturesSmileProviderInterface normalData) { ArgumentChecker.notNull(security, "Option security"); ArgumentChecker.notNull(normalData, "Normal data"); final double delay = security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime(); return normalData.getVolatility(security.getExpirationTime(), security.getStrike(), delay); }
/** * Computes the price curve sensitivity in the Hull-White one factor model. * * @param security The option security. * @param hwMulticurves The multi-curves provider with Hull-White one factor parameters. * @return The curve sensitivity. */ @Override public MulticurveSensitivity priceCurveSensitivity( final InterestRateFutureOptionMarginSecurity security, final HullWhiteOneFactorProviderInterface hwMulticurves) { ArgumentChecker.notNull(security, "Option security"); ArgumentChecker.notNull(hwMulticurves, "Hull-White and multi-curves data"); ArgumentChecker.isTrue( security.getCurrency().equals(hwMulticurves.getHullWhiteCurrency()), "Model currency incompatible with security currency"); final MulticurveProviderInterface multicurves = hwMulticurves.getMulticurveProvider(); final HullWhiteOneFactorPiecewiseConstantParameters parameters = hwMulticurves.getHullWhiteParameters(); final double k = security.getStrike(); final double ktilde = 1.0 - k; final double theta = security.getExpirationTime(); final double delta = security.getUnderlyingFuture().getFixingPeriodAccrualFactor(); final double t0 = security.getUnderlyingFuture().getTradingLastTime(); final double t1 = security.getUnderlyingFuture().getFixingPeriodStartTime(); final double t2 = security.getUnderlyingFuture().getFixingPeriodEndTime(); // forward sweep final double alpha = MODEL.alpha(parameters, 0.0, theta, t1, t2); final double gamma = MODEL.futuresConvexityFactor(parameters, t0, t1, t2); final double forward = multicurves.getSimplyCompoundForwardRate( security.getUnderlyingFuture().getIborIndex(), t1, t2, delta); final double kappa = -Math.log((1 + delta * ktilde) / (1 + delta * forward) / gamma) / alpha - 0.5 * alpha; // Bakcward sweep final double priceBar = 1.0; double forwardBar; if (security.isCall()) { final double normalAlphaKappa = NORMAL.getCDF(-kappa - alpha); forwardBar = -gamma * normalAlphaKappa * priceBar; } else { final double normalAlphaKappa = NORMAL.getCDF(kappa + alpha); forwardBar = gamma * normalAlphaKappa * priceBar; } final Map<String, List<ForwardSensitivity>> mapFwd = new HashMap<>(); final List<ForwardSensitivity> listForward = new ArrayList<>(); listForward.add(new SimplyCompoundedForwardSensitivity(t1, t2, delta, forwardBar)); mapFwd.put( hwMulticurves .getMulticurveProvider() .getName(security.getUnderlyingFuture().getIborIndex()), listForward); return MulticurveSensitivity.ofForward(mapFwd); }
/** * Computes the option security price from future price. * * @param security The future option security. * @param sabrData The SABR data bundle. * @param priceFuture The price of the underlying future. * @return The security price. */ public double optionPriceFromFuturePrice( final InterestRateFutureOptionMarginSecurity security, final SABRInterestRateDataBundle sabrData, final double priceFuture) { final double rateStrike = 1.0 - security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(rateStrike, security.getExpirationTime(), !security.isCall()); final double forward = 1 - priceFuture; final double delay = security.getUnderlyingFuture().getLastTradingTime() - security.getExpirationTime(); final double volatility = sabrData .getSABRParameter() .getVolatility(new double[] {security.getExpirationTime(), delay, rateStrike, forward}); final BlackFunctionData dataBlack = new BlackFunctionData(forward, 1.0, volatility); final double priceSecurity = BLACK_FUNCTION.getPriceFunction(option).evaluate(dataBlack); return priceSecurity; }
/** * Computes the price in the Hull-White one factor model. * * @param security The option security. * @param hwMulticurves The multi-curves provider with Hull-White one factor parameters. * @return The price. */ @Override public double price( final InterestRateFutureOptionMarginSecurity security, final HullWhiteOneFactorProviderInterface hwMulticurves) { ArgumentChecker.notNull(security, "Option security"); ArgumentChecker.notNull(hwMulticurves, "Hull-White and multi-curves data"); ArgumentChecker.isTrue( security.getCurrency().equals(hwMulticurves.getHullWhiteCurrency()), "Model currency incompatible with security currency"); final MulticurveProviderInterface multicurves = hwMulticurves.getMulticurveProvider(); final HullWhiteOneFactorPiecewiseConstantParameters parameters = hwMulticurves.getHullWhiteParameters(); final double k = security.getStrike(); final double ktilde = 1.0 - k; final double theta = security.getExpirationTime(); final double delta = security.getUnderlyingFuture().getFixingPeriodAccrualFactor(); final double t0 = security.getUnderlyingFuture().getTradingLastTime(); final double t1 = security.getUnderlyingFuture().getFixingPeriodStartTime(); final double t2 = security.getUnderlyingFuture().getFixingPeriodEndTime(); final double alpha = MODEL.alpha(parameters, 0.0, theta, t1, t2); final double gamma = MODEL.futuresConvexityFactor(parameters, t0, t1, t2); final double forward = multicurves.getSimplyCompoundForwardRate( security.getUnderlyingFuture().getIborIndex(), t1, t2, delta); final double kappa = -Math.log((1 + delta * ktilde) / (1 + delta * forward) / gamma) / alpha - 0.5 * alpha; if (security.isCall()) { final double normalKappa = NORMAL.getCDF(-kappa); final double normalAlphaKappa = NORMAL.getCDF(-kappa - alpha); return (1 - k + 1.0 / delta) * normalKappa - (1.0 / delta + forward) * gamma * normalAlphaKappa; } final double normalKappa = NORMAL.getCDF(kappa); final double normalAlphaKappa = NORMAL.getCDF(kappa + alpha); return (1.0 / delta + forward) * gamma * normalAlphaKappa - (1 - k + 1.0 / delta) * normalKappa; }