예제 #1
0
        //-------------------------------------------------------------------------
        public virtual void test_combinedWith()
        {
            PointSensitivityBuilder @base = PointSensitivityBuilder.none();
            PointSensitivityBuilder ibor  = DummyPointSensitivity.of(GBP, date(2015, 6, 30), 2.0d);

            assertSame(@base.combinedWith(ibor), ibor);     // returns other
        }
예제 #2
0
        public virtual void test_withCurrency()
        {
            PointSensitivityBuilder @base = PointSensitivityBuilder.none();

            assertSame(@base.withCurrency(GBP), @base);     // no effect
            assertSame(@base.withCurrency(USD), @base);     // no effect
        }
예제 #3
0
        //-------------------------------------------------------------------------
        public virtual void test_cloned()
        {
            PointSensitivityBuilder @base = PointSensitivityBuilder.none();
            PointSensitivityBuilder test  = @base.cloned();

            assertSame(test, @base);
        }
예제 #4
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the Ibor caplet/floorlet 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="period">  the Ibor caplet/floorlet period </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the point sensitivity to the rate curves </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityRatesStickyModel(IborCapletFloorletPeriod period, RatesProvider ratesProvider, SabrIborCapletFloorletVolatilities volatilities)
        {
            Currency currency = period.Currency;

            if (ratesProvider.ValuationDate.isAfter(period.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            double  expiry    = volatilities.relativeTime(period.FixingDateTime);
            PutCall putCall   = period.PutCall;
            double  strike    = period.Strike;
            double  indexRate = ratesProvider.iborIndexRates(period.Index).rate(period.IborRate.Observation);
            PointSensitivityBuilder dfSensi = ratesProvider.discountFactors(currency).zeroRatePointSensitivity(period.PaymentDate);
            double factor = period.Notional * period.YearFraction;

            if (expiry < 0d)
            {     // option expired already, but not yet paid
                double sign   = putCall.Call ? 1d : -1d;
                double payoff = Math.Max(sign * (indexRate - strike), 0d);
                return(dfSensi.multipliedBy(payoff * factor));
            }
            ValueDerivatives        volatilityAdj       = volatilities.volatilityAdjoint(expiry, strike, indexRate);
            PointSensitivityBuilder indexRateSensiSensi = ratesProvider.iborIndexRates(period.Index).ratePointSensitivity(period.IborRate.Observation);
            double df       = ratesProvider.discountFactor(currency, period.PaymentDate);
            double fwdPv    = factor * volatilities.price(expiry, putCall, strike, indexRate, volatilityAdj.Value);
            double fwdDelta = factor * volatilities.priceDelta(expiry, putCall, strike, indexRate, volatilityAdj.Value);
            double fwdVega  = factor * volatilities.priceVega(expiry, putCall, strike, indexRate, volatilityAdj.Value);

            return(dfSensi.multipliedBy(fwdPv).combinedWith(indexRateSensiSensi.multipliedBy(fwdDelta * df + fwdVega * volatilityAdj.getDerivative(0) * df)));
        }
        //-------------------------------------------------------------------------
        /// <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>
        /// 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)));
        }
        //-------------------------------------------------------------------------
        /// <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)));
        }
