示例#1
0
 public CmsDeltaIntegrantProvider(SabrExtrapolationReplicationCmsPeriodPricer outerInstance, CmsPeriod cmsPeriod, ResolvedSwap swap, SabrSwaptionVolatilities swaptionVolatilities, double forward, double strike, double timeToExpiry, double tenor, double cutOffStrike, double eta) : base(outerInstance, cmsPeriod, swap, swaptionVolatilities, forward, strike, timeToExpiry, tenor, cutOffStrike, eta)
 {
     this.outerInstance = outerInstance;
     this.nnp_Renamed   = nnp(forward);
 }
示例#2
0
        /// <summary>
        /// Explains the present value of the CMS period.
        /// <para>
        /// This returns explanatory information about the calculation.
        ///
        /// </para>
        /// </summary>
        /// <param name="period">  the product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the volatilities </param>
        /// <param name="builder">  the builder to populate </param>
        public void explainPresentValue(CmsPeriod period, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities, ExplainMapBuilder builder)
        {
            string    type        = period.CmsPeriodType.ToString();
            Currency  ccy         = period.Currency;
            LocalDate paymentDate = period.PaymentDate;

            builder.put(ExplainKey.ENTRY_TYPE, "Cms" + type + "Period");
            builder.put(ExplainKey.STRIKE_VALUE, period.Strike);
            builder.put(ExplainKey.NOTIONAL, CurrencyAmount.of(ccy, period.Notional));
            builder.put(ExplainKey.PAYMENT_DATE, period.PaymentDate);
            builder.put(ExplainKey.DISCOUNT_FACTOR, ratesProvider.discountFactor(ccy, paymentDate));
            builder.put(ExplainKey.START_DATE, period.StartDate);
            builder.put(ExplainKey.END_DATE, period.EndDate);
            builder.put(ExplainKey.FIXING_DATE, period.FixingDate);
            builder.put(ExplainKey.ACCRUAL_YEAR_FRACTION, period.YearFraction);
            builder.put(ExplainKey.PRESENT_VALUE, presentValue(period, ratesProvider, swaptionVolatilities));
            builder.put(ExplainKey.FORWARD_RATE, swapPricer.parRate(period.UnderlyingSwap, ratesProvider));
            builder.put(ExplainKey.CONVEXITY_ADJUSTED_RATE, adjustedForwardRate(period, ratesProvider, swaptionVolatilities));
        }
示例#3
0
            public CmsIntegrantProvider(SabrExtrapolationReplicationCmsPeriodPricer outerInstance, CmsPeriod cmsPeriod, ResolvedSwap swap, SabrSwaptionVolatilities swaptionVolatilities, double forward, double strike, double timeToExpiry, double tenor, double cutOffStrike, double eta)
            {
                this.outerInstance = outerInstance;

                ResolvedSwapLeg fixedLeg = swap.getLegs(SwapLegType.FIXED).get(0);

                this.nbFixedPeriod      = fixedLeg.PaymentPeriods.size();
                this.nbFixedPaymentYear = (int)(long)Math.Round(1d / ((RatePaymentPeriod)fixedLeg.PaymentPeriods.get(0)).AccrualPeriods.get(0).YearFraction, MidpointRounding.AwayFromZero);
                this.tau = 1d / nbFixedPaymentYear;
                this.eta = eta;
                SabrFormulaData sabrPoint = SabrFormulaData.of(swaptionVolatilities.alpha(timeToExpiry, tenor), swaptionVolatilities.beta(timeToExpiry, tenor), swaptionVolatilities.rho(timeToExpiry, tenor), swaptionVolatilities.nu(timeToExpiry, tenor));

                this.shift             = swaptionVolatilities.shift(timeToExpiry, tenor);
                this.sabrExtrapolation = SabrExtrapolationRightFunction.of(forward + shift, timeToExpiry, sabrPoint, cutOffStrike + shift, outerInstance.mu);
                this.putCall           = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.FLOORLET) ? PutCall.PUT : PutCall.CALL;
                this.strike            = strike;
                this.factor            = g(forward) / h(forward);
                this.g0 = new double[4];
                g0[0]   = nbFixedPeriod * tau;
                g0[1]   = -0.5 * nbFixedPeriod * (nbFixedPeriod + 1.0d) * tau * tau;
                g0[2]   = -2.0d / 3.0d * g0[1] * (nbFixedPeriod + 2.0d) * tau;
                g0[3]   = -3.0d / 4.0d * g0[2] * (nbFixedPeriod + 2.0d) * tau;
            }
