//-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value sensitivity to the normal volatility used in the pricing
        /// based on the price of the underlying future.
        /// <para>
        /// The result is a single sensitivity to the volatility used.
        /// The volatility is associated with the expiry/delay/strike/future price key combination.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOptionTrade">  the trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the price of the underlying future, in decimal form </param>
        /// <returns> the price sensitivity </returns>
        public IborFutureOptionSensitivity presentValueSensitivityModelParamsVolatility(ResolvedIborFutureOptionTrade futureOptionTrade, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities, double futurePrice)
        {
            ResolvedIborFutureOption    product          = futureOptionTrade.Product;
            IborFutureOptionSensitivity priceSensitivity = futureOptionPricer.priceSensitivityModelParamsVolatility(product, ratesProvider, volatilities, futurePrice);
            double factor = futureOptionPricer.marginIndex(product, 1) * futureOptionTrade.Quantity;

            return(priceSensitivity.multipliedBy(factor));
        }
 //-------------------------------------------------------------------------
 /// <summary>
 /// Calculates the price of the Ibor future option trade.
 /// <para>
 /// The price of the trade is the price on the valuation date.
 /// The price is calculated using the volatility model.
 ///
 /// </para>
 /// </summary>
 /// <param name="trade">  the trade </param>
 /// <param name="ratesProvider">  the rates provider </param>
 /// <param name="volatilities">  the volatilities </param>
 /// <returns> the price of the product, in decimal form </returns>
 public double price(ResolvedIborFutureOptionTrade trade, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities)
 {
     return(futureOptionPricer.price(trade.Product, ratesProvider, volatilities));
 }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the Ibor future option trade.
        /// <para>
        /// The present value sensitivity of the trade is the sensitivity of the present value to
        /// the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="trade">  the trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the present value curve sensitivity of the trade </returns>
        public PointSensitivities presentValueSensitivityRates(ResolvedIborFutureOptionTrade trade, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities)
        {
            ResolvedIborFutureOption product          = trade.Product;
            PointSensitivities       priceSensi       = futureOptionPricer.priceSensitivityRatesStickyStrike(product, ratesProvider, volatilities);
            PointSensitivities       marginIndexSensi = futureOptionPricer.marginIndexSensitivity(product, priceSensi);

            return(marginIndexSensi.multipliedBy(trade.Quantity));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value sensitivity to the normal volatility used in the pricing.
        /// <para>
        /// The result is a single sensitivity to the volatility used.
        /// The volatility is associated with the expiry/delay/strike/future price key combination.
        /// </para>
        /// <para>
        /// This calculates the underlying future price using the future pricer.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOptionTrade">  the trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the price sensitivity </returns>
        public IborFutureOptionSensitivity presentValueSensitivityModelParamsVolatility(ResolvedIborFutureOptionTrade futureOptionTrade, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities)
        {
            ResolvedIborFuture future      = futureOptionTrade.Product.UnderlyingFuture;
            double             futurePrice = futureOptionPricer.FuturePricer.price(future, ratesProvider);

            return(presentValueSensitivityModelParamsVolatility(futureOptionTrade, ratesProvider, volatilities, futurePrice));
        }
        /// <summary>
        /// Calculates the price sensitivity to the normal volatility used for the pricing of the Ibor future option
        /// based on the price of the underlying future.
        /// <para>
        /// This sensitivity is also called the <i>price normal vega</i>.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOption">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the underlying future price, in decimal form </param>
        /// <returns> the sensitivity </returns>
        public virtual IborFutureOptionSensitivity priceSensitivityModelParamsVolatility(ResolvedIborFutureOption futureOption, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities, double futurePrice)
        {
            ArgChecker.isTrue(futureOption.PremiumStyle.Equals(FutureOptionPremiumStyle.DAILY_MARGIN), "Premium style should be DAILY_MARGIN");

            double             timeToExpiry = volatilities.relativeTime(futureOption.Expiry);
            double             strike       = futureOption.StrikePrice;
            ResolvedIborFuture future       = futureOption.UnderlyingFuture;
            double             volatility   = volatilities.volatility(timeToExpiry, future.LastTradeDate, strike, futurePrice);

            double vega = NormalFormulaRepository.vega(futurePrice, strike, timeToExpiry, volatility, futureOption.PutCall);

            return(IborFutureOptionSensitivity.of(volatilities.Name, timeToExpiry, future.LastTradeDate, strike, futurePrice, future.Currency, vega));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value of the Ibor future option trade from the underlying future price.
        /// <para>
        /// The present value of the product is the value on the valuation date.
        /// The current price is calculated using the volatility model with a known future price.
        /// </para>
        /// <para>
        /// This method calculates based on the difference between the model price and the
        /// last settlement price, or the trade price if traded on the valuation date.
        ///
        /// </para>
        /// </summary>
        /// <param name="trade">  the trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the price of the underlying future, in decimal form </param>
        /// <param name="lastOptionSettlementPrice">  the last settlement price used for margining for the option, in decimal form </param>
        /// <returns> the present value </returns>
        public CurrencyAmount presentValue(ResolvedIborFutureOptionTrade trade, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities, double futurePrice, double lastOptionSettlementPrice)
        {
            double optionPrice = futureOptionPricer.price(trade.Product, ratesProvider, volatilities, futurePrice);

            return(presentValue(trade, ratesProvider.ValuationDate, optionPrice, lastOptionSettlementPrice));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the price sensitivity to the normal volatility used for the pricing of the Ibor future option.
        /// <para>
        /// This sensitivity is also called the <i>price normal vega</i>.
        /// </para>
        /// <para>
        /// This calculates the underlying future price using the future pricer.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOption">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the sensitivity </returns>
        public virtual IborFutureOptionSensitivity priceSensitivityModelParamsVolatility(ResolvedIborFutureOption futureOption, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities)
        {
            double futurePrice = this.futurePrice(futureOption, ratesProvider);

            return(priceSensitivityModelParamsVolatility(futureOption, ratesProvider, volatilities, futurePrice));
        }
        /// <summary>
        /// Calculates the price sensitivity of the Ibor future option product
        /// based on the price of the underlying future.
        /// <para>
        /// The price sensitivity of the product is the sensitivity of the price to the underlying curves.
        /// The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOption">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the price of the underlying future, in decimal form </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public virtual PointSensitivities priceSensitivityRatesStickyStrike(ResolvedIborFutureOption futureOption, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities, double futurePrice)
        {
            double             delta = deltaStickyStrike(futureOption, ratesProvider, volatilities, futurePrice);
            PointSensitivities futurePriceSensitivity = futurePricer.priceSensitivity(futureOption.UnderlyingFuture, ratesProvider);

            return(futurePriceSensitivity.multipliedBy(delta));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the price sensitivity of the Ibor future option product based on curves.
        /// <para>
        /// The price sensitivity of the product is the sensitivity of the price to the underlying curves.
        /// The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
        /// </para>
        /// <para>
        /// This calculates the underlying future price using the future pricer.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOption">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public virtual PointSensitivities priceSensitivityRatesStickyStrike(ResolvedIborFutureOption futureOption, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities)
        {
            ArgChecker.isTrue(futureOption.PremiumStyle.Equals(FutureOptionPremiumStyle.DAILY_MARGIN), "Premium style should be DAILY_MARGIN");

            double futurePrice = this.futurePrice(futureOption, ratesProvider);

            return(priceSensitivityRatesStickyStrike(futureOption, ratesProvider, volatilities, futurePrice));
        }
        /// <summary>
        /// Calculates the delta of the Ibor future option product
        /// based on the price of the underlying future.
        /// <para>
        /// The delta of the product is the sensitivity of the option price to the future price.
        /// The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOption">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the price of the underlying future, in decimal form </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public virtual double deltaStickyStrike(ResolvedIborFutureOption futureOption, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities, double futurePrice)
        {
            ArgChecker.isTrue(futureOption.PremiumStyle.Equals(FutureOptionPremiumStyle.DAILY_MARGIN), "Premium style should be DAILY_MARGIN");

            double             timeToExpiry = volatilities.relativeTime(futureOption.Expiry);
            double             strike       = futureOption.StrikePrice;
            ResolvedIborFuture future       = futureOption.UnderlyingFuture;
            double             volatility   = volatilities.volatility(timeToExpiry, future.LastTradeDate, strike, futurePrice);

            return(NormalFormulaRepository.delta(futurePrice, strike, timeToExpiry, volatility, futureOption.PutCall));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the delta of the Ibor future option product.
        /// <para>
        /// The delta of the product is the sensitivity of the option price to the future price.
        /// The volatility is unchanged for a fixed strike in the sensitivity computation, hence the "StickyStrike" name.
        /// </para>
        /// <para>
        /// This calculates the underlying future price using the future pricer.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOption">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public virtual double deltaStickyStrike(ResolvedIborFutureOption futureOption, RatesProvider ratesProvider, NormalIborFutureOptionVolatilities volatilities)
        {
            double futurePrice = this.futurePrice(futureOption, ratesProvider);

            return(deltaStickyStrike(futureOption, ratesProvider, volatilities, futurePrice));
        }