//-------------------------------------------------------------------------
        /// <summary>
        /// Calibrate trinomial tree to Black volatilities by using a vanilla option.
        /// <para>
        /// {@code ResolvedFxVanillaOption} is typically the underlying option of an exotic instrument to price using the
        /// calibrated tree, and is used to ensure that the grid points properly cover the lifetime of the target option.
        ///
        /// </para>
        /// </summary>
        /// <param name="option">  the vanilla option </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <returns> the trinomial tree data </returns>
        public virtual RecombiningTrinomialTreeData calibrateTrinomialTree(ResolvedFxVanillaOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities)
        {
            double       timeToExpiry = volatilities.relativeTime(option.Expiry);
            CurrencyPair currencyPair = option.Underlying.CurrencyPair;

            return(calibrateTrinomialTree(timeToExpiry, currencyPair, ratesProvider, volatilities));
        }
Beispiel #2
0
 //-------------------------------------------------------------------------
 public virtual void test_presentValueSensitivity()
 {
     for (int i = 0; i < NB_STRIKES; ++i)
     {
         ResolvedFxVanillaOption        option        = CALLS[i];
         PointSensitivityBuilder        point         = PRICER.presentValueSensitivityRatesStickyStrike(option, RATES_PROVIDER, VOLS);
         CurrencyParameterSensitivities sensiComputed = RATES_PROVIDER.parameterSensitivity(point.build());
         double timeToExpiry = VOLS.relativeTime(EXPIRY);
         double forwardRate  = FX_PRICER.forwardFxRate(UNDERLYING[i], RATES_PROVIDER).fxRate(CURRENCY_PAIR);
         double strikeRate   = option.Strike;
         SmileDeltaParameters smileAtTime = VOLS.Smile.smileForExpiry(timeToExpiry);
         double[]             vols        = smileAtTime.Volatility.toArray();
         double df = RATES_PROVIDER.discountFactor(USD, PAY);
         CurrencyParameterSensitivities sensiExpected = FD_CAL.sensitivity(RATES_PROVIDER, p => PRICER.presentValue(option, p, VOLS));
         CurrencyParameterSensitivities sensiRes      = FD_CAL.sensitivity(RATES_PROVIDER, (ImmutableRatesProvider p) =>
         {
             double fwd     = FX_PRICER.forwardFxRate(option.Underlying, p).fxRate(CURRENCY_PAIR);
             double[] strs  = smileAtTime.strike(fwd).toArray();
             double[] wghts = weights(fwd, strikeRate, strs, timeToExpiry, vols[1]);
             double res     = 0d;
             for (int j = 0; j < 3; ++j)
             {
                 res += wghts[j] * (BlackFormulaRepository.price(forwardRate, strs[j], timeToExpiry, vols[j], true) - BlackFormulaRepository.price(forwardRate, strs[j], timeToExpiry, vols[1], true));
             }
             return(CurrencyAmount.of(USD, -res * df * NOTIONAL));
         });
         assertTrue(sensiComputed.equalWithTolerance(sensiExpected.combinedWith(sensiRes), FD_EPS * NOTIONAL * 10d));
     }
 }