示例#4
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value curve sensitivity of the CMS product.
        /// <para>
        /// The present value sensitivity of the product is the sensitivity of the present value to the underlying curves.
        ///
        /// </para>
        /// </summary>
        /// <param name="cms">  the CMS product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public virtual PointSensitivityBuilder presentValueSensitivityRates(ResolvedCms cms, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            PointSensitivityBuilder pvSensiCmsLeg = cmsLegPricer.presentValueSensitivityRates(cms.CmsLeg, ratesProvider, swaptionVolatilities);

            if (!cms.PayLeg.Present)
            {
                return(pvSensiCmsLeg);
            }
            PointSensitivityBuilder pvSensiPayLeg = payLegPricer.presentValueSensitivity(cms.PayLeg.get(), ratesProvider);

            return(pvSensiCmsLeg.combinedWith(pvSensiPayLeg));
        }
示例#5
0
        private double integrateCall(RungeKuttaIntegrator1D integrator, System.Func <double, double> integrant, SabrSwaptionVolatilities swaptionVolatilities, double forward, double strike, double expiryTime, double tenor)
        {
            double res;
            double vol    = swaptionVolatilities.volatility(expiryTime, tenor, forward, forward);
            double upper0 = Math.Max(forward * Math.Exp(6d * vol * Math.Sqrt(expiryTime)), Math.Max(cutOffStrike, 2d * strike)); // To ensure that the integral covers a good part of the smile
            double upper  = Math.Min(upper0, 1d);                                                                                // To ensure that we don't miss the meaningful part

            res = integrator.integrate(integrant, strike, upper).Value;
            double reminder = integrant(upper) * upper;
            double error    = reminder / res;
            int    count    = 0;

            while (Math.Abs(error) > integrator.RelativeTolerance && count < MAX_COUNT)
            {
                res     += integrator.integrate(integrant, upper, 2d * upper).Value;
                upper   *= 2d;
                reminder = integrant(upper) * upper;
                error    = reminder / res;
                ++count;
                if (count == MAX_COUNT)
                {
                    log.info("Maximum iteration count, " + MAX_COUNT + ", has been reached. Relative error is greater than " + integrator.RelativeTolerance);
                }
            }
            return(res);
        }
示例#6
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity of the swaption trade 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="trade">  the swaption trade </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 PointSensitivities presentValueSensitivityRatesStickyModel(ResolvedSwaptionTrade trade, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            // product
            ResolvedSwaption        product   = trade.Product;
            PointSensitivityBuilder pointSens = isCash(product) ? cashParYieldPricer.presentValueSensitivityRatesStickyModel(product, ratesProvider, swaptionVolatilities) : physicalPricer.presentValueSensitivityRatesStickyModel(product, ratesProvider, swaptionVolatilities);
            // premium
            Payment premium = trade.Premium;
            PointSensitivityBuilder pvcsPremium = paymentPricer.presentValueSensitivity(premium, ratesProvider);

            // total
            return(pointSens.combinedWith(pvcsPremium).build());
        }
