/// <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); }