예제 #9
0
        public virtual void endedTest()
        {
            LocalDate           valuationDate = PRODUCT.ProtectionEndDate.plusDays(1);
            CreditRatesProvider provider      = createCreditRatesProviderSingle(valuationDate, false);
            double price = PRICER.price(PRODUCT, provider, SETTLEMENT_STD, CLEAN, REF_DATA);

            assertEquals(price, 0d);
            CurrencyAmount pv = PRICER.presentValue(PRODUCT, provider, SETTLEMENT_STD, CLEAN, REF_DATA);

            assertEquals(pv, CurrencyAmount.zero(USD));
            assertThrowsIllegalArg(() => PRICER.parSpread(PRODUCT, provider, SETTLEMENT_STD, REF_DATA));
            CurrencyAmount rpv01 = PRICER.rpv01(PRODUCT, provider, SETTLEMENT_STD, CLEAN, REF_DATA);

            assertEquals(rpv01, CurrencyAmount.zero(USD));
            CurrencyAmount recovery01 = PRICER.recovery01(PRODUCT, provider, SETTLEMENT_STD, REF_DATA);

            assertEquals(recovery01, CurrencyAmount.zero(USD));
            PointSensitivityBuilder sensi = PRICER.presentValueSensitivity(PRODUCT, provider, SETTLEMENT_STD, REF_DATA);

            assertEquals(sensi, PointSensitivityBuilder.none());
            PointSensitivityBuilder sensiPrice = PRICER.priceSensitivity(PRODUCT, provider, SETTLEMENT_STD, REF_DATA);

            assertEquals(sensiPrice, PointSensitivityBuilder.none());
            assertThrowsIllegalArg(() => PRICER.parSpreadSensitivity(PRODUCT, provider, SETTLEMENT_STD, REF_DATA));
            JumpToDefault jumpToDefault = PRICER.jumpToDefault(PRODUCT, provider, SETTLEMENT_STD, REF_DATA);

            assertEquals(jumpToDefault, JumpToDefault.of(USD, ImmutableMap.of(INDEX_ID, 0d)));
            CurrencyAmount expectedLoss = PRICER.expectedLoss(PRODUCT, provider);

            assertEquals(expectedLoss, CurrencyAmount.zero(USD));
        }