示例#7
0
 //-------------------------------------------------------------------------
 /// <summary>
 /// Computes the currency exposure of the swaption trade.
 /// </summary>
 /// <param name="trade">  the swaption trade </param>
 /// <param name="ratesProvider">  the rates provider </param>
 /// <param name="swaptionVolatilities">  the volatilities </param>
 /// <returns> the currency exposure </returns>
 public virtual MultiCurrencyAmount currencyExposure(ResolvedSwaptionTrade trade, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
 {
     return(MultiCurrencyAmount.of(presentValue(trade, ratesProvider, swaptionVolatilities)));
 }
示例#8
0
        /// <summary>
        /// Computes the adjusted forward rate for a CMS coupon.
        /// <para>
        /// The adjusted forward rate, is the number such that, multiplied by the notional, the year fraction and the payment
        /// date discount factor, it produces the present value. In other terms, it is the number which used in the same
        /// formula used for Ibor coupon pricing will provide the correct present value.
        /// </para>
        /// <para>
        /// For period already fixed, this number will be equal to the swap index fixing.
        /// </para>
        /// <para>
        /// For cap or floor the result is the adjusted forward rate for the coupon equivalent to the cap/floor,
        /// i.e. the coupon with the same dates and index but with no cap or floor strike.
        ///
        /// </para>
        /// </summary>
        /// <param name="cmsPeriod">  the CMS period, which should be of the type <seealso cref="CmsPeriodType#COUPON"/> </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the adjusted forward rate </returns>
        public double adjustedForwardRate(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            CmsPeriod coupon    = cmsPeriod.toCouponEquivalent();
            Currency  ccy       = cmsPeriod.Currency;
            double    dfPayment = provider.discountFactor(ccy, coupon.PaymentDate);
            double    pv        = presentValue(coupon, provider, swaptionVolatilities).Amount;

            return(pv / (coupon.Notional * coupon.YearFraction * dfPayment));
        }
示例#9
0
        /// <summary>
        /// Computes the adjustment to the forward rate for a CMS coupon.
        /// <para>
        /// The adjustment to the forward rate, is the quantity that need to be added to the forward rate to obtain the
        /// adjusted forward rate. The adjusted forward rate is the number which used in the same formula used for
        /// Ibor coupon pricing (forward * notional * accrual factor * discount factor) will provide the correct present value.
        /// </para>
        /// <para>
        /// For cap or floor the result is the adjustment to the forward rate for the coupon equivalent to the cap/floor,
        /// i.e. the coupon with the same dates and index but with no cap or floor strike.
        ///
        /// </para>
        /// </summary>
        /// <param name="cmsPeriod">  the CMS period, which should be of the type <seealso cref="CmsPeriodType#COUPON"/> </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the adjusted forward rate </returns>
        public double adjustmentToForwardRate(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            CmsPeriod coupon = cmsPeriod.toCouponEquivalent();
            double    adjustedForwardRate = this.adjustedForwardRate(coupon, provider, swaptionVolatilities);
            double    forward             = swapPricer.parRate(coupon.UnderlyingSwap, provider);

            return(adjustedForwardRate - forward);
        }
        //-------------------------------------------------------------------------
        /// <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)));
        }
示例#11
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value </returns>
        public CurrencyAmount presentValue(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency ccy = cmsPeriod.Currency;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(CurrencyAmount.zero(ccy));
            }
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        expiryTime    = swaptionVolatilities.relativeTime(fixingDate.atTime(index.FixingTime).atZone(index.FixingZone));
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);
            double        strikeCpn     = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, fixedRate.Value);
                    return(CurrencyAmount.of(ccy, dfPayment * payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);

            if (expiryTime < MIN_TIME)
            {
                double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, forward);
                return(CurrencyAmount.of(ccy, dfPayment * payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
            }
            double eta = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            double factor     = dfPayment / intProv.h(forward) * intProv.g(forward);
            double strikePart = factor * intProv.k(strikeCpn) * intProv.bs(strikeCpn);
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL, NUM_ITER);
            double integralPart = 0d;

            System.Func <double, double> integrant = intProv.integrant();
            try
            {
                if (intProv.PutCall.Call)
                {
                    integralPart = dfPayment * integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                }
                else
                {
                    integralPart = -dfPayment *integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn);
                }
            }
            catch (Exception e)
            {
                throw new MathException(e);
            }
            double priceCMS = (strikePart + integralPart);

            if (cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON))
            {
                priceCMS -= dfPayment * shift;
            }
            priceCMS *= cmsPeriod.Notional * cmsPeriod.YearFraction;
            return(CurrencyAmount.of(ccy, priceCMS));
        }
示例#12
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value of the CMS product.
        /// <para>
        /// The present value of the product is the value on the valuation date.
        /// </para>
        /// <para>
        /// CMS leg and pay leg are typically in the same currency. Thus the present value is expressed as a
        /// single currency amount in most cases.
        ///
        /// </para>
        /// </summary>
        /// <param name="cms">  the CMS product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value </returns>
        public virtual MultiCurrencyAmount presentValue(ResolvedCms cms, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            CurrencyAmount pvCmsLeg = cmsLegPricer.presentValue(cms.CmsLeg, ratesProvider, swaptionVolatilities);

            if (!cms.PayLeg.Present)
            {
                return(MultiCurrencyAmount.of(pvCmsLeg));
            }
            CurrencyAmount pvPayLeg = payLegPricer.presentValue(cms.PayLeg.get(), ratesProvider);

            return(MultiCurrencyAmount.of(pvCmsLeg).plus(pvPayLeg));
        }
