Esempio n. 1
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));
        }