/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.future.provider; import com.opengamma.analytics.financial.interestrate.future.derivative.BondFuturesOptionMarginSecurity; import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.BlackFunctionData; import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.BlackPriceFunction; import com.opengamma.analytics.financial.model.option.pricing.analytic.formula.EuropeanVanillaOption; import com.opengamma.analytics.financial.model.volatility.BlackFormulaRepository; import com.opengamma.analytics.financial.provider.description.interestrate.BlackBondFuturesProviderInterface; import com.opengamma.analytics.financial.provider.description.interestrate.IssuerProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity; import com.opengamma.util.ArgumentChecker; /** * Method for the pricing of bond future options (with futures-like margin). The pricing is done with a Black * formula on the bond future price. * The Black parameters are represented by (expiration-delay) surfaces. * The delay is the time difference between the last notice and the option expiration. */ public final class BondFuturesOptionMarginSecurityBlackBondFuturesMethod extends FuturesSecurityBlackBondFuturesMethod { /** The method default instance. */ private static final BondFuturesOptionMarginSecurityBlackBondFuturesMethod DEFAULT = new BondFuturesOptionMarginSecurityBlackBondFuturesMethod(); /** The Black function used in the pricing. */ private static final BlackPriceFunction BLACK_FUNCTION = new BlackPriceFunction(); /** The method used to compute the future price. */ private final FuturesSecurityIssuerMethod _methodFutures; /** * Default constructor. */ private BondFuturesOptionMarginSecurityBlackBondFuturesMethod() { _methodFutures = BondFuturesSecurityDiscountingMethod.getInstance(); } /** * Constructor from a particular bond futures method. The method is used to compute the price and price curve * sensitivity of the underlying futures. * @param methodFutures The bond futures method. */ public BondFuturesOptionMarginSecurityBlackBondFuturesMethod(FuturesSecurityIssuerMethod methodFutures) { super(methodFutures); _methodFutures = methodFutures; } /** * Return the method unique instance. * @return The instance. */ public static BondFuturesOptionMarginSecurityBlackBondFuturesMethod getDefaultInstance() { return DEFAULT; } /** * Computes the option security price from future price. * @param security The future option security, not null * @param black The curve and Black volatility data, not null * @param price The underlying futures price. * @return The security price. */ public double price(final BondFuturesOptionMarginSecurity security, final BlackBondFuturesProviderInterface black, final double price) { ArgumentChecker.notNull(security, "security"); ArgumentChecker.notNull(black, "Black data"); final double strike = security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, security.getExpirationTime(), security.isCall()); final double delay = security.getUnderlyingFuture().getNoticeLastTime() - security.getExpirationTime(); final double volatility = black.getVolatility(security.getExpirationTime(), delay, strike, price); final BlackFunctionData dataBlack = new BlackFunctionData(price, 1.0, volatility); final double priceSecurity = BLACK_FUNCTION.getPriceFunction(option).evaluate(dataBlack); return priceSecurity; } /** * Computes the option security price curve sensitivity. * It is supposed that for a given strike the volatility does not change with the curves. * The option price and its derivative wrt the futures price is computed using the futures price. * The derivatives of the futures price with respect to the curves are computed using the curves. * @param security The future option security, not null * @param black The curve and Black volatility data, not null * @param price The underlying futures price. * @return The security price curve sensitivity. */ public MulticurveSensitivity priceCurveSensitivity(final BondFuturesOptionMarginSecurity security, final BlackBondFuturesProviderInterface black, final double price) { ArgumentChecker.notNull(security, "security"); ArgumentChecker.notNull(black, "Black data"); // Forward sweep final double strike = security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, security.getExpirationTime(), security.isCall()); final double delay = security.getUnderlyingFuture().getNoticeLastTime() - security.getExpirationTime(); final double volatility = black.getVolatility(security.getExpirationTime(), delay, strike, price); final BlackFunctionData dataBlack = new BlackFunctionData(price, 1.0, volatility); final double[] priceAdjoint = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); // Backward sweep final double priceBar = 1.0; final double priceFutureBar = priceAdjoint[1] * priceBar; final MulticurveSensitivity priceFutureDerivative = _methodFutures.priceCurveSensitivity(security.getUnderlyingFuture(), black.getIssuerProvider()); return priceFutureDerivative.multipliedBy(priceFutureBar); } /** * Interpolates and returns the option's implied volatility * @param security The future option security, not null * @param black The curve and Black volatility data, not null * @return Lognormal Implied Volatility. */ public double impliedVolatility(final BondFuturesOptionMarginSecurity security, final BlackBondFuturesProviderInterface black) { ArgumentChecker.notNull(security, "security"); ArgumentChecker.notNull(black, "Black data"); final double priceFutures = _methodFutures.price(security.getUnderlyingFuture(), black.getIssuerProvider()); final double strike = security.getStrike(); final double delay = security.getUnderlyingFuture().getNoticeLastTime() - security.getExpirationTime(); final double volatility = black.getVolatility(security.getExpirationTime(), delay, strike, priceFutures); return volatility; } /** * Computes the underlying future security price. * @param security The future option security, not null * @param issuerMulticurves Issuer and multi-curves provider. * @return The security price. */ public double underlyingFuturePrice(final BondFuturesOptionMarginSecurity security, final IssuerProviderInterface issuerMulticurves) { ArgumentChecker.notNull(security, "security"); return _methodFutures.price(security.getUnderlyingFuture(), issuerMulticurves); } /** * The theoretical delta of the option with respect to the underlying futures price. * @param security The future option security, not null * @param black The curve and Black volatility data, not null * @return The delta. */ public double deltaUnderlyingPrice(final BondFuturesOptionMarginSecurity security, final BlackBondFuturesProviderInterface black) { ArgumentChecker.notNull(security, "security"); ArgumentChecker.notNull(black, "Black data"); final double priceFutures = _methodFutures.price(security.getUnderlyingFuture(), black.getIssuerProvider()); final double strike = security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, security.getExpirationTime(), security.isCall()); final double delay = security.getUnderlyingFuture().getNoticeLastTime() - security.getExpirationTime(); final double volatility = black.getVolatility(security.getExpirationTime(), delay, strike, priceFutures); final BlackFunctionData dataBlack = new BlackFunctionData(priceFutures, 1.0, volatility); final double[] priceAdjoint = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); return priceAdjoint[1]; } /** * The theoretical gamma of the option with respect to the underlying futures price. * @param security The future option security, not null * @param black The curve and Black volatility data, not null * @return The gamma. */ public double gammaUnderlyingPrice(final BondFuturesOptionMarginSecurity security, final BlackBondFuturesProviderInterface black) { ArgumentChecker.notNull(security, "security"); ArgumentChecker.notNull(black, "Black data"); final double priceFutures = _methodFutures.price(security.getUnderlyingFuture(), black.getIssuerProvider()); final double strike = security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, security.getExpirationTime(), security.isCall()); final double delay = security.getUnderlyingFuture().getNoticeLastTime() - security.getExpirationTime(); final double volatility = black.getVolatility(security.getExpirationTime(), delay, strike, priceFutures); final BlackFunctionData dataBlack = new BlackFunctionData(priceFutures, 1.0, volatility); final double[] firstDerivs = new double[3]; final double[][] secondDerivs = new double[3][3]; BLACK_FUNCTION.getPriceAdjoint2(option, dataBlack, firstDerivs, secondDerivs); return secondDerivs[0][0]; } /** * The theoretical vega of the option with respect to the underlying futures price. * @param security The future option security, not null * @param black The curve and Black volatility data, not null * @return The vega. */ public double vegaUnderlyingPrice(final BondFuturesOptionMarginSecurity security, final BlackBondFuturesProviderInterface black) { ArgumentChecker.notNull(security, "security"); ArgumentChecker.notNull(black, "Black data"); final double priceFutures = _methodFutures.price(security.getUnderlyingFuture(), black.getIssuerProvider()); final double strike = security.getStrike(); final EuropeanVanillaOption option = new EuropeanVanillaOption(strike, security.getExpirationTime(), security.isCall()); final double delay = security.getUnderlyingFuture().getNoticeLastTime() - security.getExpirationTime(); final double volatility = black.getVolatility(security.getExpirationTime(), delay, strike, priceFutures); final BlackFunctionData dataBlack = new BlackFunctionData(priceFutures, 1.0, volatility); final double[] priceAdjoint = BLACK_FUNCTION.getPriceAdjoint(option, dataBlack); return priceAdjoint[2]; } /** * The theoretical theta of the option with respect to the underlying futures price. * @param security The future option security, not null * @param black The curve and Black volatility data, not null * @return The theta. */ public double theta(final BondFuturesOptionMarginSecurity security, final BlackBondFuturesProviderInterface black) { ArgumentChecker.notNull(security, "security"); ArgumentChecker.notNull(black, "Black data"); final double priceFutures = _methodFutures.price(security.getUnderlyingFuture(), black.getIssuerProvider()); final double strike = security.getStrike(); final double delay = security.getUnderlyingFuture().getNoticeLastTime() - security.getExpirationTime(); final double volatility = black.getVolatility(security.getExpirationTime(), delay, strike, priceFutures); final double rate = -Math.log(black.getMulticurveProvider() .getDiscountFactor(security.getCurrency(), security.getExpirationTime())) / security.getExpirationTime(); return BlackFormulaRepository.theta(priceFutures, strike, security.getExpirationTime(), volatility, security.isCall(), rate); } }