示例#13
0
 /// <summary>
 /// Calculates the present value sensitivity to the strike value.
 /// <para>
 /// The present value sensitivity of the product is the sensitivity of the present value to the strike value.
 /// This is not relevant for CMS coupons and an exception is thrown in the underlying pricer.
 ///
 /// </para>
 /// </summary>
 /// <param name="cms">  the CMS product </param>
 /// <param name="ratesProvider">  the rates provider </param>
 /// <param name="swaptionVolatilities">  the swaption volatilities </param>
 /// <returns> the present value sensitivity </returns>
 public virtual double presentValueSensitivityStrike(ResolvedCms cms, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
 {
     return(cmsLegPricer.presentValueSensitivityStrike(cms.CmsLeg, ratesProvider, swaptionVolatilities));
 }
示例#14
0
 /// <summary>
 /// Calculates the present value sensitivity to the SABR model parameters.
 /// <para>
 /// The present value sensitivity of the product is the sensitivity of the present value
 /// to the SABR model parameters, alpha, beta, rho and nu.
 ///
 /// </para>
 /// </summary>
 /// <param name="cms">  the CMS product </param>
 /// <param name="ratesProvider">  the rates provider </param>
 /// <param name="swaptionVolatilities">  the swaption volatilities </param>
 /// <returns> the present value sensitivity </returns>
 public virtual PointSensitivityBuilder presentValueSensitivityModelParamsSabr(ResolvedCms cms, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
 {
     return(cmsLegPricer.presentValueSensitivityModelParamsSabr(cms.CmsLeg, ratesProvider, swaptionVolatilities));
 }
        //-------------------------------------------------------------------------
        /// <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))));
        }
示例#16
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes the present value curve sensitivity by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public PointSensitivityBuilder presentValueSensitivityRates(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency ccy = cmsPeriod.Currency;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        expiryTime    = swaptionVolatilities.relativeTime(fixingDate.atTime(index.FixingTime).atZone(index.FixingZone));
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);
            double        strikeCpn     = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = payOff(cmsPeriod.CmsPeriodType, strikeCpn, fixedRate.Value);
                    return(provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate).multipliedBy(payoff * cmsPeriod.Notional * cmsPeriod.YearFraction));
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);
            double eta     = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsDeltaIntegrantProvider intProv    = new CmsDeltaIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            RungeKuttaIntegrator1D    integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL, NUM_ITER);

            double[] bs = intProv.bsbsp(strikeCpn);
            double[] n  = intProv.Nnp;
            double   strikePartPrice   = intProv.k(strikeCpn) * n[0] * bs[0];
            double   integralPartPrice = 0d;
            double   integralPart      = 0d;

            System.Func <double, double> integrant      = intProv.integrant();
            System.Func <double, double> integrantDelta = intProv.integrantDelta();
            try
            {
                if (intProv.PutCall.Call)
                {
                    integralPartPrice = integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                    integralPart      = dfPayment * integrateCall(integrator, integrantDelta, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                }
                else
                {
                    integralPartPrice = -integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn).Value;
                    integralPart      = -dfPayment *integrator.integrate(integrantDelta, -shift, strikeCpn);
                }
            }
            catch (Exception e)
            {
                throw new MathException(e);
            }
            double deltaPD = strikePartPrice + integralPartPrice;

            if (cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON))
            {
                deltaPD -= shift;
            }
            deltaPD *= cmsPeriod.Notional * cmsPeriod.YearFraction;
            double strikePart = dfPayment * intProv.k(strikeCpn) * (n[1] * bs[0] + n[0] * bs[1]);
            double deltaFwd   = (strikePart + integralPart) * cmsPeriod.Notional * cmsPeriod.YearFraction;
            PointSensitivityBuilder sensiFwd = swapPricer.parRateSensitivity(swap, provider).multipliedBy(deltaFwd);
            PointSensitivityBuilder sensiDf  = provider.discountFactors(ccy).zeroRatePointSensitivity(cmsPeriod.PaymentDate).multipliedBy(deltaPD);

            return(sensiFwd.combinedWith(sensiDf));
        }
        //-------------------------------------------------------------------------
        /// <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)));
        }
