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