/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.future.provider; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.opengamma.analytics.financial.interestrate.future.derivative.InterestRateFutureOptionMarginSecurity; import com.opengamma.analytics.financial.model.interestrate.HullWhiteOneFactorPiecewiseConstantInterestRateModel; import com.opengamma.analytics.financial.model.interestrate.definition.HullWhiteOneFactorPiecewiseConstantParameters; import com.opengamma.analytics.financial.provider.description.interestrate.HullWhiteOneFactorProviderInterface; import com.opengamma.analytics.financial.provider.description.interestrate.MulticurveProviderInterface; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.ForwardSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.MulticurveSensitivity; import com.opengamma.analytics.financial.provider.sensitivity.multicurve.SimplyCompoundedForwardSensitivity; import com.opengamma.analytics.math.statistics.distribution.NormalDistribution; import com.opengamma.analytics.math.statistics.distribution.ProbabilityDistribution; import com.opengamma.util.ArgumentChecker; /** * Method for the pricing of interest rate future options with daily margining. * The model is the Hull-White one factor model {@link HullWhiteOneFactorPiecewiseConstantInterestRateModel}. * <p>Reference: Interest Rate Futures and their options: Some Pricing Approaches. OpenGamma Documentation n.6. Version 1.5 - December 2012. */ public final class InterestRateFutureOptionMarginSecurityHullWhiteMethod extends InterestRateFutureOptionMarginSecurityGenericMethod<HullWhiteOneFactorProviderInterface> { /** * The unique instance of the calculator. */ private static final InterestRateFutureOptionMarginSecurityHullWhiteMethod INSTANCE = new InterestRateFutureOptionMarginSecurityHullWhiteMethod(); /** * Constructor. */ private InterestRateFutureOptionMarginSecurityHullWhiteMethod() { } /** * Gets the calculator instance. * @return The calculator. */ public static InterestRateFutureOptionMarginSecurityHullWhiteMethod getInstance() { return INSTANCE; } /** * The Hull-White model. */ private static final HullWhiteOneFactorPiecewiseConstantInterestRateModel MODEL = new HullWhiteOneFactorPiecewiseConstantInterestRateModel(); /** * The normal distribution implementation. */ private static final ProbabilityDistribution<Double> NORMAL = new NormalDistribution(0, 1); /** * 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; } /** * 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); } }