//-------------------------------------------------------------------------
        /// <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          strike     = calculateStrike(fixedLeg);

            if (expiry < 0d)
            {     // Option has expired already
                return(PointSensitivityBuilder.none());
            }
            double      forward    = SwapPricer.parRate(underlying, ratesProvider);
            double      volatility = swaptionVolatilities.volatility(expiry, tenor, strike, forward);
            double      numeraire  = calculateNumeraire(swaption, fixedLeg, forward, ratesProvider);
            DoubleArray derivative = swaptionVolatilities.volatilityAdjoint(expiry, tenor, strike, forward).Derivatives;
            double      vega       = numeraire * swaption.LongShort.sign() * BlackFormulaRepository.vega(forward + shift, strike + shift, expiry, volatility);
            // 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>
        /// 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);
            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                  shift             = swaptionVolatilities.shift(expiry, tenor);
            ValueDerivatives        volatilityAdj     = swaptionVolatilities.volatilityAdjoint(expiry, tenor, strike, forward);
            bool                    isCall            = fixedLeg.PayReceive.Pay;
            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);
            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 + vega * volatilityAdj.getDerivative(0)) + annuityCashDr * price)).combinedWith(discountSettleSensi.multipliedBy(sign * annuityCash * price)));
        }
        internal static CmsPeriod sutCoupon()
        {
            FixedIborSwapConvention conv = INDEX.Template.Convention;
            ResolvedSwap            swap = conv.toTrade(FIXING, START, END, BuySell.BUY, 1d, 0.01).Product.resolve(REF_DATA);

            return(CmsPeriod.builder().currency(GBP).notional(NOTIONAL).startDate(START).endDate(END).unadjustedStartDate(START_UNADJUSTED).unadjustedEndDate(END_UNADJUSTED).yearFraction(YEAR_FRACTION).paymentDate(PAYMENT).fixingDate(FIXING).dayCount(ACT_360).index(INDEX).underlyingSwap(swap).build());
        }
        internal static CmsPeriod sut2()
        {
            FixedIborSwapConvention conv = INDEX.Template.Convention;
            ResolvedSwap            swap = conv.toTrade(FIXING.plusDays(1), START.plusDays(1), END.plusDays(1), BuySell.BUY, 1d, 1d).Product.resolve(REF_DATA);

            return(CmsPeriod.builder().currency(EUR).notional(NOTIONAL + 1).startDate(START.plusDays(1)).endDate(END.plusDays(1)).unadjustedStartDate(START_UNADJUSTED.plusDays(1)).unadjustedEndDate(END_UNADJUSTED.plusDays(1)).yearFraction(YEAR_FRACTION + 0.01).paymentDate(PAYMENT.plusDays(1)).fixingDate(FIXING.plusDays(1)).floorlet(STRIKE).dayCount(ACT_365F).index(SwapIndices.EUR_EURIBOR_1100_5Y).underlyingSwap(swap).build());
        }
        //-------------------------------------------------------------------------
        public virtual void test_cashFlowEquivalentAndSensitivity()
        {
            ResolvedSwap swap = ResolvedSwap.of(IBOR_LEG, FIXED_LEG);
            ImmutableMap <Payment, PointSensitivityBuilder> computedFull = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap, PROVIDER);
            ImmutableList <Payment> keyComputedFull = computedFull.Keys.asList();
            ImmutableList <PointSensitivityBuilder>         valueComputedFull = computedFull.values().asList();
            ImmutableMap <Payment, PointSensitivityBuilder> computedIborLeg   = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivityIborLeg(IBOR_LEG, PROVIDER);
            ImmutableMap <Payment, PointSensitivityBuilder> computedFixedLeg  = CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivityFixedLeg(FIXED_LEG, PROVIDER);

            assertEquals(computedFixedLeg.Keys.asList(), keyComputedFull.subList(0, 2));
            assertEquals(computedIborLeg.Keys.asList(), keyComputedFull.subList(2, 6));
            assertEquals(computedFixedLeg.values().asList(), valueComputedFull.subList(0, 2));
            assertEquals(computedIborLeg.values().asList(), valueComputedFull.subList(2, 6));

            double eps = 1.0e-7;
            RatesFiniteDifferenceSensitivityCalculator calc = new RatesFiniteDifferenceSensitivityCalculator(eps);
            int size = keyComputedFull.size();

            for (int i = 0; i < size; ++i)
            {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final int index = i;
                int index = i;
                CurrencyParameterSensitivities expected = calc.sensitivity(PROVIDER, p => ((NotionalExchange)CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, p).PaymentEvents.get(index)).PaymentAmount);
                SwapPaymentEvent               @event   = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, PROVIDER).PaymentEvents.get(index);
                PointSensitivityBuilder        point    = computedFull.get(((NotionalExchange)@event).Payment);
                CurrencyParameterSensitivities computed = PROVIDER.parameterSensitivity(point.build());
                assertTrue(computed.equalWithTolerance(expected, eps * NOTIONAL));
            }
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the price of the deliverable swap futures product.
        /// <para>
        /// The price of the product is the price on the valuation date.
        ///
        /// </para>
        /// </summary>
        /// <param name="future">  the future </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the price of the product, in decimal form </returns>
        public double price(ResolvedDsf future, RatesProvider ratesProvider)
        {
            ResolvedSwap   swap     = future.UnderlyingSwap;
            Currency       currency = future.Currency;
            CurrencyAmount pvSwap   = swapPricer.presentValue(swap, currency, ratesProvider);
            double         df       = ratesProvider.discountFactor(currency, future.DeliveryDate);

            return(1d + pvSwap.Amount / df);
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the price sensitivity of the deliverable swap futures product.
        /// <para>
        /// The price sensitivity of the product is the sensitivity of the price to the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="future">  the future </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <returns> the price curve sensitivity of the product </returns>
        public PointSensitivities priceSensitivity(ResolvedDsf future, RatesProvider ratesProvider)
        {
            ResolvedSwap            swap        = future.UnderlyingSwap;
            Currency                currency    = future.Currency;
            double                  pvSwap      = swapPricer.presentValue(swap, currency, ratesProvider).Amount;
            double                  dfInv       = 1d / ratesProvider.discountFactor(currency, future.DeliveryDate);
            PointSensitivityBuilder sensiSwapPv = swapPricer.presentValueSensitivity(swap, ratesProvider).multipliedBy(dfInv);
            PointSensitivityBuilder sensiDf     = ratesProvider.discountFactors(currency).zeroRatePointSensitivity(future.DeliveryDate).multipliedBy(-pvSwap * dfInv * dfInv);

            return(sensiSwapPv.combinedWith(sensiDf).build());
        }
        public virtual void test_cashFlowEquivalent_pv()
        {
            ResolvedSwap                 swap       = ResolvedSwap.of(IBOR_LEG, FIXED_LEG);
            ResolvedSwapLeg              cfe        = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, PROVIDER);
            DiscountingSwapLegPricer     pricerLeg  = DiscountingSwapLegPricer.DEFAULT;
            DiscountingSwapProductPricer pricerSwap = DiscountingSwapProductPricer.DEFAULT;
            CurrencyAmount               pvCfe      = pricerLeg.presentValue(cfe, PROVIDER);
            MultiCurrencyAmount          pvSwap     = pricerSwap.presentValue(swap, PROVIDER);

            assertEquals(pvCfe.Amount, pvSwap.getAmount(GBP).Amount, TOLERANCE_PV);
        }
        public virtual void test_cashFlowEquivalentAndSensitivity_wrongSwap()
        {
            ResolvedSwap swap1 = ResolvedSwap.of(IBOR_LEG, FIXED_LEG, IBOR_LEG);

            assertThrowsIllegalArg(() => CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap1, PROVIDER));
            ResolvedSwap swap2 = ResolvedSwap.of(FIXED_LEG, FIXED_LEG);

            assertThrowsIllegalArg(() => CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap2, PROVIDER));
            ResolvedSwap swap3 = ResolvedSwap.of(FIXED_LEG, CashFlowEquivalentCalculator.cashFlowEquivalentIborLeg(IBOR_LEG, PROVIDER));

            assertThrowsIllegalArg(() => CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap3, PROVIDER));
        }
        public virtual void test_cashFlowEquivalentAndSensitivity_compounding()
        {
            RatePaymentPeriod iborCmp    = RatePaymentPeriod.builder().paymentDate(PAYMENT2).accrualPeriods(IBOR1, IBOR2).dayCount(ACT_365F).currency(GBP).notional(-NOTIONAL).build();
            ResolvedSwapLeg   iborLegCmp = ResolvedSwapLeg.builder().type(IBOR).payReceive(PAY).paymentPeriods(iborCmp).build();
            ResolvedSwap      swap1      = ResolvedSwap.of(iborLegCmp, FIXED_LEG);

            assertThrowsIllegalArg(() => CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap1, PROVIDER));
            RatePaymentPeriod fixedCmp    = RatePaymentPeriod.builder().paymentDate(PAYMENT2).accrualPeriods(FIXED1, FIXED2).dayCount(ACT_365F).currency(GBP).notional(NOTIONAL).build();
            ResolvedSwapLeg   fixedLegCmp = ResolvedSwapLeg.builder().type(FIXED).payReceive(RECEIVE).paymentPeriods(fixedCmp).build();
            ResolvedSwap      swap2       = ResolvedSwap.of(IBOR_LEG, fixedLegCmp);

            assertThrowsIllegalArg(() => CashFlowEquivalentCalculator.cashFlowEquivalentAndSensitivitySwap(swap2, PROVIDER));
        }
        public virtual void test_cashFlowEquivalent()
        {
            ResolvedSwap    swap             = ResolvedSwap.of(IBOR_LEG, FIXED_LEG);
            ResolvedSwapLeg computed         = CashFlowEquivalentCalculator.cashFlowEquivalentSwap(swap, PROVIDER);
            ResolvedSwapLeg computedIborLeg  = CashFlowEquivalentCalculator.cashFlowEquivalentIborLeg(IBOR_LEG, PROVIDER);
            ResolvedSwapLeg computedFixedLeg = CashFlowEquivalentCalculator.cashFlowEquivalentFixedLeg(FIXED_LEG, PROVIDER);

            assertEquals(computedFixedLeg.PaymentEvents, computed.PaymentEvents.subList(0, 2));
            assertEquals(computedIborLeg.PaymentEvents, computed.PaymentEvents.subList(2, 6));

            // expected payments from fixed leg
            NotionalExchange fixedPayment1 = NotionalExchange.of(CurrencyAmount.of(GBP, NOTIONAL * RATE * PAY_YC1), PAYMENT1);
            NotionalExchange fixedPayment2 = NotionalExchange.of(CurrencyAmount.of(GBP, NOTIONAL * RATE * PAY_YC2), PAYMENT2);
            // expected payments from ibor leg
            LocalDate        fixingSTART1       = GBP_LIBOR_3M.calculateEffectiveFromFixing(FIXING1, REF_DATA);
            double           fixedYearFraction1 = GBP_LIBOR_3M.DayCount.relativeYearFraction(fixingSTART1, GBP_LIBOR_3M.calculateMaturityFromEffective(fixingSTART1, REF_DATA));
            double           beta1              = (1d + fixedYearFraction1 * PROVIDER.iborIndexRates(GBP_LIBOR_3M).rate(GBP_LIBOR_3M_COMP1.Observation)) * PROVIDER.discountFactor(GBP, PAYMENT1) / PROVIDER.discountFactor(GBP, fixingSTART1);
            NotionalExchange iborPayment11      = NotionalExchange.of(CurrencyAmount.of(GBP, -NOTIONAL * beta1 * PAY_YC1 / fixedYearFraction1), fixingSTART1);
            NotionalExchange iborPayment12      = NotionalExchange.of(CurrencyAmount.of(GBP, NOTIONAL * PAY_YC1 / fixedYearFraction1), PAYMENT1);
            LocalDate        fixingSTART2       = GBP_LIBOR_3M.calculateEffectiveFromFixing(FIXING2, REF_DATA);
            double           fixedYearFraction2 = GBP_LIBOR_3M.DayCount.relativeYearFraction(fixingSTART2, GBP_LIBOR_3M.calculateMaturityFromEffective(fixingSTART2, REF_DATA));
            double           beta2              = (1d + fixedYearFraction2 * PROVIDER.iborIndexRates(GBP_LIBOR_3M).rate(GBP_LIBOR_3M_COMP2.Observation)) * PROVIDER.discountFactor(GBP, PAYMENT2) / PROVIDER.discountFactor(GBP, fixingSTART2);
            NotionalExchange iborPayment21      = NotionalExchange.of(CurrencyAmount.of(GBP, -NOTIONAL * beta2 * PAY_YC2 / fixedYearFraction2), fixingSTART2);
            NotionalExchange iborPayment22      = NotionalExchange.of(CurrencyAmount.of(GBP, NOTIONAL * PAY_YC2 / fixedYearFraction2), PAYMENT2);

            ResolvedSwapLeg expected = ResolvedSwapLeg.builder().type(OTHER).payReceive(RECEIVE).paymentEvents(fixedPayment1, fixedPayment2, iborPayment11, iborPayment12, iborPayment21, iborPayment22).build();

            double eps = 1.0e-12;

            assertEquals(computed.PaymentEvents.size(), expected.PaymentEvents.size());
            for (int i = 0; i < 6; ++i)
            {
                NotionalExchange payCmp = (NotionalExchange)computed.PaymentEvents.get(i);
                NotionalExchange payExp = (NotionalExchange)expected.PaymentEvents.get(i);
                assertEquals(payCmp.Currency, payExp.Currency);
                assertEquals(payCmp.PaymentDate, payExp.PaymentDate);
                assertTrue(DoubleMath.fuzzyEquals(payCmp.PaymentAmount.Amount, payExp.PaymentAmount.Amount, NOTIONAL * eps));
            }
        }
示例#12
0
        public virtual void test_legInitialNotionalWithoutNotional()
        {
            ResolvedSwapTrade trade = ResolvedSwapTrade.builder().product(ResolvedSwap.of(KNOWN_AMOUNT_SWAP_LEG, KNOWN_AMOUNT_SWAP_LEG)).build();

            assertThrowsIllegalArg(() => SwapMeasureCalculations.DEFAULT.legInitialNotional(trade));
        }