/// <summary>
        /// Calculates the price sensitivity of the bond 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="discountingProvider">  the discounting provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the price of the underlying future </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public PointSensitivities priceSensitivityRatesStickyStrike(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider, BlackBondFutureVolatilities volatilities, double futurePrice)
        {
            double             delta = deltaStickyStrike(futureOption, discountingProvider, volatilities, futurePrice);
            PointSensitivities futurePriceSensitivity = futurePricer.priceSensitivity(futureOption.UnderlyingFuture, discountingProvider);

            return(futurePriceSensitivity.multipliedBy(delta));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the price sensitivity of the bond 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="discountingProvider">  the discounting provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public PointSensitivities priceSensitivityRatesStickyStrike(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider, BlackBondFutureVolatilities volatilities)
        {
            ArgChecker.isTrue(futureOption.PremiumStyle.Equals(FutureOptionPremiumStyle.DAILY_MARGIN), "Premium style should be DAILY_MARGIN");
            double futurePrice = this.futurePrice(futureOption, discountingProvider);

            return(priceSensitivityRatesStickyStrike(futureOption, discountingProvider, volatilities, futurePrice));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value sensitivity to the Black 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="discountingProvider">  the discounting provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the price of the underlying future </param>
        /// <returns> the price sensitivity </returns>
        public BondFutureOptionSensitivity presentValueSensitivityModelParamsVolatility(ResolvedBondFutureOptionTrade futureOptionTrade, LegalEntityDiscountingProvider discountingProvider, BlackBondFutureVolatilities volatilities, double futurePrice)
        {
            ResolvedBondFutureOption    product          = futureOptionTrade.Product;
            BondFutureOptionSensitivity priceSensitivity = productPricer.priceSensitivityModelParamsVolatility(product, discountingProvider, volatilities, futurePrice);
            double factor = productPricer.marginIndex(product, 1) * futureOptionTrade.Quantity;

            return(priceSensitivity.multipliedBy(factor));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the bond 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="discountingProvider">  the discounting provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the present value curve sensitivity of the trade </returns>
        public PointSensitivities presentValueSensitivityRates(ResolvedBondFutureOptionTrade trade, LegalEntityDiscountingProvider discountingProvider, BondFutureVolatilities volatilities)
        {
            ResolvedBondFutureOption product          = trade.Product;
            PointSensitivities       priceSensi       = productPricer.priceSensitivity(product, discountingProvider, volatilities);
            PointSensitivities       marginIndexSensi = productPricer.marginIndexSensitivity(product, priceSensi);

            return(marginIndexSensi.multipliedBy(trade.Quantity));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value of the bond future option trade from the current option price.
        /// <para>
        /// The present value of the product is the value on the valuation date.
        /// The current price is specified, not calculated.
        /// </para>
        /// <para>
        /// This method calculates based on the difference between the specified current 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="valuationDate">  the valuation date; required to asses if the trade or last closing price should be used </param>
        /// <param name="currentOptionPrice">  the option price on the valuation date </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(ResolvedBondFutureOptionTrade trade, LocalDate valuationDate, double currentOptionPrice, double lastOptionSettlementPrice)
        {
            ResolvedBondFutureOption option = trade.Product;
            double referencePrice           = this.referencePrice(trade, valuationDate, lastOptionSettlementPrice);
            double priceIndex     = productPricer.marginIndex(option, currentOptionPrice);
            double referenceIndex = productPricer.marginIndex(option, referencePrice);
            double pv             = (priceIndex - referenceIndex) * trade.Quantity;

            return(CurrencyAmount.of(option.UnderlyingFuture.Currency, pv));
        }
        /// <summary>
        /// Calculates the price sensitivity to the Black volatility used for the pricing of the bond future option
        /// based on the price of the underlying future.
        /// </summary>
        /// <param name="futureOption">  the option product </param>
        /// <param name="discountingProvider">  the discounting provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the underlying future price </param>
        /// <returns> the sensitivity </returns>
        public BondFutureOptionSensitivity priceSensitivityModelParamsVolatility(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider, BlackBondFutureVolatilities volatilities, double futurePrice)
        {
            ArgChecker.isTrue(futureOption.PremiumStyle.Equals(FutureOptionPremiumStyle.DAILY_MARGIN), "Premium style should be DAILY_MARGIN");
            double             strike       = futureOption.StrikePrice;
            ResolvedBondFuture future       = futureOption.UnderlyingFuture;
            double             volatility   = volatilities.volatility(futureOption.Expiry, future.LastTradeDate, strike, futurePrice);
            double             timeToExpiry = volatilities.relativeTime(futureOption.Expiry);
            double             vega         = BlackFormulaRepository.vega(futurePrice, strike, timeToExpiry, volatility);

            return(BondFutureOptionSensitivity.of(volatilities.Name, timeToExpiry, future.LastTradeDate, strike, futurePrice, future.Currency, vega));
        }
        /// <summary>
        /// Calculates the theta of the bond future option product based on the price of the underlying future.
        /// <para>
        /// The theta of the product is minus of the option price sensitivity to the time to expiry.
        /// 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="discountingProvider">  the discounting provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <param name="futurePrice">  the price of the underlying future </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public double theta(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider, BlackBondFutureVolatilities volatilities, double futurePrice)
        {
            ArgChecker.isTrue(futureOption.PremiumStyle.Equals(FutureOptionPremiumStyle.DAILY_MARGIN), "Premium style should be DAILY_MARGIN");
            double             strike       = futureOption.StrikePrice;
            ResolvedBondFuture future       = futureOption.UnderlyingFuture;
            double             volatility   = volatilities.volatility(futureOption.Expiry, future.LastTradeDate, strike, futurePrice);
            double             timeToExpiry = volatilities.relativeTime(futureOption.Expiry);
            double             theta        = BlackFormulaRepository.driftlessTheta(futurePrice, strike, timeToExpiry, volatility);

            return(theta);
        }
        /// <summary>
        /// Calculates the margin index sensitivity of the bond future product.
        /// <para>
        /// For two consecutive settlement prices C1 and C2, the daily margin is computed as
        ///    {@code marginIndex(future, C2) - marginIndex(future, C1)}.
        /// The margin index sensitivity if the sensitivity of the margin index to the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="option">  the option product </param>
        /// <param name="priceSensitivity">  the price sensitivity of the product </param>
        /// <returns> the index sensitivity </returns>
        internal PointSensitivities marginIndexSensitivity(ResolvedBondFutureOption option, PointSensitivities priceSensitivity)
        {
            double notional = option.UnderlyingFuture.Notional;

            return(priceSensitivity.multipliedBy(notional));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the number related to bond futures product on which the daily margin is computed.
        /// <para>
        /// For two consecutive settlement prices C1 and C2, the daily margin is computed as
        ///    {@code marginIndex(future, C2) - marginIndex(future, C1)}.
        ///
        /// </para>
        /// </summary>
        /// <param name="option">  the option product </param>
        /// <param name="price">  the price of the product, in decimal form </param>
        /// <returns> the index </returns>
        internal double marginIndex(ResolvedBondFutureOption option, double price)
        {
            double notional = option.UnderlyingFuture.Notional;

            return(price * notional);
        }
        //-------------------------------------------------------------------------
        // calculate the price of the underlying future
        private double futurePrice(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider)
        {
            ResolvedBondFuture future = futureOption.UnderlyingFuture;

            return(futurePricer.price(future, discountingProvider));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the price sensitivity to the Black volatility used for the pricing of the bond future option.
        /// <para>
        /// This calculates the underlying future price using the future pricer.
        ///
        /// </para>
        /// </summary>
        /// <param name="futureOption">  the option product </param>
        /// <param name="discountingProvider">  the discounting provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the sensitivity </returns>
        public BondFutureOptionSensitivity priceSensitivityModelParamsVolatility(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider, BlackBondFutureVolatilities volatilities)
        {
            double futurePrice = this.futurePrice(futureOption, discountingProvider);

            return(priceSensitivityModelParamsVolatility(futureOption, discountingProvider, volatilities, futurePrice));
        }
 internal PointSensitivities priceSensitivity(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider, BondFutureVolatilities volatilities)
 {
     ArgChecker.isTrue(volatilities is BlackBondFutureVolatilities, "Provider must be of type BlackVolatilityBondFutureProvider");
     return(priceSensitivityRatesStickyStrike(futureOption, discountingProvider, (BlackBondFutureVolatilities)volatilities));
 }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the theta of the bond future option product.
        /// <para>
        /// The theta of the product is the minus of the option price sensitivity to the time to expiry.
        /// 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="discountingProvider">  the discounting provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public double theta(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider, BlackBondFutureVolatilities volatilities)
        {
            double futurePrice = this.futurePrice(futureOption, discountingProvider);

            return(theta(futureOption, discountingProvider, volatilities, futurePrice));
        }
 internal double price(ResolvedBondFutureOption futureOption, LegalEntityDiscountingProvider discountingProvider, BondFutureVolatilities volatilities)
 {
     ArgChecker.isTrue(volatilities is BlackBondFutureVolatilities, "Provider must be of type BlackVolatilityBondFutureProvider");
     return(price(futureOption, discountingProvider, (BlackBondFutureVolatilities)volatilities));
 }