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