예제 #10
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value rates sensitivity of the Ibor caplet/floorlet.
        /// <para>
        /// The present value rates sensitivity of the caplet/floorlet is the sensitivity
        /// of the present value to the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="period">  the Ibor caplet/floorlet period </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the present value curve sensitivity </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityRates(IborCapletFloorletPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities)
        {
            validate(volatilities);
            Currency currency = period.Currency;

            if (ratesProvider.ValuationDate.isAfter(period.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            double  expiry    = volatilities.relativeTime(period.FixingDateTime);
            PutCall putCall   = period.PutCall;
            double  strike    = period.Strike;
            double  indexRate = ratesProvider.iborIndexRates(period.Index).rate(period.IborRate.Observation);
            PointSensitivityBuilder dfSensi = ratesProvider.discountFactors(currency).zeroRatePointSensitivity(period.PaymentDate);

            if (expiry < 0d)
            {     // Option has expired already
                double sign   = putCall.Call ? 1d : -1d;
                double payoff = Math.Max(sign * (indexRate - strike), 0d);
                return(dfSensi.multipliedBy(payoff * period.YearFraction * period.Notional));
            }
            PointSensitivityBuilder indexRateSensiSensi = ratesProvider.iborIndexRates(period.Index).ratePointSensitivity(period.IborRate.Observation);
            double volatility = volatilities.volatility(expiry, strike, indexRate);
            double df         = ratesProvider.discountFactor(currency, period.PaymentDate);
            double factor     = period.Notional * period.YearFraction;
            double fwdPv      = factor * volatilities.price(expiry, putCall, strike, indexRate, volatility);
            double fwdDelta   = factor * volatilities.priceDelta(expiry, putCall, strike, indexRate, volatility);

            return(dfSensi.multipliedBy(fwdPv).combinedWith(indexRateSensiSensi.multipliedBy(fwdDelta * df)));
        }
        public virtual void test_presentValueSensitivityRatesStickyStrike_after_expiry()
        {
            PointSensitivityBuilder pointRec = PRICER_SWAPTION.presentValueSensitivityRatesStickyStrike(SWAPTION_REC_LONG_PAST, RATE_PROVIDER, VOLS);
            PointSensitivityBuilder pointPay = PRICER_SWAPTION.presentValueSensitivityRatesStickyStrike(SWAPTION_PAY_SHORT_PAST, RATE_PROVIDER, VOLS);

            assertEquals(pointRec, PointSensitivityBuilder.none());
            assertEquals(pointPay, PointSensitivityBuilder.none());
        }
예제 #12
0
        //-------------------------------------------------------------------------
        public virtual void test_buildInto()
        {
            PointSensitivityBuilder   @base = PointSensitivityBuilder.none();
            MutablePointSensitivities combo = new MutablePointSensitivities();
            MutablePointSensitivities test  = @base.buildInto(combo);

            assertSame(test, combo);
            assertEquals(test.Sensitivities, ImmutableList.of());
        }
예제 #13
0
        // 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);
        }
예제 #14
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the Present Value of a Basis Point curve sensitivity for a fixed swap leg.
        /// <para>
        /// The Present Value of a Basis Point is the value of the leg when the rate is equal to 1.
        /// A better name would be "Present Value of 1".
        /// The quantity is also known as "physical annuity" or "level".
        /// </para>
        /// <para>
        /// Each period must not have FX reset or compounding.
        /// They must not be of type <seealso cref="KnownAmountSwapPaymentPeriod"/>.
        ///
        /// </para>
        /// </summary>
        /// <param name="fixedLeg">  the swap fixed leg </param>
        /// <param name="provider">  the rates provider </param>
        /// <returns> the Present Value of a Basis Point sensitivity to the curves </returns>
        public virtual PointSensitivityBuilder pvbpSensitivity(ResolvedSwapLeg fixedLeg, RatesProvider provider)
        {
            PointSensitivityBuilder builder = PointSensitivityBuilder.none();

            foreach (SwapPaymentPeriod period in fixedLeg.PaymentPeriods)
            {
                builder = builder.combinedWith(paymentPeriodPricer.pvbpSensitivity(period, provider));
            }
            return(builder);
        }
            //  Accumulated rate sensitivity - approximated forward rates if not all fixed and not part of cutoff
            internal PointSensitivityBuilder approximatedForwardAccumulationSensitivity()
            {
                int nbPeriodNotCutOff = nbPeriods - cutoffOffset + 1;

                if (fixedPeriod < nbPeriodNotCutOff)
                {
                    LocalDate endDateApprox = observations[nbPeriodNotCutOff - 1].MaturityDate;
                    return(approximatedInterestSensitivity(observations[fixedPeriod], endDateApprox, rates));
                }
                return(PointSensitivityBuilder.none());
            }
        //-------------------------------------------------------------------------
        /// <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));
        }
        //-------------------------------------------------------------------------
        public PointSensitivityBuilder ratePointSensitivity(IborIndexObservation observation)
        {
            LocalDate fixingDate    = observation.FixingDate;
            LocalDate valuationDate = ValuationDate;

            if (fixingDate.isBefore(valuationDate) || (fixingDate.Equals(valuationDate) && fixings.get(fixingDate).HasValue))
            {
                return(PointSensitivityBuilder.none());
            }
            return(IborRateSensitivity.of(observation, 1d));
        }
        //-------------------------------------------------------------------------
        public PointSensitivityBuilder ratePointSensitivity(FxIndexObservation observation, Currency baseCurrency)
        {
            ArgChecker.isTrue(index.CurrencyPair.contains(baseCurrency), "Currency {} invalid for FxIndex {}", baseCurrency, index);

            LocalDate fixingDate = observation.FixingDate;

            if (fixingDate.isBefore(ValuationDate) || (fixingDate.Equals(ValuationDate) && fixings.get(fixingDate).HasValue))
            {
                return(PointSensitivityBuilder.none());
            }
            return(FxIndexSensitivity.of(observation, baseCurrency, 1d));
        }
예제 #19
0
        /// <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>
        /// 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="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(ResolvedFxVanillaOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities)
        {
            if (volatilities.relativeTime(option.Expiry) <= 0d)
            {
                return(PointSensitivityBuilder.none());
            }
            ResolvedFxSingle underlying = option.Underlying;
            FxRate           forward    = fxPricer.forwardFxRate(underlying, ratesProvider);
            CurrencyPair     strikePair = underlying.CurrencyPair;
            CurrencyAmount   valueVega  = presentValueVega(option, ratesProvider, volatilities);

            return(FxOptionSensitivity.of(volatilities.Name, strikePair, volatilities.relativeTime(option.Expiry), option.Strike, forward.fxRate(strikePair), valueVega.Currency, valueVega.Amount));
        }
