/// <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);
        }
        //-------------------------------------------------------------------------
        public virtual void test_theta_presentValueTheta()
        {
            double         theta         = PRICER.theta(CALL_OTM, RATES_PROVIDER, VOLS);
            CurrencyAmount pvTheta       = PRICER.presentValueTheta(CALL_OTM, RATES_PROVIDER, VOLS);
            double         timeToExpiry  = VOLS.relativeTime(EXPIRY);
            double         dfDom         = RATES_PROVIDER.discountFactor(USD, PAYMENT_DATE);
            double         forward       = PRICER.DiscountingFxSingleProductPricer.forwardFxRate(FX_PRODUCT_HIGH, RATES_PROVIDER).fxRate(CURRENCY_PAIR);
            double         vol           = SMILE_TERM.volatility(timeToExpiry, STRIKE_RATE_HIGH, forward);
            double         expectedTheta = dfDom * BlackFormulaRepository.driftlessTheta(forward, STRIKE_RATE_HIGH, timeToExpiry, vol);

            assertEquals(theta, expectedTheta, TOL);
            double expectedPvTheta = -NOTIONAL *dfDom *BlackFormulaRepository.driftlessTheta(forward, STRIKE_RATE_HIGH, timeToExpiry, vol);

            assertEquals(pvTheta.Currency, USD);
            assertEquals(pvTheta.Amount, expectedPvTheta, NOTIONAL * TOL);
        }
        public virtual void test_presentValueTheta_formula_shift()
        {
            CurrencyAmount computedCaplet   = PRICER.presentValueTheta(CAPLET_LONG, RATES, SHIFTED_VOLS);
            CurrencyAmount computedFloorlet = PRICER.presentValueTheta(FLOORLET_SHORT, RATES, SHIFTED_VOLS);
            double         forward          = RATES.iborIndexRates(EUR_EURIBOR_3M).rate(RATE_COMP.Observation);
            double         expiry           = SHIFTED_VOLS.relativeTime(CAPLET_LONG.FixingDateTime);
            double         volatility       = SHIFTED_VOLS.volatility(expiry, STRIKE, forward);
            double         df               = RATES.discountFactor(EUR, CAPLET_LONG.PaymentDate);
            double         shift            = IborCapletFloorletDataSet.SHIFT;
            double         expectedCaplet   = NOTIONAL * df * CAPLET_LONG.YearFraction * BlackFormulaRepository.driftlessTheta(forward + shift, STRIKE + shift, expiry, volatility);
            double         expectedFloorlet = -NOTIONAL *df *FLOORLET_SHORT.YearFraction *BlackFormulaRepository.driftlessTheta(forward + shift, STRIKE + shift, expiry, volatility);

            assertEquals(computedCaplet.Currency, EUR);
            assertEquals(computedCaplet.Amount, expectedCaplet, NOTIONAL * TOL);
            assertEquals(computedFloorlet.Currency, EUR);
            assertEquals(computedFloorlet.Amount, expectedFloorlet, NOTIONAL * TOL);
        }