public override Builder set(string propertyName, object newValue) { switch (propertyName.GetHashCode()) { case 1574023291: // securityId this.securityId_Renamed = (SecurityId)newValue; break; case 1585636160: // notional this.notional_Renamed = (double?)newValue.Value; break; case 681469378: // deliveryDate this.deliveryDate_Renamed = (LocalDate)newValue; break; case -1041950404: // lastTradeDate this.lastTradeDate_Renamed = (LocalDate)newValue; break; case 1497421456: // underlyingSwap this.underlyingSwap_Renamed = (ResolvedSwap)newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return(this); }
/// <summary> /// Calculates the present value of the swaption product. /// <para> /// The result is expressed using the currency of the swapion. /// /// </para> /// </summary> /// <param name="swaption"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="hwProvider"> the Hull-White model parameter provider </param> /// <returns> the present value </returns> public virtual CurrencyAmount presentValue(ResolvedSwaption swaption, RatesProvider ratesProvider, HullWhiteOneFactorPiecewiseConstantParametersProvider hwProvider) { validate(swaption, ratesProvider, hwProvider); ResolvedSwap swap = swaption.Underlying; LocalDate expiryDate = swaption.ExpiryDate; if (expiryDate.isBefore(ratesProvider.ValuationDate)) { // Option has expired already return(CurrencyAmount.of(swap.Legs.get(0).Currency, 0d)); } ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, ratesProvider); int nPayments = cashFlowEquiv.PaymentEvents.size(); double[] alpha = new double[nPayments]; double[] discountedCashFlow = new double[nPayments]; for (int loopcf = 0; loopcf < nPayments; loopcf++) { NotionalExchange payment = (NotionalExchange)cashFlowEquiv.PaymentEvents.get(loopcf); LocalDate maturityDate = payment.PaymentDate; alpha[loopcf] = hwProvider.alpha(ratesProvider.ValuationDate, expiryDate, expiryDate, maturityDate); discountedCashFlow[loopcf] = paymentPricer.presentValueAmount(payment.Payment, ratesProvider); } double omega = (swap.getLegs(SwapLegType.FIXED).get(0).PayReceive.Pay ? -1d : 1d); double kappa = computeKappa(hwProvider, discountedCashFlow, alpha, omega); double pv = 0.0; for (int loopcf = 0; loopcf < nPayments; loopcf++) { pv += discountedCashFlow[loopcf] * NORMAL.getCDF(omega * (kappa + alpha[loopcf])); } return(CurrencyAmount.of(cashFlowEquiv.Currency, pv * (swaption.LongShort.Long ? 1d : -1d))); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value sensitivity of the swaption to the rate curves. /// <para> /// The present value sensitivity is computed in a "sticky strike" style, i.e. the sensitivity to the /// curve nodes with the volatility at the swaption strike unchanged. This sensitivity does not include a potential /// change of volatility due to the implicit change of forward rate or moneyness. /// /// </para> /// </summary> /// <param name="swaption"> the swaption </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="swaptionVolatilities"> the volatilities </param> /// <returns> the point sensitivity to the rate curves </returns> public virtual PointSensitivityBuilder presentValueSensitivityRatesStickyStrike(ResolvedSwaption swaption, RatesProvider ratesProvider, SwaptionVolatilities swaptionVolatilities) { validate(swaption, ratesProvider, swaptionVolatilities); double expiry = swaptionVolatilities.relativeTime(swaption.Expiry); ResolvedSwap underlying = swaption.Underlying; ResolvedSwapLeg fixedLeg = this.fixedLeg(underlying); if (expiry < 0d) { // Option has expired already return(PointSensitivityBuilder.none()); } double forward = SwapPricer.parRate(underlying, ratesProvider); double pvbp = SwapPricer.LegPricer.pvbp(fixedLeg, ratesProvider); double strike = SwapPricer.LegPricer.couponEquivalent(fixedLeg, ratesProvider, pvbp); double tenor = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate); double volatility = swaptionVolatilities.volatility(expiry, tenor, strike, forward); PutCall putCall = PutCall.ofPut(fixedLeg.PayReceive.Receive); double price = swaptionVolatilities.price(expiry, tenor, putCall, strike, forward, volatility); double delta = swaptionVolatilities.priceDelta(expiry, tenor, putCall, strike, forward, volatility); // Backward sweep PointSensitivityBuilder pvbpDr = SwapPricer.LegPricer.pvbpSensitivity(fixedLeg, ratesProvider); PointSensitivityBuilder forwardDr = SwapPricer.parRateSensitivity(underlying, ratesProvider); double sign = swaption.LongShort.sign(); return(pvbpDr.multipliedBy(price * sign * Math.Sign(pvbp)).combinedWith(forwardDr.multipliedBy(delta * Math.Abs(pvbp) * sign))); }
public override Builder set(string propertyName, object newValue) { switch (propertyName.GetHashCode()) { case 116685664: // longShort this.longShort_Renamed = (LongShort)newValue; break; case -1937554512: // swaptionSettlement this.swaptionSettlement_Renamed = (SwaptionSettlement)newValue; break; case -1289159373: // expiry this.expiry_Renamed = (ZonedDateTime)newValue; break; case -1770633379: // underlying this.underlying_Renamed = (ResolvedSwap)newValue; break; default: throw new NoSuchElementException("Unknown property: " + propertyName); } return(this); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value sensitivity of the swaption product to the rate curves. /// <para> /// The present value sensitivity is computed in a "sticky model parameter" style, i.e. the sensitivity to the /// curve nodes with the SABR model parameters unchanged. This sensitivity does not include a potential /// re-calibration of the model parameters to the raw market data. /// /// </para> /// </summary> /// <param name="swaption"> the swaption product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="swaptionVolatilities"> the volatilities </param> /// <returns> the point sensitivity to the rate curves </returns> public virtual PointSensitivityBuilder presentValueSensitivityRatesStickyModel(ResolvedSwaption swaption, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities) { validate(swaption, ratesProvider, swaptionVolatilities); ZonedDateTime expiryDateTime = swaption.Expiry; double expiry = swaptionVolatilities.relativeTime(expiryDateTime); ResolvedSwap underlying = swaption.Underlying; ResolvedSwapLeg fixedLeg = this.fixedLeg(underlying); if (expiry < 0d) { // Option has expired already return(PointSensitivityBuilder.none()); } double forward = SwapPricer.parRate(underlying, ratesProvider); double pvbp = SwapPricer.LegPricer.pvbp(fixedLeg, ratesProvider); double strike = SwapPricer.LegPricer.couponEquivalent(fixedLeg, ratesProvider, pvbp); double tenor = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate); double shift = swaptionVolatilities.shift(expiry, tenor); ValueDerivatives volatilityAdj = swaptionVolatilities.volatilityAdjoint(expiry, tenor, strike, forward); bool isCall = fixedLeg.PayReceive.Pay; // Payer at strike is exercise when rate > strike, i.e. call on rate // Backward sweep PointSensitivityBuilder pvbpDr = SwapPricer.LegPricer.pvbpSensitivity(fixedLeg, ratesProvider); PointSensitivityBuilder forwardDr = SwapPricer.parRateSensitivity(underlying, ratesProvider); double shiftedForward = forward + shift; double shiftedStrike = strike + shift; double price = BlackFormulaRepository.price(shiftedForward, shiftedStrike, expiry, volatilityAdj.Value, isCall); double delta = BlackFormulaRepository.delta(shiftedForward, shiftedStrike, expiry, volatilityAdj.Value, isCall); double vega = BlackFormulaRepository.vega(shiftedForward, shiftedStrike, expiry, volatilityAdj.Value); double sign = swaption.LongShort.sign(); return(pvbpDr.multipliedBy(price * sign * Math.Sign(pvbp)).combinedWith(forwardDr.multipliedBy((delta + vega * volatilityAdj.getDerivative(0)) * Math.Abs(pvbp) * sign))); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value sensitivity of the swaption to the rate curves. /// <para> /// The present value sensitivity is computed in a "sticky strike" style, i.e. the sensitivity to the /// curve nodes with the volatility at the swaption strike unchanged. This sensitivity does not include a potential /// change of volatility due to the implicit change of forward rate or moneyness. /// /// </para> /// </summary> /// <param name="swaption"> the swaption </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="swaptionVolatilities"> the volatilities </param> /// <returns> the point sensitivity to the rate curves </returns> public virtual PointSensitivityBuilder presentValueSensitivityRatesStickyStrike(ResolvedSwaption swaption, RatesProvider ratesProvider, SwaptionVolatilities swaptionVolatilities) { validate(swaption, ratesProvider, swaptionVolatilities); double expiry = swaptionVolatilities.relativeTime(swaption.Expiry); ResolvedSwap underlying = swaption.Underlying; ResolvedSwapLeg fixedLeg = this.fixedLeg(underlying); if (expiry < 0d) { // Option has expired already return(PointSensitivityBuilder.none()); } double forward = SwapPricer.parRate(underlying, ratesProvider); ValueDerivatives annuityDerivative = SwapPricer.LegPricer.annuityCashDerivative(fixedLeg, forward); double annuityCash = annuityDerivative.Value; double annuityCashDr = annuityDerivative.getDerivative(0); LocalDate settlementDate = ((CashSwaptionSettlement)swaption.SwaptionSettlement).SettlementDate; double discountSettle = ratesProvider.discountFactor(fixedLeg.Currency, settlementDate); double strike = calculateStrike(fixedLeg); double tenor = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate); double volatility = swaptionVolatilities.volatility(expiry, tenor, strike, forward); PutCall putCall = PutCall.ofPut(fixedLeg.PayReceive.Receive); double price = swaptionVolatilities.price(expiry, tenor, putCall, strike, forward, volatility); double delta = swaptionVolatilities.priceDelta(expiry, tenor, putCall, strike, forward, volatility); // Backward sweep PointSensitivityBuilder forwardSensi = SwapPricer.parRateSensitivity(underlying, ratesProvider); PointSensitivityBuilder discountSettleSensi = ratesProvider.discountFactors(fixedLeg.Currency).zeroRatePointSensitivity(settlementDate); double sign = swaption.LongShort.sign(); return(forwardSensi.multipliedBy(sign * discountSettle * (annuityCash * delta + annuityCashDr * price)).combinedWith(discountSettleSensi.multipliedBy(sign * annuityCash * price))); }
/// <summary> /// Restricted copy constructor. </summary> /// <param name="beanToCopy"> the bean to copy from, not null </param> internal Builder(ResolvedSwaption beanToCopy) { this.longShort_Renamed = beanToCopy.LongShort; this.swaptionSettlement_Renamed = beanToCopy.SwaptionSettlement; this.expiry_Renamed = beanToCopy.Expiry; this.underlying_Renamed = beanToCopy.Underlying; }
/// <summary> /// Calculates the par spread curve sensitivity for a swap. /// <para> /// The par spread is the common spread on all payments of the first leg for which the total swap present value is 0. /// </para> /// <para> /// The par spread is computed with respect to the first leg. For that leg, all the payments have 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 spread curve sensitivity of the swap product </returns> public virtual PointSensitivityBuilder parSpreadSensitivity(ResolvedSwap swap, RatesProvider provider) { ResolvedSwapLeg referenceLeg = swap.Legs.get(0); Currency ccyReferenceLeg = referenceLeg.Currency; double convertedPv = presentValue(swap, ccyReferenceLeg, provider).Amount; PointSensitivityBuilder convertedPvDr = presentValueSensitivity(swap, ccyReferenceLeg, provider); // try one payment compounding, typically for inflation swaps Triple <bool, int, double> fixedCompounded = checkFixedCompounded(referenceLeg); if (fixedCompounded.First) { double df = provider.discountFactor(ccyReferenceLeg, referenceLeg.PaymentPeriods.get(0).PaymentDate); PointSensitivityBuilder dfDr = provider.discountFactors(ccyReferenceLeg).zeroRatePointSensitivity(referenceLeg.PaymentPeriods.get(0).PaymentDate); double referenceConvertedPv = legPricer.presentValue(referenceLeg, provider).Amount; PointSensitivityBuilder referenceConvertedPvDr = legPricer.presentValueSensitivity(referenceLeg, provider); double notional = ((RatePaymentPeriod)referenceLeg.PaymentPeriods.get(0)).Notional; PointSensitivityBuilder dParSpreadDr = convertedPvDr.combinedWith(referenceConvertedPvDr.multipliedBy(-1)).multipliedBy(-1.0d / (df * notional)).combinedWith(dfDr.multipliedBy((convertedPv - referenceConvertedPv) / (df * df * notional))).multipliedBy(1.0d / fixedCompounded.Second * Math.Pow(-(convertedPv - referenceConvertedPv) / (df * notional) + 1.0d, 1.0d / fixedCompounded.Second - 1.0d)); return(dParSpreadDr); } double pvbp = legPricer.pvbp(referenceLeg, provider); // Backward sweep double convertedPvBar = -1d / pvbp; double pvbpBar = convertedPv / (pvbp * pvbp); PointSensitivityBuilder pvbpDr = legPricer.pvbpSensitivity(referenceLeg, provider); return(convertedPvDr.multipliedBy(convertedPvBar).combinedWith(pvbpDr.multipliedBy(pvbpBar))); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value sensitivity to the SABR model parameters of the swaption product. /// <para> /// The sensitivity of the present value to the SABR model parameters, alpha, beta, rho and nu. /// /// </para> /// </summary> /// <param name="swaption"> the swaption product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="swaptionVolatilities"> the volatilities </param> /// <returns> the point sensitivity to the SABR model parameters </returns> public virtual PointSensitivityBuilder presentValueSensitivityModelParamsSabr(ResolvedSwaption swaption, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities) { validate(swaption, ratesProvider, swaptionVolatilities); double expiry = swaptionVolatilities.relativeTime(swaption.Expiry); ResolvedSwap underlying = swaption.Underlying; ResolvedSwapLeg fixedLeg = this.fixedLeg(underlying); double tenor = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate); double shift = swaptionVolatilities.shift(expiry, tenor); double pvbp = SwapPricer.LegPricer.pvbp(fixedLeg, ratesProvider); double strike = SwapPricer.LegPricer.couponEquivalent(fixedLeg, ratesProvider, pvbp); if (expiry < 0d) { // Option has expired already return(PointSensitivityBuilder.none()); } double forward = SwapPricer.parRate(underlying, ratesProvider); double volatility = swaptionVolatilities.volatility(expiry, tenor, strike, forward); DoubleArray derivative = swaptionVolatilities.volatilityAdjoint(expiry, tenor, strike, forward).Derivatives; // Backward sweep double vega = Math.Abs(pvbp) * BlackFormulaRepository.vega(forward + shift, strike + shift, expiry, volatility) * swaption.LongShort.sign(); // sensitivities Currency ccy = fixedLeg.Currency; SwaptionVolatilitiesName name = swaptionVolatilities.Name; return(PointSensitivityBuilder.of(SwaptionSabrSensitivity.of(name, expiry, tenor, ALPHA, ccy, vega * derivative.get(2)), SwaptionSabrSensitivity.of(name, expiry, tenor, BETA, ccy, vega * derivative.get(3)), SwaptionSabrSensitivity.of(name, expiry, tenor, RHO, ccy, vega * derivative.get(4)), SwaptionSabrSensitivity.of(name, expiry, tenor, NU, ccy, vega * derivative.get(5)))); }
/// <summary> /// Restricted copy constructor. </summary> /// <param name="beanToCopy"> the bean to copy from, not null </param> internal Builder(ResolvedDsf beanToCopy) { this.securityId_Renamed = beanToCopy.SecurityId; this.notional_Renamed = beanToCopy.Notional; this.deliveryDate_Renamed = beanToCopy.DeliveryDate; this.lastTradeDate_Renamed = beanToCopy.LastTradeDate; this.underlyingSwap_Renamed = beanToCopy.UnderlyingSwap; }
/// <summary> /// Computes cash flow equivalent of swap. /// <para> /// The swap should be a fix-for-Ibor swap without compounding, and its swap legs /// should not involve {@code PaymentEvent}. /// </para> /// <para> /// The return type is {@code ResolvedSwapLeg} in which individual payments are /// represented in terms of {@code NotionalExchange}. /// /// </para> /// </summary> /// <param name="swap"> the swap product </param> /// <param name="ratesProvider"> the rates provider </param> /// <returns> the cash flow equivalent </returns> public static ResolvedSwapLeg cashFlowEquivalentSwap(ResolvedSwap swap, RatesProvider ratesProvider) { validateSwap(swap); ResolvedSwapLeg cfFixed = cashFlowEquivalentFixedLeg(swap.getLegs(SwapLegType.FIXED).get(0), ratesProvider); ResolvedSwapLeg cfIbor = cashFlowEquivalentIborLeg(swap.getLegs(SwapLegType.IBOR).get(0), ratesProvider); ResolvedSwapLeg leg = ResolvedSwapLeg.builder().paymentEvents(Stream.concat(cfFixed.PaymentEvents.stream(), cfIbor.PaymentEvents.stream()).collect(Collectors.toList())).payReceive(PayReceive.RECEIVE).type(SwapLegType.OTHER).build(); return(leg); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test(dataProvider = "stubOn") public void test_stub_overnight(OvernightIborSwapConvention convention, com.opengamma.strata.basics.date.Tenor tenor) public virtual void test_stub_overnight(OvernightIborSwapConvention convention, Tenor tenor) { LocalDate tradeDate = LocalDate.of(2015, 10, 20); SwapTrade swap = convention.createTrade(tradeDate, tenor, BuySell.BUY, 1, 0.01, REF_DATA); ResolvedSwap swapResolved = swap.Product.resolve(REF_DATA); LocalDate endDate = swapResolved.getLeg(PayReceive.PAY).get().EndDate; assertTrue(endDate.isAfter(tradeDate.plus(tenor).minusDays(7))); assertTrue(endDate.isBefore(tradeDate.plus(tenor).plusDays(7))); }
//------------------------------------------------------------------------- // checking that at least one leg is a fixed leg and returning the first one private ResolvedSwapLeg fixedLeg(ResolvedSwap swap) { IList <ResolvedSwapLeg> fixedLegs = swap.getLegs(SwapLegType.FIXED); if (fixedLegs.Count == 0) { throw new System.ArgumentException("Swap must contain a fixed leg"); } return(fixedLegs[0]); }
/// <summary> /// Calculates the current cash of the swap product. /// </summary> /// <param name="swap"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the current cash of the swap product </returns> public virtual MultiCurrencyAmount currentCash(ResolvedSwap swap, RatesProvider provider) { MultiCurrencyAmount ce = MultiCurrencyAmount.empty(); foreach (ResolvedSwapLeg leg in swap.Legs) { ce = ce.plus(legPricer.currentCash(leg, provider)); } return(ce); }
// calculate present or forecast value sensitivity for the swap private static PointSensitivityBuilder swapValueSensitivity(ResolvedSwap swap, RatesProvider provider, System.Func <ResolvedSwapLeg, RatesProvider, PointSensitivityBuilder> legFn) { PointSensitivityBuilder builder = PointSensitivityBuilder.none(); foreach (ResolvedSwapLeg leg in swap.Legs) { builder = builder.combinedWith(legFn(leg, provider)); } return(builder); }
//------------------------------------------------------------------------- /// <summary> /// Calculates the accrued interest since the last payment. /// <para> /// This determines the payment period applicable at the valuation date and calculates /// the accrued interest since the last payment. /// /// </para> /// </summary> /// <param name="swap"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the accrued interest of the swap product </returns> public virtual MultiCurrencyAmount accruedInterest(ResolvedSwap swap, RatesProvider provider) { MultiCurrencyAmount result = MultiCurrencyAmount.empty(); foreach (ResolvedSwapLeg leg in swap.Legs) { result = result.plus(legPricer.accruedInterest(leg, provider)); } return(result); }
//------------------------------------------------------------------------- /// <summary> /// Computes the present value curve sensitivity by simple forward rate estimation. /// </summary> /// <param name="cmsPeriod"> the CMS </param> /// <param name="provider"> the rates provider </param> /// <returns> the present value sensitivity </returns> public virtual PointSensitivityBuilder presentValueSensitivity(CmsPeriod cmsPeriod, RatesProvider provider) { Currency ccy = cmsPeriod.Currency; LocalDate valuationDate = provider.ValuationDate; if (valuationDate.isAfter(cmsPeriod.PaymentDate)) { return(PointSensitivityBuilder.none()); } LocalDate fixingDate = cmsPeriod.FixingDate; double dfPayment = provider.discountFactor(ccy, cmsPeriod.PaymentDate); if (!fixingDate.isAfter(valuationDate)) { // Using fixing double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate); if (fixedRate.HasValue) { double payoff = 0d; switch (cmsPeriod.CmsPeriodType) { case CAPLET: payoff = Math.Max(fixedRate.Value - cmsPeriod.Strike, 0d); break; case FLOORLET: payoff = Math.Max(cmsPeriod.Strike - fixedRate.Value, 0d); break; case COUPON: payoff = fixedRate.Value; break; default: throw new System.ArgumentException("unsupported CMS type"); } return(provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate).multipliedBy(payoff * cmsPeriod.Notional * cmsPeriod.YearFraction)); } else if (fixingDate.isBefore(valuationDate)) { throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate)); } } if (!cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON)) { throw new System.ArgumentException("Unable to price cap or floor in this pricer"); } // Using forward ResolvedSwap swap = cmsPeriod.UnderlyingSwap; ZeroRateSensitivity dfPaymentdr = provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate); double forward = swapPricer.parRate(swap, provider); PointSensitivityBuilder forwardSensi = swapPricer.parRateSensitivity(swap, provider); return(forwardSensi.multipliedBy(dfPayment).combinedWith(dfPaymentdr.multipliedBy(forward)).multipliedBy(cmsPeriod.Notional * cmsPeriod.YearFraction)); }
//------------------------------------------------------------------------- /// <summary> /// Explains the present value of the swap product. /// <para> /// This returns explanatory information about the calculation. /// /// </para> /// </summary> /// <param name="swap"> the product </param> /// <param name="provider"> the rates provider </param> /// <returns> the explanatory information </returns> public virtual ExplainMap explainPresentValue(ResolvedSwap swap, RatesProvider provider) { ExplainMapBuilder builder = ExplainMap.builder(); builder.put(ExplainKey.ENTRY_TYPE, "Swap"); foreach (ResolvedSwapLeg leg in swap.Legs) { builder.addListEntryWithIndex(ExplainKey.LEGS, child => legPricer.explainPresentValueInternal(leg, provider, child)); } return(builder.build()); }
//------------------------------------------------------------------------- /// <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)); }
private ResolvedSwaption(LongShort longShort, SwaptionSettlement swaptionSettlement, ZonedDateTime expiry, ResolvedSwap underlying) { JodaBeanUtils.notNull(longShort, "longShort"); JodaBeanUtils.notNull(swaptionSettlement, "swaptionSettlement"); JodaBeanUtils.notNull(expiry, "expiry"); JodaBeanUtils.notNull(underlying, "underlying"); this.longShort = longShort; this.swaptionSettlement = swaptionSettlement; this.expiry = expiry; this.underlying = underlying; }
/// <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); }
/// <summary> /// Checks that there is exactly one fixed leg and returns it. /// </summary> /// <param name="swap"> the swap </param> /// <returns> the fixed leg </returns> protected internal virtual ResolvedSwapLeg fixedLeg(ResolvedSwap swap) { ArgChecker.isFalse(swap.CrossCurrency, "Swap must be single currency"); // find fixed leg IList <ResolvedSwapLeg> fixedLegs = swap.getLegs(SwapLegType.FIXED); if (fixedLegs.Count == 0) { throw new System.ArgumentException("Swap must contain a fixed leg"); } return(fixedLegs[0]); }
/// <summary> /// Computes the forward rate associated to the swap underlying the CMS period. /// <para> /// Returns a value only if the period has not fixed yet. If the fixing date is on or before the valuation date, /// an <seealso cref="IllegalArgumentException"/> is thrown. /// /// </para> /// </summary> /// <param name="cmsPeriod"> the CMS </param> /// <param name="provider"> the rates provider </param> /// <returns> the forward rate </returns> public virtual double forwardRate(CmsPeriod cmsPeriod, RatesProvider provider) { LocalDate fixingDate = cmsPeriod.FixingDate; LocalDate valuationDate = provider.ValuationDate; if (!fixingDate.isAfter(valuationDate)) { // Using fixing throw new System.ArgumentException("Forward rate is availaible only for valuation date after the fixing date"); } ResolvedSwap swap = cmsPeriod.UnderlyingSwap; return(swapPricer.parRate(swap, provider)); }
//------------------------------------------------------------------------- /// <summary> /// Computes the implied volatility of the swaption. /// </summary> /// <param name="swaption"> the swaption </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="swaptionVolatilities"> the volatilities </param> /// <returns> the implied volatility associated with the swaption </returns> public virtual double impliedVolatility(ResolvedSwaption swaption, RatesProvider ratesProvider, SwaptionVolatilities swaptionVolatilities) { validate(swaption, ratesProvider, swaptionVolatilities); double expiry = swaptionVolatilities.relativeTime(swaption.Expiry); ResolvedSwap underlying = swaption.Underlying; ResolvedSwapLeg fixedLeg = this.fixedLeg(underlying); ArgChecker.isTrue(expiry >= 0d, "Option must be before expiry to compute an implied volatility"); double forward = SwapPricer.parRate(underlying, ratesProvider); double strike = calculateStrike(fixedLeg); double tenor = swaptionVolatilities.tenor(fixedLeg.StartDate, fixedLeg.EndDate); return(swaptionVolatilities.volatility(expiry, tenor, strike, forward)); }
/// <summary> /// Creates an instance. </summary> /// <param name="securityId"> the value of the property, not null </param> /// <param name="notional"> the value of the property </param> /// <param name="deliveryDate"> the value of the property, not null </param> /// <param name="lastTradeDate"> the value of the property, not null </param> /// <param name="underlyingSwap"> the value of the property, not null </param> internal ResolvedDsf(SecurityId securityId, double notional, LocalDate deliveryDate, LocalDate lastTradeDate, ResolvedSwap underlyingSwap) { JodaBeanUtils.notNull(securityId, "securityId"); ArgChecker.notNegativeOrZero(notional, "notional"); JodaBeanUtils.notNull(deliveryDate, "deliveryDate"); JodaBeanUtils.notNull(lastTradeDate, "lastTradeDate"); JodaBeanUtils.notNull(underlyingSwap, "underlyingSwap"); this.securityId = securityId; this.notional = notional; this.deliveryDate = deliveryDate; this.lastTradeDate = lastTradeDate; this.underlyingSwap = underlyingSwap; validate(); }
private void calibration_market_quote_sensitivity_check(System.Func <MarketData, RatesProvider> calibrator, double shift) { double notional = 100_000_000.0; double spread = 0.0050; SwapTrade trade = IborIborSwapConventions.USD_LIBOR_3M_LIBOR_6M.createTrade(VAL_DATE, Period.ofMonths(8), Tenor.TENOR_7Y, BuySell.BUY, notional, spread, REF_DATA); RatesProvider result = calibrator(ALL_QUOTES); ResolvedSwap product = trade.Product.resolve(REF_DATA); PointSensitivityBuilder pts = SWAP_PRICER.presentValueSensitivity(product, result); CurrencyParameterSensitivities ps = result.parameterSensitivity(pts.build()); CurrencyParameterSensitivities mqs = MQC.sensitivity(ps, result); double pv0 = SWAP_PRICER.presentValue(product, result).getAmount(USD).Amount; double[] mqsDscComputed = mqs.getSensitivity(DSCON_CURVE_NAME, USD).Sensitivity.toArray(); for (int i = 0; i < DSC_NB_NODES; i++) { //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> map = new java.util.HashMap<>(ALL_QUOTES.getValues()); IDictionary <MarketDataId <object>, object> map = new Dictionary <MarketDataId <object>, object>(ALL_QUOTES.Values); map[QuoteId.of(StandardId.of(SCHEME, DSC_ID_VALUE[i]))] = DSC_MARKET_QUOTES[i] + shift; ImmutableMarketData marketData = ImmutableMarketData.of(VAL_DATE, map); RatesProvider rpShifted = calibrator(marketData); double pvS = SWAP_PRICER.presentValue(product, rpShifted).getAmount(USD).Amount; assertEquals(mqsDscComputed[i], (pvS - pv0) / shift, TOLERANCE_PV_DELTA, "DSC - node " + i); } double[] mqsFwd3Computed = mqs.getSensitivity(FWD3_CURVE_NAME, USD).Sensitivity.toArray(); for (int i = 0; i < FWD3_NB_NODES; i++) { //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> map = new java.util.HashMap<>(ALL_QUOTES.getValues()); IDictionary <MarketDataId <object>, object> map = new Dictionary <MarketDataId <object>, object>(ALL_QUOTES.Values); map[QuoteId.of(StandardId.of(SCHEME, FWD3_ID_VALUE[i]))] = FWD3_MARKET_QUOTES[i] + shift; ImmutableMarketData marketData = ImmutableMarketData.of(VAL_DATE, map); RatesProvider rpShifted = calibrator(marketData); double pvS = SWAP_PRICER.presentValue(product, rpShifted).getAmount(USD).Amount; assertEquals(mqsFwd3Computed[i], (pvS - pv0) / shift, TOLERANCE_PV_DELTA, "FWD3 - node " + i); } double[] mqsFwd6Computed = mqs.getSensitivity(FWD6_CURVE_NAME, USD).Sensitivity.toArray(); for (int i = 0; i < FWD6_NB_NODES; i++) { //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> map = new java.util.HashMap<>(ALL_QUOTES.getValues()); IDictionary <MarketDataId <object>, object> map = new Dictionary <MarketDataId <object>, object>(ALL_QUOTES.Values); map[QuoteId.of(StandardId.of(SCHEME, FWD6_ID_VALUE[i]))] = FWD6_MARKET_QUOTES[i] + shift; ImmutableMarketData marketData = ImmutableMarketData.of(VAL_DATE, map); RatesProvider rpShifted = calibrator(marketData); double pvS = SWAP_PRICER.presentValue(product, rpShifted).getAmount(USD).Amount; assertEquals(mqsFwd6Computed[i], (pvS - pv0) / shift, TOLERANCE_PV_DELTA, "FWD6 - node " + i); } }
//------------------------------------------------------------------------- /// <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); }
//------------------------------------------------------------------------- // calculate present or forecast value for the swap private static MultiCurrencyAmount swapValue(RatesProvider provider, ResolvedSwap swap, System.Func <ResolvedSwapLeg, RatesProvider, double> legFn) { if (swap.CrossCurrency) { //JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter: return(swap.Legs.Select(leg => CurrencyAmount.of(leg.Currency, legFn(leg, provider))).collect(toMultiCurrencyAmount())); } else { Currency currency = swap.Legs.GetEnumerator().next().Currency; double total = 0d; foreach (ResolvedSwapLeg leg in swap.Legs) { total += legFn(leg, provider); } return(MultiCurrencyAmount.of(currency, total)); } }
//------------------------------------------------------------------------- /// <summary> /// Calculates the present value sensitivity to piecewise constant volatility parameters of the Hull-White model. /// </summary> /// <param name="swaption"> the product </param> /// <param name="ratesProvider"> the rates provider </param> /// <param name="hwProvider"> the Hull-White model parameter provider </param> /// <returns> the present value Hull-White model parameter sensitivity of the swaption product </returns> public virtual DoubleArray presentValueSensitivityModelParamsHullWhite(ResolvedSwaption swaption, RatesProvider ratesProvider, HullWhiteOneFactorPiecewiseConstantParametersProvider hwProvider) { validate(swaption, ratesProvider, hwProvider); ResolvedSwap swap = swaption.Underlying; LocalDate expiryDate = swaption.ExpiryDate; if (expiryDate.isBefore(ratesProvider.ValuationDate)) { // Option has expired already return(DoubleArray.EMPTY); } ResolvedSwapLeg cashFlowEquiv = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, ratesProvider); int nPayments = cashFlowEquiv.PaymentEvents.size(); double[] alpha = new double[nPayments]; double[][] alphaAdjoint = new double[nPayments][]; double[] discountedCashFlow = new double[nPayments]; for (int loopcf = 0; loopcf < nPayments; loopcf++) { NotionalExchange payment = (NotionalExchange)cashFlowEquiv.PaymentEvents.get(loopcf); ValueDerivatives valueDeriv = hwProvider.alphaAdjoint(ratesProvider.ValuationDate, expiryDate, expiryDate, payment.PaymentDate); alpha[loopcf] = valueDeriv.Value; alphaAdjoint[loopcf] = valueDeriv.Derivatives.toArray(); discountedCashFlow[loopcf] = paymentPricer.presentValueAmount(payment.Payment, ratesProvider); } double omega = (swap.getLegs(SwapLegType.FIXED).get(0).PayReceive.Pay ? -1d : 1d); double kappa = computeKappa(hwProvider, discountedCashFlow, alpha, omega); int nParams = alphaAdjoint[0].Length; if (Math.Abs(kappa) > 1d / SMALL) { // decays exponentially return(DoubleArray.filled(nParams)); } double[] pvSensi = new double[nParams]; double sign = (swaption.LongShort.Long ? 1d : -1d); for (int i = 0; i < nParams; ++i) { for (int loopcf = 0; loopcf < nPayments; loopcf++) { pvSensi[i] += sign * discountedCashFlow[loopcf] * NORMAL.getPDF(omega * (kappa + alpha[loopcf])) * omega * alphaAdjoint[loopcf][i]; } } return(DoubleArray.ofUnsafe(pvSensi)); }
// semi-parallel gamma PV01 for one scenario private CurrencyParameterSensitivities pv01SemiParallelGammaBucketed(ResolvedSwapTrade trade, RatesMarketData marketData) { // find the curve identifiers and resolve to a single curve ResolvedSwap product = trade.Product; if (product.CrossCurrency) { throw new System.ArgumentException("Implementation only supports a single curve, but swap is cross-currency"); } Currency currency = product.Legs.get(0).Currency; ISet <Index> indices = product.allIndices(); //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: com.google.common.collect.ImmutableSet<com.opengamma.strata.data.MarketDataId<?>> discountIds = marketData.getLookup().getDiscountMarketDataIds(currency); ImmutableSet <MarketDataId <object> > discountIds = marketData.Lookup.getDiscountMarketDataIds(currency); //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: com.google.common.collect.ImmutableSet<com.opengamma.strata.data.MarketDataId<?>> forwardIds = indices.stream().flatMap(idx -> marketData.getLookup().getForwardMarketDataIds(idx).stream()).collect(toImmutableSet()); ImmutableSet <MarketDataId <object> > forwardIds = indices.stream().flatMap(idx => marketData.Lookup.getForwardMarketDataIds(idx).stream()).collect(toImmutableSet()); //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: java.util.Set<com.opengamma.strata.data.MarketDataId<?>> allIds = com.google.common.collect.Sets.union(discountIds, forwardIds); ISet <MarketDataId <object> > allIds = Sets.union(discountIds, forwardIds); if (allIds.Count != 1) { throw new System.ArgumentException(Messages.format("Implementation only supports a single curve, but lookup refers to more than one: {}", allIds)); } //JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET: //ORIGINAL LINE: com.opengamma.strata.data.MarketDataId<?> singleId = allIds.iterator().next(); MarketDataId <object> singleId = allIds.GetEnumerator().next(); if (!(singleId is CurveId)) { //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: throw new System.ArgumentException(Messages.format("Implementation only supports a single curve, but lookup does not refer to a curve: {} {}", singleId.GetType().FullName, singleId)); } CurveId curveId = (CurveId)singleId; Curve curve = marketData.MarketData.getValue(curveId); // calculate gamma CurrencyParameterSensitivity gamma = CurveGammaCalculator.DEFAULT.calculateSemiParallelGamma(curve, currency, c => calculateCurveSensitivity(trade, marketData, curveId, c)); return(CurrencyParameterSensitivities.of(gamma).multipliedBy(ONE_BASIS_POINT * ONE_BASIS_POINT)); }