예제 #21
0
        // calculates the present value curve sensitivity of the periods composing the leg in the currency of the swap leg
        internal virtual PointSensitivityBuilder presentValueSensitivityPeriodsInternal(ResolvedSwapLeg leg, RatesProvider provider)
        {
            PointSensitivityBuilder builder = PointSensitivityBuilder.none();

            foreach (SwapPaymentPeriod period in leg.PaymentPeriods)
            {
                if (!period.PaymentDate.isBefore(provider.ValuationDate))
                {
                    builder = builder.combinedWith(paymentPeriodPricer.presentValueSensitivity(period, provider));
                }
            }
            return(builder);
        }
            // Accumulated rate sensitivity - cutoff part if not fixed
            internal PointSensitivityBuilder cutOffAccumulationSensitivity()
            {
                PointSensitivityBuilder combinedPointSensitivityBuilder = PointSensitivityBuilder.none();
                int nbPeriodNotCutOff = nbPeriods - cutoffOffset + 1;

                for (int i = Math.Max(fixedPeriod, nbPeriodNotCutOff); i < nbPeriods; i++)
                {
                    OvernightIndexObservation obs = observations[i];
                    PointSensitivityBuilder   forwardRateSensitivity = rates.ratePointSensitivity(obs).multipliedBy(obs.YearFraction);
                    combinedPointSensitivityBuilder = combinedPointSensitivityBuilder.combinedWith(forwardRateSensitivity);
                }
                return(combinedPointSensitivityBuilder);
            }
예제 #23
0
        public virtual void test_presentValueSensitivitySabrParameter_afterPay()
        {
            PointSensitivityBuilder computed = LEG_PRICER.presentValueSensitivityModelParamsSabr(FLOOR_LEG, RATES_PROVIDER_AFTER_PERIOD, VOLATILITIES_AFTER_PERIOD);
            PointSensitivityBuilder expected = PointSensitivityBuilder.none();
            IList <CmsPeriod>       cms      = FLOOR_LEG.CmsPeriods;
            int size = cms.Count;

            for (int i = 0; i < size; ++i)
            {
                expected = expected.combinedWith(PERIOD_PRICER.presentValueSensitivityModelParamsSabr(cms[i], RATES_PROVIDER_AFTER_PERIOD, VOLATILITIES_AFTER_PERIOD));
            }
            assertEquals(computed, expected);
        }
        //-------------------------------------------------------------------------
        public PointSensitivityBuilder valuePointSensitivity(PriceIndexObservation observation)
        {
            YearMonth fixingMonth = observation.FixingMonth;

            // If fixing in the past, check time series and returns the historic month price index if present
            if (fixingMonth.isBefore(YearMonth.from(valuationDate)))
            {
                if (fixings.get(fixingMonth.atEndOfMonth()).HasValue)
                {
                    return(PointSensitivityBuilder.none());
                }
            }
            return(InflationRateSensitivity.of(observation, 1d));
        }
 // Composition - forward part in non-cutoff period; past/valuation date case dealt with in previous methods
 internal ObjDoublePair <PointSensitivityBuilder> compositionFactorAndSensitivityNonCutoff()
 {
     if (!nextFixing.isAfter(lastFixingNonCutoff))
     {
         OvernightIndexObservation obs = computation.observeOn(nextFixing);
         LocalDate startDate           = obs.EffectiveDate;
         LocalDate endDate             = computation.calculateMaturityFromFixing(lastFixingNonCutoff);
         double    accrualFactor       = dayCount.yearFraction(startDate, endDate);
         double    rate = rates.periodRate(obs, endDate);
         PointSensitivityBuilder rateSensitivity = rates.periodRatePointSensitivity(obs, endDate);
         rateSensitivity = rateSensitivity.multipliedBy(accrualFactor);
         return(ObjDoublePair.of(rateSensitivity, 1.0d + accrualFactor * rate));
     }
     return(ObjDoublePair.of(PointSensitivityBuilder.none(), 1.0d));
 }
