/// <summary> /// Calculates the present value sensitivity of the FX barrier option product. /// <para> /// The present value sensitivity of the product is the sensitivity of <seealso cref="#presentValue"/> to /// the underlying curve parameters. /// </para> /// <para> /// The sensitivity is computed by bump and re-price. /// /// </para> /// </summary> /// <param name="option"> the option product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the Black volatility provider </param> /// <param name="baseTreeData"> the trinomial tree data </param> /// <returns> the present value of the product </returns> public virtual CurrencyParameterSensitivities presentValueSensitivityRates(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities, RecombiningTrinomialTreeData baseTreeData) { ArgChecker.isTrue(baseTreeData.NumberOfSteps == calibrator.NumberOfSteps, "the number of steps mismatch between pricer and trinomial tree data"); double shift = 1.0e-5; CurrencyAmount pvBase = presentValue(option, ratesProvider, volatilities, baseTreeData); ResolvedFxVanillaOption underlyingOption = option.UnderlyingOption; ResolvedFxSingle underlyingFx = underlyingOption.Underlying; CurrencyPair currencyPair = underlyingFx.CurrencyPair; ImmutableRatesProvider immRatesProvider = ratesProvider.toImmutableRatesProvider(); ImmutableMap <Currency, Curve> baseCurves = immRatesProvider.DiscountCurves; CurrencyParameterSensitivities result = CurrencyParameterSensitivities.empty(); foreach (KeyValuePair <Currency, Curve> entry in baseCurves.entrySet()) { if (currencyPair.contains(entry.Key)) { Curve curve = entry.Value; int nParams = curve.ParameterCount; DoubleArray sensitivity = DoubleArray.of(nParams, i => { Curve dscBumped = curve.withParameter(i, curve.getParameter(i) + shift); IDictionary <Currency, Curve> mapBumped = new Dictionary <Currency, Curve>(baseCurves); mapBumped[entry.Key] = dscBumped; ImmutableRatesProvider providerDscBumped = immRatesProvider.toBuilder().discountCurves(mapBumped).build(); double pvBumped = presentValue(option, providerDscBumped, volatilities).Amount; return((pvBumped - pvBase.Amount) / shift); }); result = result.combinedWith(curve.createParameterSensitivity(pvBase.Currency, sensitivity)); } } return(result); }
/// <summary> /// Creates an {@code ResolvedFxSingle} using a rate. /// <para> /// This create an FX specifying a value date, notional in one currency, the second currency /// and the FX rate between the two. /// The currencies of the payments must differ. /// </para> /// <para> /// This factory identifies the currency pair of the exchange and assigns the payments /// to match the base or counter currency of the standardized currency pair. /// For example, a EUR/USD exchange always has EUR as the base payment and USD as the counter payment. /// </para> /// <para> /// No payment date adjustments apply. /// /// </para> /// </summary> /// <param name="amountCurrency1"> the amount of the near leg in the first currency </param> /// <param name="fxRate"> the near FX rate </param> /// <param name="paymentDate"> date that the FX settles </param> /// <returns> the resolved foreign exchange transaction </returns> public static ResolvedFxSingle of(CurrencyAmount amountCurrency1, FxRate fxRate, LocalDate paymentDate) { CurrencyPair pair = fxRate.Pair; ArgChecker.isTrue(pair.contains(amountCurrency1.Currency)); Currency currency2 = pair.Base.Equals(amountCurrency1.Currency) ? pair.Counter : pair.Base; CurrencyAmount amountCurrency2 = amountCurrency1.convertedTo(currency2, fxRate).negated(); return(ResolvedFxSingle.of(Payment.of(amountCurrency1, paymentDate), Payment.of(amountCurrency2, paymentDate))); }
//------------------------------------------------------------------------- //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @ImmutableValidator private void validate() private void validate() { CurrencyPair pair = observation.Index.CurrencyPair; if (!pair.contains(settlementCurrencyNotional.Currency)) { throw new System.ArgumentException("FxIndex and settlement notional currency are incompatible"); } if (!(pair.Equals(agreedFxRate.Pair) || pair.isInverse(agreedFxRate.Pair))) { throw new System.ArgumentException("FxIndex and agreed FX rate are incompatible"); } }
// internal method where adjustment may be null private static FxSingle create(CurrencyAmount amount, FxRate fxRate, LocalDate paymentDate, BusinessDayAdjustment paymentDateAdjustment) { ArgChecker.notNull(amount, "amount"); ArgChecker.notNull(fxRate, "fxRate"); ArgChecker.notNull(paymentDate, "paymentDate"); CurrencyPair pair = fxRate.Pair; if (!pair.contains(amount.Currency)) { throw new System.ArgumentException(Messages.format("FxRate '{}' and CurrencyAmount '{}' must have a currency in common", fxRate, amount)); } Currency currency2 = pair.Base.Equals(amount.Currency) ? pair.Counter : pair.Base; CurrencyAmount amountCurrency2 = amount.convertedTo(currency2, fxRate).negated(); return(create(amount, amountCurrency2, paymentDate, paymentDateAdjustment)); }