示例#18
0
        /// <summary>
        /// Computes the present value sensitivity to SABR parameters by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public PointSensitivityBuilder presentValueSensitivityModelParamsSabr(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            Currency      ccy           = cmsPeriod.Currency;
            SwapIndex     index         = cmsPeriod.Index;
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            ZonedDateTime expiryDate    = fixingDate.atTime(index.FixingTime).atZone(index.FixingZone);
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(PointSensitivityBuilder.none());
            }
            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    return(PointSensitivityBuilder.none());
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double expiryTime            = swaptionVolatilities.relativeTime(expiryDate);
            double shift                 = swaptionVolatilities.shift(expiryTime, tenor);
            double strikeCpn             = cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON) ? -shift : cmsPeriod.Strike;
            double forward               = swapPricer.parRate(swap, provider);
            double eta                   = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor, cutOffStrike, eta);
            double factor                = dfPayment / intProv.h(forward) * intProv.g(forward);
            double factor2               = factor * intProv.k(strikeCpn);

            double[] strikePartPrice          = intProv.SabrExtrapolation.priceAdjointSabr(Math.Max(0d, strikeCpn + shift), intProv.PutCall).Derivatives.multipliedBy(factor2).toArray();
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL_VEGA, NUM_ITER);

            double[] totalSensi = new double[4];
            for (int loopparameter = 0; loopparameter < 4; loopparameter++)
            {
                double integralPart = 0d;
                System.Func <double, double> integrant = intProv.integrantVega(loopparameter);
                try
                {
                    if (intProv.PutCall.Call)
                    {
                        integralPart = dfPayment * integrateCall(integrator, integrant, swaptionVolatilities, forward, strikeCpn, expiryTime, tenor);
                    }
                    else
                    {
                        integralPart = -dfPayment *integrator.integrate(integrant, -shift + ZERO_SHIFT, strikeCpn);
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(e);
                }
                totalSensi[loopparameter] = (strikePartPrice[loopparameter] + integralPart) * cmsPeriod.Notional * cmsPeriod.YearFraction;
            }
            SwaptionVolatilitiesName name = swaptionVolatilities.Name;

            return(PointSensitivityBuilder.of(SwaptionSabrSensitivity.of(name, expiryTime, tenor, ALPHA, ccy, totalSensi[0]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, BETA, ccy, totalSensi[1]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, RHO, ccy, totalSensi[2]), SwaptionSabrSensitivity.of(name, expiryTime, tenor, NU, ccy, totalSensi[3])));
        }
示例#19
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value sensitivity to the SABR model parameters of the swaption trade.
        /// <para>
        /// The sensitivity of the present value to the SABR model parameters, alpha, beta, rho and nu.
        ///
        /// </para>
        /// </summary>
        /// <param name="trade">  the swaption trade </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 PointSensitivities presentValueSensitivityModelParamsSabr(ResolvedSwaptionTrade trade, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            ResolvedSwaption        product   = trade.Product;
            PointSensitivityBuilder pointSens = isCash(product) ? cashParYieldPricer.presentValueSensitivityModelParamsSabr(product, ratesProvider, swaptionVolatilities) : physicalPricer.presentValueSensitivityModelParamsSabr(product, ratesProvider, swaptionVolatilities);

            return(pointSens.build());
        }