예제 #26
0
        /// <summary>
        /// Calculates the price sensitivity of the product.
        /// <para>
        /// The price sensitivity of the product is the sensitivity of price to the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="cds">  the product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="referenceDate">  the reference date </param>
        /// <param name="refData">  the reference data </param>
        /// <returns> the present value sensitivity </returns>
        public virtual PointSensitivityBuilder priceSensitivity(ResolvedCds cds, CreditRatesProvider ratesProvider, LocalDate referenceDate, ReferenceData refData)
        {
            if (isExpired(cds, ratesProvider))
            {
                return(PointSensitivityBuilder.none());
            }
            LocalDate stepinDate         = cds.StepinDateOffset.adjust(ratesProvider.ValuationDate, refData);
            LocalDate effectiveStartDate = cds.calculateEffectiveStartDate(stepinDate);
            double    recoveryRate       = this.recoveryRate(cds, ratesProvider);
            Pair <CreditDiscountFactors, LegalEntitySurvivalProbabilities> rates = reduceDiscountFactors(cds, ratesProvider);

            PointSensitivityBuilder protectionLegSensi = protectionLegSensitivity(cds, rates.First, rates.Second, referenceDate, effectiveStartDate, recoveryRate);
            PointSensitivityBuilder riskyAnnuitySensi  = riskyAnnuitySensitivity(cds, rates.First, rates.Second, referenceDate, stepinDate, effectiveStartDate).multipliedBy(-cds.FixedRate);

            return(protectionLegSensi.combinedWith(riskyAnnuitySensi));
        }
        private PointSensitivityBuilder rateForwardSensitivity(OvernightAveragedRateComputation computation, OvernightIndexRates rates)
        {
            OvernightIndex          index                           = computation.Index;
            HolidayCalendar         calendar                        = computation.FixingCalendar;
            LocalDate               startFixingDate                 = computation.StartDate;
            LocalDate               endFixingDateP1                 = computation.EndDate;
            LocalDate               endFixingDate                   = calendar.previous(endFixingDateP1);
            LocalDate               onRateEndDate                   = computation.calculateMaturityFromFixing(endFixingDate);
            LocalDate               onRateStartDate                 = computation.calculateEffectiveFromFixing(startFixingDate);
            LocalDate               lastNonCutOffMatDate            = onRateEndDate;
            int                     cutoffOffset                    = computation.RateCutOffDays > 1 ? computation.RateCutOffDays : 1;
            PointSensitivityBuilder combinedPointSensitivityBuilder = PointSensitivityBuilder.none();
            double                  accrualFactorTotal              = index.DayCount.yearFraction(onRateStartDate, onRateEndDate);

            if (cutoffOffset > 1)
            {     // Cut-off period
                IList <double> noCutOffAccrualFactorList = new List <double>();
                LocalDate      currentFixingDate         = endFixingDateP1;
                LocalDate      cutOffEffectiveDate;
                for (int i = 0; i < cutoffOffset; i++)
                {
                    currentFixingDate    = calendar.previous(currentFixingDate);
                    cutOffEffectiveDate  = computation.calculateEffectiveFromFixing(currentFixingDate);
                    lastNonCutOffMatDate = computation.calculateMaturityFromEffective(cutOffEffectiveDate);
                    double accrualFactor = index.DayCount.yearFraction(cutOffEffectiveDate, lastNonCutOffMatDate);
                    noCutOffAccrualFactorList.Add(accrualFactor);
                }
                OvernightIndexObservation lastIndexObs = computation.observeOn(currentFixingDate);
                PointSensitivityBuilder   forwardRateCutOffSensitivity = rates.ratePointSensitivity(lastIndexObs);
                double totalAccrualFactor = 0.0;
                for (int i = 0; i < cutoffOffset - 1; i++)
                {
                    totalAccrualFactor += noCutOffAccrualFactorList[i];
                }
                forwardRateCutOffSensitivity    = forwardRateCutOffSensitivity.multipliedBy(totalAccrualFactor);
                combinedPointSensitivityBuilder = combinedPointSensitivityBuilder.combinedWith(forwardRateCutOffSensitivity);
            }
            // Approximated part
            OvernightIndexObservation indexObs = computation.observeOn(onRateStartDate);
            PointSensitivityBuilder   approximatedInterestAndSensitivity = approximatedInterestSensitivity(indexObs, lastNonCutOffMatDate, rates);

            combinedPointSensitivityBuilder = combinedPointSensitivityBuilder.combinedWith(approximatedInterestAndSensitivity);
            combinedPointSensitivityBuilder = combinedPointSensitivityBuilder.multipliedBy(1.0 / accrualFactorTotal);
            // final rate
            return(combinedPointSensitivityBuilder);
        }