Beispiel #3
0
 //-------------------------------------------------------------------------
 public virtual void test_price_presentValue()
 {
     for (int i = 0; i < NB_STRIKES; ++i)
     {
         ResolvedFxVanillaOption      call      = CALLS[i];
         ResolvedFxVanillaOptionTrade callTrade = ResolvedFxVanillaOptionTrade.builder().product(call).premium(Payment.of(EUR, 0, VAL_DATE)).build();
         double               computedPriceCall = PRICER.price(call, RATES_PROVIDER, VOLS);
         CurrencyAmount       computedCall      = PRICER.presentValue(call, RATES_PROVIDER, VOLS);
         double               timeToExpiry      = VOLS.relativeTime(EXPIRY);
         FxRate               forward           = FX_PRICER.forwardFxRate(UNDERLYING[i], RATES_PROVIDER);
         double               forwardRate       = forward.fxRate(CURRENCY_PAIR);
         double               strikeRate        = call.Strike;
         SmileDeltaParameters smileAtTime       = VOLS.Smile.smileForExpiry(timeToExpiry);
         double[]             strikes           = smileAtTime.strike(forwardRate).toArray();
         double[]             vols              = smileAtTime.Volatility.toArray();
         double               df                = RATES_PROVIDER.discountFactor(USD, PAY);
         double[]             weights           = this.weights(forwardRate, strikeRate, strikes, timeToExpiry, vols[1]);
         double               expectedPriceCall = BlackFormulaRepository.price(forwardRate, strikeRate, timeToExpiry, vols[1], true);
         for (int j = 0; j < 3; ++j)
         {
             expectedPriceCall += weights[j] * (BlackFormulaRepository.price(forwardRate, strikes[j], timeToExpiry, vols[j], true) - BlackFormulaRepository.price(forwardRate, strikes[j], timeToExpiry, vols[1], true));
         }
         expectedPriceCall *= df;
         assertEquals(computedPriceCall, expectedPriceCall, TOL);
         assertEquals(computedCall.Amount, expectedPriceCall * NOTIONAL, TOL * NOTIONAL);
         // test against trade pricer
         assertEquals(computedCall, TRADE_PRICER.presentValue(callTrade, RATES_PROVIDER, VOLS).getAmount(USD));
     }
 }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the currency exposure of the FX vanilla option trade.
        /// </summary>
        /// <param name="trade">  the option trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <returns> the currency exposure </returns>
        public virtual MultiCurrencyAmount currencyExposure(ResolvedFxVanillaOptionTrade trade, RatesProvider ratesProvider, BlackFxOptionSmileVolatilities volatilities)
        {
            Payment                 premium   = trade.Premium;
            CurrencyAmount          pvPremium = paymentPricer.presentValue(premium, ratesProvider);
            ResolvedFxVanillaOption product   = trade.Product;

            return(productPricer.currencyExposure(product, ratesProvider, volatilities).plus(pvPremium));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the FX vanilla option trade.
        /// <para>
        /// The present value sensitivity of the trade is the sensitivity of the present value to
        /// the underlying curves.
        /// </para>
        /// <para>
        /// The volatility is fixed in this sensitivity computation.
        ///
        /// </para>
        /// </summary>
        /// <param name="trade">  the option trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <returns> the present value curve sensitivity of the trade </returns>
        public virtual PointSensitivities presentValueSensitivityRatesStickyStrike(ResolvedFxVanillaOptionTrade trade, RatesProvider ratesProvider, BlackFxOptionSmileVolatilities volatilities)
        {
            ResolvedFxVanillaOption product     = trade.Product;
            PointSensitivities      pvcsProduct = productPricer.presentValueSensitivityRatesStickyStrike(product, ratesProvider, volatilities).build();
            Payment            premium          = trade.Premium;
            PointSensitivities pvcsPremium      = paymentPricer.presentValueSensitivity(premium, ratesProvider).build();

            return(pvcsProduct.combinedWith(pvcsPremium));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value of the FX vanilla option trade.
        /// <para>
        /// The present value of the trade is the value on the valuation date.
        ///
        /// </para>
        /// </summary>
        /// <param name="trade">  the option trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <returns> the present value of the trade </returns>
        public virtual MultiCurrencyAmount presentValue(ResolvedFxVanillaOptionTrade trade, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities)
        {
            ResolvedFxVanillaOption product   = trade.Product;
            CurrencyAmount          pvProduct = productPricer.presentValue(product, ratesProvider, volatilities);
            Payment        premium            = trade.Premium;
            CurrencyAmount pvPremium          = paymentPricer.presentValue(premium, ratesProvider);

            return(MultiCurrencyAmount.of(pvProduct).plus(pvPremium));
        }
Beispiel #7
0
 static VannaVolgaFxVanillaOptionProductPricerTest()
 {
     for (int i = 0; i < NB_STRIKES; ++i)
     {
         double         strike    = STRIKE_MIN + i * STRIKE_RANGE / (NB_STRIKES - 1d);
         CurrencyAmount eurAmount = CurrencyAmount.of(EUR, NOTIONAL);
         CurrencyAmount usdAmount = CurrencyAmount.of(USD, -NOTIONAL * strike);
         UNDERLYING[i] = ResolvedFxSingle.of(eurAmount, usdAmount, PAY);
         CALLS[i]      = ResolvedFxVanillaOption.builder().longShort(LONG).expiry(EXPIRY).underlying(UNDERLYING[i]).build();
         PUTS[i]       = ResolvedFxVanillaOption.builder().longShort(SHORT).expiry(EXPIRY).underlying(UNDERLYING[i].inverse()).build();
     }
 }
Beispiel #8
0
 public virtual void test_price_presentValue_afterExpiry()
 {
     for (int i = 0; i < NB_STRIKES; ++i)
     {
         ResolvedFxVanillaOption      call      = CALLS[i];
         ResolvedFxVanillaOptionTrade callTrade = ResolvedFxVanillaOptionTrade.builder().product(call).premium(Payment.of(EUR, 0, VOLS_AFTER.ValuationDate)).build();
         double         computedPriceCall       = PRICER.price(call, RATES_PROVIDER_AFTER, VOLS_AFTER);
         CurrencyAmount computedCall            = PRICER.presentValue(call, RATES_PROVIDER_AFTER, VOLS_AFTER);
         assertEquals(computedPriceCall, 0d, TOL);
         assertEquals(computedCall.Amount, 0d, TOL);
         ResolvedFxVanillaOption      put      = PUTS[i];
         ResolvedFxVanillaOptionTrade putTrade = ResolvedFxVanillaOptionTrade.builder().product(put).premium(Payment.of(EUR, 0, VOLS_AFTER.ValuationDate)).build();
         double         computedPricePut       = PRICER.price(put, RATES_PROVIDER_AFTER, VOLS_AFTER);
         CurrencyAmount computedPut            = PRICER.presentValue(put, RATES_PROVIDER_AFTER, VOLS_AFTER);
         assertEquals(computedPricePut, 0d, TOL);
         assertEquals(computedPut.Amount, 0d, TOL);
         // test against trade pricer
         assertEquals(computedCall, TRADE_PRICER.presentValue(callTrade, RATES_PROVIDER_AFTER, VOLS_AFTER).getAmount(USD));
         assertEquals(computedPut, TRADE_PRICER.presentValue(putTrade, RATES_PROVIDER_AFTER, VOLS_AFTER).getAmount(USD));
     }
 }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value sensitivity to the black volatility used in the pricing.
        /// <para>
        /// The result is a single sensitivity to the volatility used.
        ///
        /// </para>
        /// </summary>
        /// <param name="trade">  the option trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <returns> the present value sensitivity </returns>
        public virtual PointSensitivities presentValueSensitivityModelParamsVolatility(ResolvedFxVanillaOptionTrade trade, RatesProvider ratesProvider, BlackFxOptionSmileVolatilities volatilities)
        {
            ResolvedFxVanillaOption product = trade.Product;

            return(productPricer.presentValueSensitivityModelParamsVolatility(product, ratesProvider, volatilities).build());
        }