示例#20
0
        /// <summary>
        /// Computes the present value sensitivity to strike by replication in SABR framework with extrapolation on the right.
        /// </summary>
        /// <param name="cmsPeriod">  the CMS </param>
        /// <param name="provider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the present value sensitivity </returns>
        public double presentValueSensitivityStrike(CmsPeriod cmsPeriod, RatesProvider provider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            ArgChecker.isFalse(cmsPeriod.CmsPeriodType.Equals(CmsPeriodType.COUPON), "presentValueSensitivityStrike is not relevant for CMS coupon");
            Currency  ccy   = cmsPeriod.Currency;
            SwapIndex index = cmsPeriod.Index;

            if (provider.ValuationDate.isAfter(cmsPeriod.PaymentDate))
            {
                return(0d);
            }
            ResolvedSwap  swap          = cmsPeriod.UnderlyingSwap;
            double        dfPayment     = provider.discountFactor(ccy, cmsPeriod.PaymentDate);
            ZonedDateTime valuationDate = swaptionVolatilities.ValuationDateTime;
            LocalDate     fixingDate    = cmsPeriod.FixingDate;
            double        tenor         = swaptionVolatilities.tenor(swap.StartDate, swap.EndDate);
            ZonedDateTime expiryDate    = fixingDate.atTime(index.FixingTime).atZone(index.FixingZone);
            double        expiryTime    = swaptionVolatilities.relativeTime(expiryDate);
            double        strike        = cmsPeriod.Strike;
            double        shift         = swaptionVolatilities.shift(expiryTime, tenor);

            if (!fixingDate.isAfter(valuationDate.toLocalDate()))
            {
                double?fixedRate = provider.timeSeries(cmsPeriod.Index).get(fixingDate);
                if (fixedRate.HasValue)
                {
                    double payoff = 0d;
                    switch (cmsPeriod.CmsPeriodType)
                    {
                    case CAPLET:
                        payoff = fixedRate.Value >= strike ? -1d : 0d;
                        break;

                    case FLOORLET:
                        payoff = fixedRate.Value < strike ? 1d : 0d;
                        break;

                    default:
                        throw new System.ArgumentException("unsupported CMS type");
                    }
                    return(payoff * cmsPeriod.Notional * cmsPeriod.YearFraction * dfPayment);
                }
                else if (fixingDate.isBefore(valuationDate.toLocalDate()))
                {
                    throw new System.ArgumentException(Messages.format("Unable to get fixing for {} on date {}, no time-series supplied", cmsPeriod.Index, fixingDate));
                }
            }
            double forward = swapPricer.parRate(swap, provider);
            double eta     = index.Template.Convention.FixedLeg.DayCount.relativeYearFraction(cmsPeriod.PaymentDate, swap.StartDate);
            CmsIntegrantProvider intProv = new CmsIntegrantProvider(this, cmsPeriod, swap, swaptionVolatilities, forward, strike, expiryTime, tenor, cutOffStrike, eta);
            double factor = dfPayment * intProv.g(forward) / intProv.h(forward);
            RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(ABS_TOL, REL_TOL_STRIKE, NUM_ITER);

            double[] kpkpp = intProv.kpkpp(strike);
            double   firstPart;
            double   thirdPart;

            System.Func <double, double> integrant = intProv.integrantDualDelta();
            if (intProv.PutCall.Call)
            {
                firstPart = -kpkpp[0] * intProv.bs(strike);
                thirdPart = integrateCall(integrator, integrant, swaptionVolatilities, forward, strike, expiryTime, tenor);
            }
            else
            {
                firstPart = -kpkpp[0] * intProv.bs(strike);
                thirdPart = -integrator.integrate(integrant, -shift + ZERO_SHIFT, strike).Value;
            }
            double secondPart = intProv.k(strike) * intProv.SabrExtrapolation.priceDerivativeStrike(strike + shift, intProv.PutCall);

            return(cmsPeriod.Notional * cmsPeriod.YearFraction * factor * (firstPart + secondPart + thirdPart));
        }
示例#21
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Calculates the present value of the swaption trade.
        /// <para>
        /// The result is expressed using the currency of the swaption.
        ///
        /// </para>
        /// </summary>
        /// <param name="trade">  the swaption trade </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the volatilities </param>
        /// <returns> the present value </returns>
        public virtual CurrencyAmount presentValue(ResolvedSwaptionTrade trade, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            // product
            ResolvedSwaption product   = trade.Product;
            CurrencyAmount   pvProduct = isCash(product) ? cashParYieldPricer.presentValue(product, ratesProvider, swaptionVolatilities) : physicalPricer.presentValue(product, ratesProvider, swaptionVolatilities);
            // premium
            Payment        premium   = trade.Premium;
            CurrencyAmount pvPremium = paymentPricer.presentValue(premium, ratesProvider);

            // total
            return(pvProduct.plus(pvPremium));
        }
示例#22
0
        //-------------------------------------------------------------------------
        /// <summary>
        /// Explains the present value of the CMS product.
        /// <para>
        /// This returns explanatory information about the calculation.
        ///
        /// </para>
        /// </summary>
        /// <param name="cms">  the CMS product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="swaptionVolatilities">  the swaption volatilities </param>
        /// <returns> the explain PV map </returns>
        public virtual ExplainMap explainPresentValue(ResolvedCms cms, RatesProvider ratesProvider, SabrSwaptionVolatilities swaptionVolatilities)
        {
            ExplainMapBuilder builder = ExplainMap.builder();

            builder.put(ExplainKey.ENTRY_TYPE, "CmsSwap");
            IList <ExplainMap> legsExplain = new List <ExplainMap>();

            legsExplain.Add(cmsLegPricer.explainPresentValue(cms.CmsLeg, ratesProvider, swaptionVolatilities));
            if (cms.PayLeg.Present)
            {
                legsExplain.Add(payLegPricer.explainPresentValue(cms.PayLeg.get(), ratesProvider));
            }
            builder.put(ExplainKey.LEGS, legsExplain);
            return(builder.build());
        }