예제 #28
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value volatility sensitivity of the Ibor caplet/floorlet.
        /// <para>
        /// The present value volatility sensitivity of the caplet/floorlet is the sensitivity
        /// of the present value to the implied volatility.
        /// </para>
        /// <para>
        /// The sensitivity to the implied volatility is also called vega.
        ///
        /// </para>
        /// </summary>
        /// <param name="period">  the Ibor caplet/floorlet period </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the volatilities </param>
        /// <returns> the point sensitivity to the volatility </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityModelParamsVolatility(IborCapletFloorletPeriod period, RatesProvider ratesProvider, IborCapletFloorletVolatilities volatilities)
        {
            validate(volatilities);
            double   expiry   = volatilities.relativeTime(period.FixingDateTime);
            double   strike   = period.Strike;
            Currency currency = period.Currency;

            if (expiry <= 0d)
            {     // Option has expired already or at expiry
                return(PointSensitivityBuilder.none());
            }
            double  forward    = ratesProvider.iborIndexRates(period.Index).rate(period.IborRate.Observation);
            double  volatility = volatilities.volatility(expiry, strike, forward);
            PutCall putCall    = period.PutCall;
            double  df         = ratesProvider.discountFactor(currency, period.PaymentDate);
            double  vega       = df * period.YearFraction * volatilities.priceVega(expiry, putCall, strike, forward, volatility);

            return(IborCapletFloorletSensitivity.of(volatilities.Name, expiry, strike, forward, currency, vega * period.Notional));
        }
        //-------------------------------------------------------------------------
        /// <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 curves.
        /// </para>
        /// <para>
        /// The volatility is fixed in this sensitivity computation, i.e., sticky-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 present value curve sensitivity of the product </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityRatesStickyStrike(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;
            double              signedNotional      = this.signedNotional(underlyingOption);
            double              counterYearFraction = ratesProvider.discountFactors(currencyPair.Counter).relativeYearFraction(underlyingFx.PaymentDate);
            ZeroRateSensitivity counterSensi        = ZeroRateSensitivity.of(currencyPair.Counter, counterYearFraction, signedNotional * (priceDerivatives.getDerivative(2) + priceDerivatives.getDerivative(3)));
            double              baseYearFraction    = ratesProvider.discountFactors(currencyPair.Base).relativeYearFraction(underlyingFx.PaymentDate);
            ZeroRateSensitivity baseSensi           = ZeroRateSensitivity.of(currencyPair.Base, baseYearFraction, currencyPair.Counter, -priceDerivatives.getDerivative(3) * signedNotional);

            return(counterSensi.combinedWith(baseSensi));
        }
예제 #30
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the foreign exchange vanilla option product.
        /// <para>
        /// The present value sensitivity of the product is the sensitivity of <seealso cref="#presentValue"/> to
        /// the underlying curves.
        /// </para>
        /// <para>
        /// The implied strikes and weights are fixed in this sensitivity computation.
        ///
        /// </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 curve sensitivity of the product </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityRatesStickyStrike(ResolvedFxVanillaOption option, RatesProvider ratesProvider, BlackFxOptionSmileVolatilities volatilities)
        {
            validate(ratesProvider, volatilities);
            double timeToExpiry = volatilities.relativeTime(option.Expiry);

            if (timeToExpiry <= 0d)
            {
                return(PointSensitivityBuilder.none());
            }
            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               forwardRate  = forward.fxRate(currencyPair);
            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 signedNotional            = this.signedNotional(option);
            PointSensitivityBuilder dfSensi  = ratesProvider.discountFactors(ccyCounter).zeroRatePointSensitivity(underlyingFx.PaymentDate).multipliedBy(priceFwd * signedNotional);
            PointSensitivityBuilder fwdSensi = fxPricer.forwardFxRatePointSensitivity(option.PutCall.Call ? underlyingFx : underlyingFx.inverse(), ratesProvider).multipliedBy(df * deltaFwd * signedNotional);

            return(dfSensi.combinedWith(fwdSensi));
        }