//------------------------------------------------------------------------- private void validateData(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities, RecombiningTrinomialTreeData data) { ResolvedFxVanillaOption underlyingOption = option.UnderlyingOption; ArgChecker.isTrue(DoubleMath.fuzzyEquals(data.getTime(data.NumberOfSteps), volatilities.relativeTime(underlyingOption.Expiry), SMALL), "time to expiry mismatch between pricing option and trinomial tree data"); ArgChecker.isTrue(DoubleMath.fuzzyEquals(data.Spot, ratesProvider.fxRate(underlyingOption.Underlying.CurrencyPair), SMALL), "today's FX rate mismatch between rates provider and trinomial tree data"); }
// Check FX rates are transfered in multi-currency cases. public virtual void calibrate_xccy() { RatesProvider multicurveSyn = CALIBRATOR_SYNTHETIC.calibrate(GROUPS_SYN_USDEUR, MULTICURVE_INPUT_USDEUR_TSEMPTY, REF_DATA); double eurUsdInput = MULTICURVE_INPUT_USDEUR_TSEMPTY.fxRate(Currency.EUR, Currency.USD); double eurUsdSynthetic = multicurveSyn.fxRate(Currency.EUR, Currency.USD); assertEquals(eurUsdInput, eurUsdSynthetic, TOLERANCE_MQ); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the swap product, converted to the specified currency. /// <para> /// The present value of the product is the value on the valuation date. /// This is the discounted forecast value. /// The result is converted to the specified currency. /// /// </para> /// </summary> /// <param name="swap"> the product </param> /// <param name="currency"> the currency to convert to </param> /// <param name="provider"> the rates provider </param> /// <returns> the present value of the swap product in the specified currency </returns> public virtual CurrencyAmount presentValue(ResolvedSwap swap, Currency currency, RatesProvider provider) { double totalPv = 0; foreach (ResolvedSwapLeg leg in swap.Legs) { double pv = legPricer.presentValueInternal(leg, provider); totalPv += (pv * provider.fxRate(leg.Currency, currency)); } return(CurrencyAmount.of(currency, totalPv)); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the currency exposure of the foreign exchange vanilla option product. /// </summary> /// <param name="option"> the option product </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(ResolvedFxVanillaOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { CurrencyPair strikePair = option.Underlying.CurrencyPair; double price = this.price(option, ratesProvider, volatilities); double delta = this.delta(option, ratesProvider, volatilities); double spot = ratesProvider.fxRate(strikePair); double signedNotional = this.signedNotional(option); CurrencyAmount domestic = CurrencyAmount.of(strikePair.Counter, (price - delta * spot) * signedNotional); CurrencyAmount foreign = CurrencyAmount.of(strikePair.Base, delta * signedNotional); return(MultiCurrencyAmount.of(domestic, foreign)); }
/// <summary> /// Calculates the currency exposure of the FX barrier option product. /// <para> /// This assumes the tree is already calibrated and the tree data is stored as {@code RecombiningTrinomialTreeData}. /// The tree data should be consistent with the pricer and other inputs, see <seealso cref="#validateData"/>. /// /// </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="treeData"> the trinomial tree data </param> /// <returns> the currency exposure </returns> public virtual MultiCurrencyAmount currencyExposure(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities, RecombiningTrinomialTreeData treeData) { ResolvedFxVanillaOption underlyingOption = option.UnderlyingOption; ValueDerivatives priceDerivatives = this.priceDerivatives(option, ratesProvider, volatilities, treeData); double price = priceDerivatives.Value; double delta = priceDerivatives.getDerivative(0); CurrencyPair currencyPair = underlyingOption.Underlying.CurrencyPair; double todayFx = ratesProvider.fxRate(currencyPair); double signedNotional = this.signedNotional(underlyingOption); CurrencyAmount domestic = CurrencyAmount.of(currencyPair.Counter, (price - delta * todayFx) * signedNotional); CurrencyAmount foreign = CurrencyAmount.of(currencyPair.Base, delta * signedNotional); return(MultiCurrencyAmount.of(domestic, foreign)); }
//------------------------------------------------------------------------- // The derivatives are [0] spot, [1] strike, [2] rate, [3] cost-of-carry, [4] volatility, [5] timeToExpiry, [6] spot twice private ValueDerivatives priceDerivatives(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { validate(option, ratesProvider, volatilities); SimpleConstantContinuousBarrier barrier = (SimpleConstantContinuousBarrier)option.Barrier; ResolvedFxVanillaOption underlyingOption = option.UnderlyingOption; double[] derivatives = new double[7]; if (volatilities.relativeTime(underlyingOption.Expiry) < 0d) { return(ValueDerivatives.of(0d, DoubleArray.ofUnsafe(derivatives))); } ResolvedFxSingle underlyingFx = underlyingOption.Underlying; CurrencyPair currencyPair = underlyingFx.CurrencyPair; Currency ccyBase = currencyPair.Base; Currency ccyCounter = currencyPair.Counter; DiscountFactors baseDiscountFactors = ratesProvider.discountFactors(ccyBase); DiscountFactors counterDiscountFactors = ratesProvider.discountFactors(ccyCounter); double rateBase = baseDiscountFactors.zeroRate(underlyingFx.PaymentDate); double rateCounter = counterDiscountFactors.zeroRate(underlyingFx.PaymentDate); double costOfCarry = rateCounter - rateBase; double dfBase = baseDiscountFactors.discountFactor(underlyingFx.PaymentDate); double dfCounter = counterDiscountFactors.discountFactor(underlyingFx.PaymentDate); double todayFx = ratesProvider.fxRate(currencyPair); double strike = underlyingOption.Strike; double forward = todayFx * dfBase / dfCounter; double volatility = volatilities.volatility(currencyPair, underlyingOption.Expiry, strike, forward); double timeToExpiry = volatilities.relativeTime(underlyingOption.Expiry); ValueDerivatives valueDerivatives = BARRIER_PRICER.priceAdjoint(todayFx, strike, timeToExpiry, costOfCarry, rateCounter, volatility, underlyingOption.PutCall.Call, barrier); if (!option.Rebate.Present) { return(valueDerivatives); } CurrencyAmount rebate = option.Rebate.get(); ValueDerivatives valueDerivativesRebate = rebate.Currency.Equals(ccyCounter) ? CASH_REBATE_PRICER.priceAdjoint(todayFx, timeToExpiry, costOfCarry, rateCounter, volatility, barrier.inverseKnockType()) : ASSET_REBATE_PRICER.priceAdjoint(todayFx, timeToExpiry, costOfCarry, rateCounter, volatility, barrier.inverseKnockType()); double rebateRate = rebate.Amount / Math.Abs(underlyingFx.BaseCurrencyPayment.Amount); double price = valueDerivatives.Value + rebateRate * valueDerivativesRebate.Value; derivatives[0] = valueDerivatives.getDerivative(0) + rebateRate * valueDerivativesRebate.getDerivative(0); derivatives[1] = valueDerivatives.getDerivative(1); for (int i = 2; i < 7; ++i) { derivatives[i] = valueDerivatives.getDerivative(i) + rebateRate * valueDerivativesRebate.getDerivative(i - 1); } return(ValueDerivatives.of(price, DoubleArray.ofUnsafe(derivatives))); }
/// <summary> /// Calculates the currency exposure of the foreign exchange vanilla option product. /// </summary> /// <param name="option"> the option product </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(ResolvedFxVanillaOption option, RatesProvider ratesProvider, BlackFxOptionSmileVolatilities volatilities) { validate(ratesProvider, volatilities); double timeToExpiry = volatilities.relativeTime(option.Expiry); if (timeToExpiry <= 0d) { return(MultiCurrencyAmount.empty()); } ResolvedFxSingle underlyingFx = option.Underlying; Currency ccyCounter = option.CounterCurrency; double df = ratesProvider.discountFactor(ccyCounter, underlyingFx.PaymentDate); FxRate forward = fxPricer.forwardFxRate(underlyingFx, ratesProvider); CurrencyPair currencyPair = underlyingFx.CurrencyPair; double spot = ratesProvider.fxRate(currencyPair); double forwardRate = forward.fxRate(currencyPair); double fwdRateSpotSensitivity = fxPricer.forwardFxRateSpotSensitivity(option.PutCall.Call ? underlyingFx : underlyingFx.inverse(), ratesProvider); double strikeRate = option.Strike; bool isCall = option.PutCall.Call; SmileDeltaParameters smileAtTime = volatilities.Smile.smileForExpiry(timeToExpiry); double[] strikes = smileAtTime.strike(forwardRate).toArray(); double[] vols = smileAtTime.Volatility.toArray(); double volAtm = vols[1]; double[] x = vannaVolgaWeights(forwardRate, strikeRate, timeToExpiry, volAtm, strikes); double priceFwd = BlackFormulaRepository.price(forwardRate, strikeRate, timeToExpiry, volAtm, isCall); double deltaFwd = BlackFormulaRepository.delta(forwardRate, strikeRate, timeToExpiry, volAtm, isCall); for (int i = 0; i < 3; i += 2) { double priceFwdAtm = BlackFormulaRepository.price(forwardRate, strikes[i], timeToExpiry, volAtm, isCall); double priceFwdSmile = BlackFormulaRepository.price(forwardRate, strikes[i], timeToExpiry, vols[i], isCall); priceFwd += x[i] * (priceFwdSmile - priceFwdAtm); double deltaFwdAtm = BlackFormulaRepository.delta(forwardRate, strikes[i], timeToExpiry, volAtm, isCall); double deltaFwdSmile = BlackFormulaRepository.delta(forwardRate, strikes[i], timeToExpiry, vols[i], isCall); deltaFwd += x[i] * (deltaFwdSmile - deltaFwdAtm); } double price = df * priceFwd; double delta = df * deltaFwd * fwdRateSpotSensitivity; double signedNotional = this.signedNotional(option); CurrencyAmount domestic = CurrencyAmount.of(currencyPair.Counter, (price - delta * spot) * signedNotional); CurrencyAmount foreign = CurrencyAmount.of(currencyPair.Base, delta * signedNotional); return(MultiCurrencyAmount.of(domestic, foreign)); }
//------------------------------------------------------------------------- /// <summary> /// Computes the par rate for swaps with a fixed leg. /// <para> /// The par rate is the common rate on all payments of the fixed leg for which the total swap present value is 0. /// </para> /// <para> /// At least one leg must be a fixed leg. The par rate will be computed with respect to the first fixed leg /// in which all the payments are fixed payments with a unique accrual period (no compounding) and no FX reset. /// If the fixed leg is compounding, the par rate is computed only when the number of fixed coupon payments is 1 and /// accrual factor of each sub-period is 1 /// /// </para> /// </summary> /// <param name="swap"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the par rate </returns> public virtual double parRate(ResolvedSwap swap, RatesProvider provider) { // find fixed leg ResolvedSwapLeg fixedLeg = this.fixedLeg(swap); Currency ccyFixedLeg = fixedLeg.Currency; // other payments (not fixed leg coupons) converted in fixed leg currency double otherLegsConvertedPv = 0.0; foreach (ResolvedSwapLeg leg in swap.Legs) { if (leg != fixedLeg) { double pvLocal = legPricer.presentValueInternal(leg, provider); otherLegsConvertedPv += (pvLocal * provider.fxRate(leg.Currency, ccyFixedLeg)); } } double fixedLegEventsPv = legPricer.presentValueEventsInternal(fixedLeg, provider); if (fixedLeg.PaymentPeriods.size() > 1) { // try multiperiod par-rate // PVBP double pvbpFixedLeg = legPricer.pvbp(fixedLeg, provider); // Par rate return(-(otherLegsConvertedPv + fixedLegEventsPv) / pvbpFixedLeg); } SwapPaymentPeriod firstPeriod = fixedLeg.PaymentPeriods.get(0); ArgChecker.isTrue(firstPeriod is RatePaymentPeriod, "PaymentPeriod must be instance of RatePaymentPeriod"); RatePaymentPeriod payment = (RatePaymentPeriod)firstPeriod; if (payment.AccrualPeriods.size() == 1) { // no compounding // PVBP double pvbpFixedLeg = legPricer.pvbp(fixedLeg, provider); // Par rate return(-(otherLegsConvertedPv + fixedLegEventsPv) / pvbpFixedLeg); } // try Compounding Triple <bool, int, double> fixedCompounded = checkFixedCompounded(fixedLeg); ArgChecker.isTrue(fixedCompounded.First, "Swap should have a fixed leg and for one payment it should be based on compunding witout spread."); double notional = payment.Notional; double df = provider.discountFactor(ccyFixedLeg, payment.PaymentDate); return(Math.Pow(-(otherLegsConvertedPv + fixedLegEventsPv) / (notional * df) + 1.0d, 1.0 / fixedCompounded.Second) - 1.0d); }
//------------------------------------------------------------------------- /// <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. This is also called Black vega. /// /// </para> /// </summary> /// <param name="option"> the option product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the Black volatility provider </param> /// <returns> the present value sensitivity </returns> public virtual PointSensitivityBuilder presentValueSensitivityModelParamsVolatility(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { ResolvedFxVanillaOption underlyingOption = option.UnderlyingOption; if (volatilities.relativeTime(underlyingOption.Expiry) <= 0d) { return(PointSensitivityBuilder.none()); } ValueDerivatives priceDerivatives = this.priceDerivatives(option, ratesProvider, volatilities); ResolvedFxSingle underlyingFx = underlyingOption.Underlying; CurrencyPair currencyPair = underlyingFx.CurrencyPair; Currency ccyBase = currencyPair.Base; Currency ccyCounter = currencyPair.Counter; double dfBase = ratesProvider.discountFactor(ccyBase, underlyingFx.PaymentDate); double dfCounter = ratesProvider.discountFactor(ccyCounter, underlyingFx.PaymentDate); double todayFx = ratesProvider.fxRate(currencyPair); double forward = todayFx * dfBase / dfCounter; return(FxOptionSensitivity.of(volatilities.Name, currencyPair, volatilities.relativeTime(underlyingOption.Expiry), underlyingOption.Strike, forward, ccyCounter, priceDerivatives.getDerivative(4) * signedNotional(underlyingOption))); }
/// <summary> /// Calculates the price of the FX barrier option product. /// <para> /// The price of the product is the value on the valuation date for one unit of the base currency /// and is expressed in the counter currency. The price does not take into account the long/short flag. /// See <seealso cref="#presentValue"/> for scaling and currency. /// </para> /// <para> /// The volatility used in this computation is the Black implied volatility at expiry time and strike. /// /// </para> /// </summary> /// <param name="option"> the option product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="volatilities"> the Black volatility provider </param> /// <returns> the price of the product </returns> public virtual double price(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities) { validate(option, ratesProvider, volatilities); SimpleConstantContinuousBarrier barrier = (SimpleConstantContinuousBarrier)option.Barrier; ResolvedFxVanillaOption underlyingOption = option.UnderlyingOption; if (volatilities.relativeTime(underlyingOption.Expiry) < 0d) { return(0d); } ResolvedFxSingle underlyingFx = underlyingOption.Underlying; Currency ccyBase = underlyingFx.BaseCurrencyPayment.Currency; Currency ccyCounter = underlyingFx.CounterCurrencyPayment.Currency; CurrencyPair currencyPair = underlyingFx.CurrencyPair; DiscountFactors baseDiscountFactors = ratesProvider.discountFactors(ccyBase); DiscountFactors counterDiscountFactors = ratesProvider.discountFactors(ccyCounter); double rateBase = baseDiscountFactors.zeroRate(underlyingFx.PaymentDate); double rateCounter = counterDiscountFactors.zeroRate(underlyingFx.PaymentDate); double costOfCarry = rateCounter - rateBase; double dfBase = baseDiscountFactors.discountFactor(underlyingFx.PaymentDate); double dfCounter = counterDiscountFactors.discountFactor(underlyingFx.PaymentDate); double todayFx = ratesProvider.fxRate(currencyPair); double strike = underlyingOption.Strike; double forward = todayFx * dfBase / dfCounter; double volatility = volatilities.volatility(currencyPair, underlyingOption.Expiry, strike, forward); double timeToExpiry = volatilities.relativeTime(underlyingOption.Expiry); double price = BARRIER_PRICER.price(todayFx, strike, timeToExpiry, costOfCarry, rateCounter, volatility, underlyingOption.PutCall.Call, barrier); if (option.Rebate.Present) { CurrencyAmount rebate = option.Rebate.get(); double priceRebate = rebate.Currency.Equals(ccyCounter) ? CASH_REBATE_PRICER.price(todayFx, timeToExpiry, costOfCarry, rateCounter, volatility, barrier.inverseKnockType()) : ASSET_REBATE_PRICER.price(todayFx, timeToExpiry, costOfCarry, rateCounter, volatility, barrier.inverseKnockType()); price += priceRebate * rebate.Amount / Math.Abs(underlyingFx.BaseCurrencyPayment.Amount); } return(price); }
/// <summary> /// Calculates the par rate curve sensitivity for a swap with a fixed leg. /// <para> /// The par rate is the common rate on all payments of the fixed leg for which the total swap present value is 0. /// </para> /// <para> /// At least one leg must be a fixed leg. The par rate will be computed with respect to the first fixed leg. /// All the payments in that leg should be fixed payments with a unique accrual period (no compounding) and no FX reset. /// /// </para> /// </summary> /// <param name="swap"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the par rate curve sensitivity of the swap product </returns> public virtual PointSensitivityBuilder parRateSensitivity(ResolvedSwap swap, RatesProvider provider) { ResolvedSwapLeg fixedLeg = this.fixedLeg(swap); Currency ccyFixedLeg = fixedLeg.Currency; // other payments (not fixed leg coupons) converted in fixed leg currency double otherLegsConvertedPv = 0.0; foreach (ResolvedSwapLeg leg in swap.Legs) { if (leg != fixedLeg) { double pvLocal = legPricer.presentValueInternal(leg, provider); otherLegsConvertedPv += (pvLocal * provider.fxRate(leg.Currency, ccyFixedLeg)); } } double fixedLegEventsPv = legPricer.presentValueEventsInternal(fixedLeg, provider); double pvbpFixedLeg = legPricer.pvbp(fixedLeg, provider); // Backward sweep double otherLegsConvertedPvBar = -1.0d / pvbpFixedLeg; double fixedLegEventsPvBar = -1.0d / pvbpFixedLeg; double pvbpFixedLegBar = (otherLegsConvertedPv + fixedLegEventsPv) / (pvbpFixedLeg * pvbpFixedLeg); PointSensitivityBuilder pvbpFixedLegDr = legPricer.pvbpSensitivity(fixedLeg, provider); PointSensitivityBuilder fixedLegEventsPvDr = legPricer.presentValueSensitivityEventsInternal(fixedLeg, provider); PointSensitivityBuilder otherLegsConvertedPvDr = PointSensitivityBuilder.none(); foreach (ResolvedSwapLeg leg in swap.Legs) { if (leg != fixedLeg) { PointSensitivityBuilder pvLegDr = legPricer.presentValueSensitivity(leg, provider).multipliedBy(provider.fxRate(leg.Currency, ccyFixedLeg)); otherLegsConvertedPvDr = otherLegsConvertedPvDr.combinedWith(pvLegDr); } } otherLegsConvertedPvDr = otherLegsConvertedPvDr.withCurrency(ccyFixedLeg); return(pvbpFixedLegDr.multipliedBy(pvbpFixedLegBar).combinedWith(fixedLegEventsPvDr.multipliedBy(fixedLegEventsPvBar)).combinedWith(otherLegsConvertedPvDr.multipliedBy(otherLegsConvertedPvBar))); }
/// <summary> /// Constructs the synthetic market data from an existing rates provider and the configuration of the new curves. /// </summary> /// <param name="group"> the curve group definition for the synthetic curves and instruments </param> /// <param name="inputProvider"> the input rates provider </param> /// <param name="refData"> the reference data, used to resolve the trades </param> /// <returns> the market data </returns> public ImmutableMarketData marketData(RatesCurveGroupDefinition group, RatesProvider inputProvider, ReferenceData refData) { // Retrieve the set of required indices and the list of required currencies ISet <Index> indicesRequired = new HashSet <Index>(); IList <Currency> ccyRequired = new List <Currency>(); foreach (RatesCurveGroupEntry entry in group.Entries) { indicesRequired.addAll(entry.Indices); ((IList <Currency>)ccyRequired).AddRange(entry.DiscountCurrencies); } // Retrieve the required time series if present in the original provider IDictionary <IndexQuoteId, LocalDateDoubleTimeSeries> ts = new Dictionary <IndexQuoteId, LocalDateDoubleTimeSeries>(); foreach (Index idx in Sets.intersection(inputProvider.TimeSeriesIndices, indicesRequired)) { ts[IndexQuoteId.of(idx)] = inputProvider.timeSeries(idx); } LocalDate valuationDate = inputProvider.ValuationDate; ImmutableList <CurveDefinition> curveGroups = group.CurveDefinitions; // Create fake market quotes of 0, only to be able to generate trades //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: java.util.Map<com.opengamma.strata.data.MarketDataId<?>, double> mapId0 = new java.util.HashMap<>(); IDictionary <MarketDataId <object>, double> mapId0 = new Dictionary <MarketDataId <object>, double>(); foreach (CurveDefinition entry in curveGroups) { ImmutableList <CurveNode> nodes = entry.Nodes; for (int i = 0; i < nodes.size(); i++) { //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: for (com.opengamma.strata.data.MarketDataId<?> key : nodes.get(i).requirements()) foreach (MarketDataId <object> key in nodes.get(i).requirements()) { mapId0[key] = 0.0d; } } } ImmutableMarketData marketQuotes0 = ImmutableMarketData.of(valuationDate, mapId0); // Generate market quotes from the trades //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: java.util.Map<com.opengamma.strata.data.MarketDataId<?>, Object> mapIdSy = new java.util.HashMap<>(); IDictionary <MarketDataId <object>, object> mapIdSy = new Dictionary <MarketDataId <object>, object>(); foreach (CurveDefinition entry in curveGroups) { ImmutableList <CurveNode> nodes = entry.Nodes; foreach (CurveNode node in nodes) { ResolvedTrade trade = node.resolvedTrade(1d, marketQuotes0, refData); double mq = measures.value(trade, inputProvider); //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: com.opengamma.strata.data.MarketDataId<?> k = node.requirements().iterator().next(); MarketDataId <object> k = node.requirements().GetEnumerator().next(); mapIdSy[k] = mq; } } // Generate quotes for FX pairs. The first currency is arbitrarily selected as starting point. // The crosses are automatically generated by the MarketDataFxRateProvider used in calibration. for (int loopccy = 1; loopccy < ccyRequired.Count; loopccy++) { CurrencyPair ccyPair = CurrencyPair.of(ccyRequired[0], ccyRequired[loopccy]); FxRateId fxId = FxRateId.of(ccyPair); mapIdSy[fxId] = FxRate.of(ccyPair, inputProvider.fxRate(ccyPair)); } return(ImmutableMarketData.builder(valuationDate).addValueMap(mapIdSy).addTimeSeriesMap(ts).build()); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value of the swap leg, converted to the specified currency. /// <para> /// The present value of the leg is the value on the valuation date. /// This is the discounted forecast value. /// The result is converted to the specified currency. /// /// </para> /// </summary> /// <param name="leg"> the leg </param> /// <param name="currency"> the currency to convert to </param> /// <param name="provider"> the rates provider </param> /// <returns> the present value of the swap leg in the specified currency </returns> public virtual CurrencyAmount presentValue(ResolvedSwapLeg leg, Currency currency, RatesProvider provider) { double pv = presentValueInternal(leg, provider); return(CurrencyAmount.of(currency, (pv * provider.fxRate(leg.Currency, currency)))); }
/// <summary> /// Calculates the present value sensitivity of the swap product converted in a given currency. /// <para> /// The present value sensitivity of the product is the sensitivity of the present value to /// the underlying curves. /// /// </para> /// </summary> /// <param name="swap"> the product </param> /// <param name="currency"> the currency to convert to </param> /// <param name="provider"> the rates provider </param> /// <returns> the present value curve sensitivity of the swap product converted in the given currency </returns> public virtual PointSensitivityBuilder presentValueSensitivity(ResolvedSwap swap, Currency currency, RatesProvider provider) { PointSensitivityBuilder builder = PointSensitivityBuilder.none(); foreach (ResolvedSwapLeg leg in swap.Legs) { PointSensitivityBuilder ls = legPricer.presentValueSensitivity(leg, provider); PointSensitivityBuilder lsConverted = ls.withCurrency(currency).multipliedBy(provider.fxRate(leg.Currency, currency)); builder = builder.combinedWith(lsConverted); } return(builder); }