Exemplo n.º 1
0
        private CurrencyParameterSensitivities sensitivityCreidtCurve <T>(ImmutableCreditRatesProvider provider, System.Func <ImmutableCreditRatesProvider, CurrencyAmount> valueFn, MetaProperty <ImmutableMap <T, LegalEntitySurvivalProbabilities> > metaProperty, CurrencyAmount valueInit)
        {
            ImmutableMap <T, LegalEntitySurvivalProbabilities> baseCurves = metaProperty.get(provider);
            CurrencyParameterSensitivities result = CurrencyParameterSensitivities.empty();

            foreach (T key in baseCurves.Keys)
            {
                LegalEntitySurvivalProbabilities credit = baseCurves.get(key);
                CreditDiscountFactors            creditDiscountFactors = credit.SurvivalProbabilities;
                DiscountFactors discountFactors = creditDiscountFactors.toDiscountFactors();
                Curve           curve           = checkDiscountFactors(discountFactors);
                int             paramCount      = curve.ParameterCount;
                double[]        sensitivity     = new double[paramCount];
                for (int i = 0; i < paramCount; i++)
                {
                    Curve dscBumped = curve.withParameter(i, curve.getParameter(i) + shift);
                    IDictionary <T, LegalEntitySurvivalProbabilities> mapBumped = new Dictionary <T, LegalEntitySurvivalProbabilities>(baseCurves);
                    mapBumped[key] = LegalEntitySurvivalProbabilities.of(credit.LegalEntityId, createCreditDiscountFactors(creditDiscountFactors, dscBumped));
                    ImmutableCreditRatesProvider providerDscBumped = provider.toBuilder().set(metaProperty, mapBumped).build();
                    sensitivity[i] = (valueFn(providerDscBumped).Amount - valueInit.Amount) / shift;
                }
                result = result.combinedWith(curve.createParameterSensitivity(valueInit.Currency, DoubleArray.copyOf(sensitivity)));
            }
            return(result);
        }
        /// <summary>
        /// Calculates the market quote sensitivities from parameter sensitivity.
        /// <para>
        /// This calculates the market quote sensitivities of fixed incomes.
        /// The input parameter sensitivities must be computed based on the legal entity discounting provider.
        ///
        /// </para>
        /// </summary>
        /// <param name="paramSensitivities">  the curve parameter sensitivities </param>
        /// <param name="provider">  the legal entity discounting provider, containing Jacobian calibration information </param>
        /// <returns> the market quote sensitivities </returns>
        public virtual CurrencyParameterSensitivities sensitivity(CurrencyParameterSensitivities paramSensitivities, LegalEntityDiscountingProvider provider)
        {
            ArgChecker.notNull(paramSensitivities, "paramSensitivities");
            ArgChecker.notNull(provider, "provider");

            CurrencyParameterSensitivities result = CurrencyParameterSensitivities.empty();

            foreach (CurrencyParameterSensitivity paramSens in paramSensitivities.Sensitivities)
            {
                // find the matching calibration info
                Curve curve = provider.findData(paramSens.MarketDataName).filter(v => v is Curve).map(v => (Curve)v).orElseThrow(() => new System.ArgumentException("Market Quote sensitivity requires curve: " + paramSens.MarketDataName));
                JacobianCalibrationMatrix info = curve.Metadata.findInfo(CurveInfoType.JACOBIAN).orElseThrow(() => new System.ArgumentException("Market Quote sensitivity requires Jacobian calibration information"));

                // calculate the market quote sensitivity using the Jacobian
                DoubleMatrix jacobian              = info.JacobianMatrix;
                DoubleArray  paramSensMatrix       = paramSens.Sensitivity;
                DoubleArray  marketQuoteSensMatrix = (DoubleArray)MATRIX_ALGEBRA.multiply(paramSensMatrix, jacobian);
                DoubleArray  marketQuoteSens       = marketQuoteSensMatrix;

                // split between different curves
                IDictionary <CurveName, DoubleArray> split = info.splitValues(marketQuoteSens);
                foreach (KeyValuePair <CurveName, DoubleArray> entry in split.SetOfKeyValuePairs())
                {
                    CurveName curveName = entry.Key;
                    CurrencyParameterSensitivity maketQuoteSens = provider.findData(curveName).map(c => c.createParameterSensitivity(paramSens.Currency, entry.Value)).orElse(CurrencyParameterSensitivity.of(curveName, paramSens.Currency, entry.Value));
                    result = result.combinedWith(maketQuoteSens);
                }
            }
            return(result);
        }
        /// <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 curve parameters.
        /// </para>
        /// <para>
        /// The sensitivity is computed by bump and re-price.
        ///
        /// </para>
        /// </summary>
        /// <param name="option">  the option product </param>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="volatilities">  the Black volatility provider </param>
        /// <param name="baseTreeData">  the trinomial tree data </param>
        /// <returns> the present value of the product </returns>
        public virtual CurrencyParameterSensitivities presentValueSensitivityRates(ResolvedFxSingleBarrierOption option, RatesProvider ratesProvider, BlackFxOptionVolatilities volatilities, RecombiningTrinomialTreeData baseTreeData)
        {
            ArgChecker.isTrue(baseTreeData.NumberOfSteps == calibrator.NumberOfSteps, "the number of steps mismatch between pricer and trinomial tree data");
            double                         shift            = 1.0e-5;
            CurrencyAmount                 pvBase           = presentValue(option, ratesProvider, volatilities, baseTreeData);
            ResolvedFxVanillaOption        underlyingOption = option.UnderlyingOption;
            ResolvedFxSingle               underlyingFx     = underlyingOption.Underlying;
            CurrencyPair                   currencyPair     = underlyingFx.CurrencyPair;
            ImmutableRatesProvider         immRatesProvider = ratesProvider.toImmutableRatesProvider();
            ImmutableMap <Currency, Curve> baseCurves       = immRatesProvider.DiscountCurves;
            CurrencyParameterSensitivities result           = CurrencyParameterSensitivities.empty();

            foreach (KeyValuePair <Currency, Curve> entry in baseCurves.entrySet())
            {
                if (currencyPair.contains(entry.Key))
                {
                    Curve       curve       = entry.Value;
                    int         nParams     = curve.ParameterCount;
                    DoubleArray sensitivity = DoubleArray.of(nParams, i =>
                    {
                        Curve dscBumped = curve.withParameter(i, curve.getParameter(i) + shift);
                        IDictionary <Currency, Curve> mapBumped = new Dictionary <Currency, Curve>(baseCurves);
                        mapBumped[entry.Key] = dscBumped;
                        ImmutableRatesProvider providerDscBumped = immRatesProvider.toBuilder().discountCurves(mapBumped).build();
                        double pvBumped = presentValue(option, providerDscBumped, volatilities).Amount;
                        return((pvBumped - pvBase.Amount) / shift);
                    });
                    result = result.combinedWith(curve.createParameterSensitivity(pvBase.Currency, sensitivity));
                }
            }
            return(result);
        }
Exemplo n.º 4
0
        // modified sensitivity function - CombinedCurve involved
        private CurrencyParameterSensitivities sensiCombinedFnBond(ImmutableLegalEntityDiscountingProvider provider)
        {
            CurrencyParameterSensitivities sensi = CurrencyParameterSensitivities.empty();
            double sum = sumCombine(provider);
            // repo curves
            ImmutableMap <Pair <RepoGroup, Currency>, DiscountFactors> mapCurrency = provider.RepoCurves;

            foreach (KeyValuePair <Pair <RepoGroup, Currency>, DiscountFactors> entry in mapCurrency.entrySet())
            {
                CombinedCurve          curveComb      = (CombinedCurve)getCurve(entry.Value);
                InterpolatedNodalCurve baseCurveInt   = checkInterpolated(curveComb.BaseCurve);
                InterpolatedNodalCurve spreadCurveInt = checkInterpolated(curveComb.SpreadCurve);
                sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(baseCurveInt.Name, USD, DoubleArray.of(baseCurveInt.ParameterCount, i => 2d * sum * baseCurveInt.XValues.get(i))));
                sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(spreadCurveInt.Name, USD, DoubleArray.of(spreadCurveInt.ParameterCount, i => 2d * sum * spreadCurveInt.XValues.get(i))));
            }
            // issuer curves
            ImmutableMap <Pair <LegalEntityGroup, Currency>, DiscountFactors> mapIndex = provider.IssuerCurves;

            foreach (KeyValuePair <Pair <LegalEntityGroup, Currency>, DiscountFactors> entry in mapIndex.entrySet())
            {
                CombinedCurve          curveComb      = (CombinedCurve)getCurve(entry.Value);
                InterpolatedNodalCurve baseCurveInt   = checkInterpolated(curveComb.BaseCurve);
                InterpolatedNodalCurve spreadCurveInt = checkInterpolated(curveComb.SpreadCurve);
                sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(baseCurveInt.Name, USD, DoubleArray.of(baseCurveInt.ParameterCount, i => 2d * sum * baseCurveInt.XValues.get(i))));
                sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(spreadCurveInt.Name, USD, DoubleArray.of(spreadCurveInt.ParameterCount, i => 2d * sum * spreadCurveInt.XValues.get(i))));
            }
            return(sensi);
        }
        //-------------------------------------------------------------------------
        public virtual void test_currencyParameterSensitivity_val_date()
        {
            // Discount factor at valuation date is always 0, no sensitivity.
            SimpleDiscountFactors test = SimpleDiscountFactors.of(GBP, DATE_VAL, CURVE);
            ZeroRateSensitivity   sens = test.zeroRatePointSensitivity(DATE_VAL);

            assertEquals(test.parameterSensitivity(sens), CurrencyParameterSensitivities.empty());
        }
        //-------------------------------------------------------------------------
        public virtual void pointToParameterMultiple()
        {
            CurrencyParameterSensitivities psComputed = PROVIDER.parameterSensitivity(POINT);

            assertEquals(psComputed.Sensitivities.size(), 6);
            CurrencyParameterSensitivities psExpected = CurrencyParameterSensitivities.empty();

            for (int i = 0; i < POINTS.Length; i++)
            {
                psExpected = psExpected.combinedWith(PROVIDER.parameterSensitivity(POINTS[i]));
            }
            assertTrue(psComputed.equalWithTolerance(psExpected, TOLERANCE_SENSI));
        }
Exemplo n.º 7
0
        //-------------------------------------------------------------------------
        public CurrencyParameterSensitivities parameterSensitivity(ZeroRateSensitivity pointSens)
        {
            double yearFraction = pointSens.YearFraction;

            if (Math.Abs(yearFraction) < EFFECTIVE_ZERO)
            {
                return(CurrencyParameterSensitivities.empty());  // Discount factor in 0 is always 1, no sensitivity.
            }
            double discountFactor = this.discountFactor(yearFraction);
            UnitParameterSensitivity     unitSens = curve.yValueParameterSensitivity(yearFraction);
            CurrencyParameterSensitivity curSens  = unitSens.multipliedBy(-1d / (yearFraction * discountFactor)).multipliedBy(pointSens.Currency, pointSens.Sensitivity);

            return(CurrencyParameterSensitivities.of(curSens));
        }
        public CurrencyParameterSensitivities parameterSensitivity(PointSensitivities pointSensitivities)
        {
            CurrencyParameterSensitivities sens = CurrencyParameterSensitivities.empty();

            foreach (PointSensitivity point in pointSensitivities.Sensitivities)
            {
                if (point is FxOptionSensitivity)
                {
                    FxOptionSensitivity pt = (FxOptionSensitivity)point;
                    if (pt.VolatilitiesName.Equals(Name))
                    {
                        sens = sens.combinedWith(parameterSensitivity(pt));
                    }
                }
            }
            return(sens);
        }
Exemplo n.º 9
0
        // modified sensitivity function - sensitivities are computed only for ibor index curves
        private CurrencyParameterSensitivities sensiModFn(ImmutableRatesProvider provider)
        {
            CurrencyParameterSensitivities sensi = CurrencyParameterSensitivities.empty();
            // Index
            ImmutableMap <Index, Curve> mapIndex = provider.IndexCurves;

            foreach (KeyValuePair <Index, Curve> entry in mapIndex.entrySet())
            {
                if (entry.Key is IborIndex)
                {
                    InterpolatedNodalCurve curveInt = checkInterpolated(entry.Value);
                    double sumSqrt = sumMod(provider);
                    sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(curveInt.Name, USD, DoubleArray.of(curveInt.ParameterCount, i => 2d * sumSqrt * curveInt.XValues.get(i))));
                }
            }
            return(sensi);
        }
        public CurrencyParameterSensitivity singleCreditCurveParameterSensitivity(PointSensitivities pointSensitivities, StandardId legalEntityId, Currency currency)
        {
            CurrencyParameterSensitivities sens = CurrencyParameterSensitivities.empty();

            foreach (PointSensitivity point in pointSensitivities.Sensitivities)
            {
                if (point is CreditCurveZeroRateSensitivity)
                {
                    CreditCurveZeroRateSensitivity pt = (CreditCurveZeroRateSensitivity)point;
                    if (pt.LegalEntityId.Equals(legalEntityId) && pt.Currency.Equals(currency))
                    {
                        LegalEntitySurvivalProbabilities factors = survivalProbabilities(pt.LegalEntityId, pt.CurveCurrency);
                        sens = sens.combinedWith(factors.parameterSensitivity(pt));
                    }
                }
            }
            ArgChecker.isTrue(sens.size() == 1, "sensitivity must be unique");
            return(sens.Sensitivities.get(0));
        }
Exemplo n.º 11
0
        // computes the sensitivity with respect to the curves
        private CurrencyParameterSensitivities sensitivity <T>(ImmutableRatesProvider provider, IDictionary <T, Curve> baseCurves, System.Func <ImmutableRatesProvider, IDictionary <T, Curve>, ImmutableRatesProvider> storeBumpedFn, System.Func <ImmutableRatesProvider, CurrencyAmount> valueFn, CurrencyAmount valueInit)
        {
            CurrencyParameterSensitivities result = CurrencyParameterSensitivities.empty();

            foreach (KeyValuePair <T, Curve> entry in baseCurves.SetOfKeyValuePairs())
            {
                Curve       curve       = entry.Value;
                DoubleArray sensitivity = DoubleArray.of(curve.ParameterCount, i =>
                {
                    Curve dscBumped = curve.withParameter(i, curve.getParameter(i) + shift);
                    IDictionary <T, Curve> mapBumped         = new Dictionary <T, Curve>(baseCurves);
                    mapBumped[entry.Key]                     = dscBumped;
                    ImmutableRatesProvider providerDscBumped = storeBumpedFn(provider, mapBumped);
                    return((valueFn(providerDscBumped).Amount - valueInit.Amount) / shift);
                });
                result = result.combinedWith(curve.createParameterSensitivity(valueInit.Currency, sensitivity));
            }
            return(result);
        }
        public CurrencyParameterSensitivity singleDiscountCurveParameterSensitivity(PointSensitivities pointSensitivities, Currency currency)
        {
            CurrencyParameterSensitivities sens = CurrencyParameterSensitivities.empty();

            foreach (PointSensitivity point in pointSensitivities.Sensitivities)
            {
                if (point is ZeroRateSensitivity)
                {
                    ZeroRateSensitivity pt = (ZeroRateSensitivity)point;
                    if (pt.Currency.Equals(currency))
                    {
                        CreditDiscountFactors factors = discountFactors(pt.CurveCurrency);
                        sens = sens.combinedWith(factors.parameterSensitivity(pt));
                    }
                }
            }
            ArgChecker.isTrue(sens.size() == 1, "sensitivity must be unique");
            return(sens.Sensitivities.get(0));
        }
        public CurrencyParameterSensitivities parameterSensitivity(PointSensitivities pointSensitivities)
        {
            CurrencyParameterSensitivities sens = CurrencyParameterSensitivities.empty();

            foreach (PointSensitivity point in pointSensitivities.Sensitivities)
            {
                if (point is RepoCurveZeroRateSensitivity)
                {
                    RepoCurveZeroRateSensitivity pt      = (RepoCurveZeroRateSensitivity)point;
                    RepoCurveDiscountFactors     factors = repoCurveDiscountFactors(pt.RepoGroup, pt.CurveCurrency);
                    sens = sens.combinedWith(factors.parameterSensitivity(pt));
                }
                else if (point is IssuerCurveZeroRateSensitivity)
                {
                    IssuerCurveZeroRateSensitivity pt      = (IssuerCurveZeroRateSensitivity)point;
                    IssuerCurveDiscountFactors     factors = issuerCurveDiscountFactors(pt.LegalEntityGroup, pt.CurveCurrency);
                    sens = sens.combinedWith(factors.parameterSensitivity(pt));
                }
            }
            return(sens);
        }
        //-------------------------------------------------------------------------
        public CurrencyParameterSensitivities parameterSensitivity(PointSensitivities pointSensitivities)
        {
            CurrencyParameterSensitivities sens = CurrencyParameterSensitivities.empty();

            foreach (PointSensitivity point in pointSensitivities.Sensitivities)
            {
                if (point is CreditCurveZeroRateSensitivity)
                {
                    CreditCurveZeroRateSensitivity   pt      = (CreditCurveZeroRateSensitivity)point;
                    LegalEntitySurvivalProbabilities factors = survivalProbabilities(pt.LegalEntityId, pt.CurveCurrency);
                    sens = sens.combinedWith(factors.parameterSensitivity(pt));
                }
                else if (point is ZeroRateSensitivity)
                {
                    ZeroRateSensitivity   pt      = (ZeroRateSensitivity)point;
                    CreditDiscountFactors factors = discountFactors(pt.CurveCurrency);
                    sens = sens.combinedWith(factors.parameterSensitivity(pt));
                }
            }
            return(sens);
        }
Exemplo n.º 15
0
        //-------------------------------------------------------------------------
        private CurrencyParameterSensitivities sensiFnBond(ImmutableLegalEntityDiscountingProvider provider)
        {
            CurrencyParameterSensitivities sensi = CurrencyParameterSensitivities.empty();
            double sum = this.sum(provider);
            // repo curves
            ImmutableMap <Pair <RepoGroup, Currency>, DiscountFactors> mapRepoCurves = provider.RepoCurves;

            foreach (KeyValuePair <Pair <RepoGroup, Currency>, DiscountFactors> entry in mapRepoCurves.entrySet())
            {
                DiscountFactors        discountFactors = entry.Value;
                InterpolatedNodalCurve curve           = (InterpolatedNodalCurve)getCurve(discountFactors);
                sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(curve.Name, discountFactors.Currency, DoubleArray.of(discountFactors.ParameterCount, i => 2d * curve.XValues.get(i) * sum)));
            }
            // issuer curves
            ImmutableMap <Pair <LegalEntityGroup, Currency>, DiscountFactors> mapIssuerCurves = provider.IssuerCurves;

            foreach (KeyValuePair <Pair <LegalEntityGroup, Currency>, DiscountFactors> entry in mapIssuerCurves.entrySet())
            {
                DiscountFactors        discountFactors = entry.Value;
                InterpolatedNodalCurve curve           = (InterpolatedNodalCurve)getCurve(discountFactors);
                sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(curve.Name, discountFactors.Currency, DoubleArray.of(discountFactors.ParameterCount, i => 2d * curve.XValues.get(i) * sum)));
            }
            return(sensi);
        }
Exemplo n.º 16
0
        // modified sensitivity function - CombinedCurve involved
        private CurrencyParameterSensitivities sensiCombinedFn(ImmutableRatesProvider provider)
        {
            CurrencyParameterSensitivities sensi = CurrencyParameterSensitivities.empty();
            double sum = sumCombine(provider);
            // Currency
            ImmutableMap <Currency, Curve> mapCurrency = provider.DiscountCurves;

            foreach (KeyValuePair <Currency, Curve> entry in mapCurrency.entrySet())
            {
                CombinedCurve          curveComb      = (CombinedCurve)entry.Value;
                InterpolatedNodalCurve baseCurveInt   = checkInterpolated(curveComb.BaseCurve);
                InterpolatedNodalCurve spreadCurveInt = checkInterpolated(curveComb.SpreadCurve);
                sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(baseCurveInt.Name, USD, DoubleArray.of(baseCurveInt.ParameterCount, i => 2d * sum * baseCurveInt.XValues.get(i))));
                sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(spreadCurveInt.Name, USD, DoubleArray.of(spreadCurveInt.ParameterCount, i => 2d * sum * spreadCurveInt.XValues.get(i))));
            }
            // Index
            ImmutableMap <Index, Curve> mapIndex = provider.IndexCurves;

            foreach (KeyValuePair <Index, Curve> entry in mapIndex.entrySet())
            {
                if (entry.Value is CombinedCurve)
                {
                    CombinedCurve          curveComb      = (CombinedCurve)entry.Value;
                    InterpolatedNodalCurve baseCurveInt   = checkInterpolated(curveComb.BaseCurve);
                    InterpolatedNodalCurve spreadCurveInt = checkInterpolated(curveComb.SpreadCurve);
                    sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(baseCurveInt.Name, USD, DoubleArray.of(baseCurveInt.ParameterCount, i => 2d * sum * baseCurveInt.XValues.get(i))));
                    sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(spreadCurveInt.Name, USD, DoubleArray.of(spreadCurveInt.ParameterCount, i => 2d * sum * spreadCurveInt.XValues.get(i))));
                }
                else
                {
                    InterpolatedNodalCurve curveInt = checkInterpolated(entry.Value);
                    sensi = sensi.combinedWith(CurrencyParameterSensitivity.of(curveInt.Name, USD, DoubleArray.of(curveInt.ParameterCount, i => 2d * sum * curveInt.XValues.get(i))));
                }
            }
            return(sensi);
        }
        public virtual void regressionPvSurfaceSensi()
        {
            PointSensitivities pointComputed = SWAPTION_PRICER.presentValueSensitivityModelParamsSabr(SWAPTION_PAY_LONG, RATE_PROVIDER, VOLS_REGRESSION).build();

            assertSensitivity(pointComputed, SabrParameterType.ALPHA, 6.5786313367554754E7, REGRESSION_TOL);
            assertSensitivity(pointComputed, SabrParameterType.BETA, -1.2044275797229866E7, REGRESSION_TOL);
            assertSensitivity(pointComputed, SabrParameterType.RHO, 266223.51118849067, REGRESSION_TOL);
            assertSensitivity(pointComputed, SabrParameterType.NU, 400285.5505271345, REGRESSION_TOL);
            CurrencyParameterSensitivities sensiComputed = VOLS_REGRESSION.parameterSensitivity(pointComputed);

            double[][] alphaExp = new double[][]
            {
                new double[] { 0.0, 1.0, 0.0 },
                new double[] { 0.5, 1.0, 0.0 },
                new double[] { 1.0, 1.0, 0.0 },
                new double[] { 2.0, 1.0, 0.0 },
                new double[] { 5.0, 1.0, 0.0 },
                new double[] { 10.0, 1.0, 0.0 },
                new double[] { 0.0, 5.0, 0.0 },
                new double[] { 0.5, 5.0, 0.0 },
                new double[] { 1.0, 5.0, 6204.475194599179 },
                new double[] { 2.0, 5.0, 3.94631212984123E7 },
                new double[] { 5.0, 5.0, 0.0 },
                new double[] { 10.0, 5.0, 0.0 },
                new double[] { 0.0, 10.0, 0.0 },
                new double[] { 0.5, 10.0, 0.0 },
                new double[] { 1.0, 10.0, 4136.961894403858 },
                new double[] { 2.0, 10.0, 2.631285063205345E7 },
                new double[] { 5.0, 10.0, 0.0 },
                new double[] { 10.0, 10.0, 0.0 }
            };
            double[][] betaExp = new double[][]
            {
                new double[] { 0.0, 1.0, -0.0 },
                new double[] { 0.5, 1.0, -0.0 },
                new double[] { 1.0, 1.0, -0.0 },
                new double[] { 2.0, 1.0, -0.0 },
                new double[] { 5.0, 1.0, -0.0 },
                new double[] { 10.0, 1.0, -0.0 },
                new double[] { 0.0, 5.0, -0.0 },
                new double[] { 0.5, 5.0, -0.0 },
                new double[] { 1.0, 5.0, -1135.926404680998 },
                new double[] { 2.0, 5.0, -7224978.759366533 },
                new double[] { 5.0, 5.0, -0.0 },
                new double[] { 10.0, 5.0, -0.0 },
                new double[] { 0.0, 10.0, -0.0 },
                new double[] { 0.5, 10.0, -0.0 },
                new double[] { 1.0, 10.0, -757.402375482629 },
                new double[] { 2.0, 10.0, -4817403.70908317 },
                new double[] { 5.0, 10.0, -0.0 },
                new double[] { 10.0, 10.0, -0.0 }
            };
            double[][] rhoExp = new double[][]
            {
                new double[] { 0.0, 1.0, 0.0 },
                new double[] { 0.5, 1.0, 0.0 },
                new double[] { 1.0, 1.0, 0.0 },
                new double[] { 2.0, 1.0, 0.0 },
                new double[] { 5.0, 1.0, 0.0 },
                new double[] { 10.0, 1.0, 0.0 },
                new double[] { 0.0, 5.0, 0.0 },
                new double[] { 0.5, 5.0, 0.0 },
                new double[] { 1.0, 5.0, 25.10821912392996 },
                new double[] { 2.0, 5.0, 159699.03429338703 },
                new double[] { 5.0, 5.0, 0.0 },
                new double[] { 10.0, 5.0, 0.0 },
                new double[] { 0.0, 10.0, 0.0 },
                new double[] { 0.5, 10.0, 0.0 },
                new double[] { 1.0, 10.0, 16.741423326578513 },
                new double[] { 2.0, 10.0, 106482.62725265314 },
                new double[] { 5.0, 10.0, 0.0 },
                new double[] { 10.0, 10.0, 0.0 }
            };
            double[][] nuExp = new double[][]
            {
                new double[] { 0.0, 1.0, 0.0 },
                new double[] { 0.5, 1.0, 0.0 },
                new double[] { 1.0, 1.0, 0.0 },
                new double[] { 2.0, 1.0, 0.0 },
                new double[] { 5.0, 1.0, 0.0 },
                new double[] { 10.0, 1.0, 0.0 },
                new double[] { 0.0, 5.0, 0.0 },
                new double[] { 0.5, 5.0, 0.0 },
                new double[] { 1.0, 5.0, 37.751952372314484 },
                new double[] { 2.0, 5.0, 240118.59649585965 },
                new double[] { 5.0, 5.0, 0.0 },
                new double[] { 10.0, 5.0, 0.0 },
                new double[] { 0.0, 10.0, 0.0 },
                new double[] { 0.5, 10.0, 0.0 },
                new double[] { 1.0, 10.0, 25.171893432592533 },
                new double[] { 2.0, 10.0, 160104.03018547 },
                new double[] { 5.0, 10.0, 0.0 },
                new double[] { 10.0, 10.0, 0.0 }
            };
            double[][][]      exps     = new double[][][] { alphaExp, betaExp, rhoExp, nuExp };
            SurfaceMetadata[] metadata = new SurfaceMetadata[] { SwaptionSabrRateVolatilityDataSet.META_ALPHA, SwaptionSabrRateVolatilityDataSet.META_BETA_USD, SwaptionSabrRateVolatilityDataSet.META_RHO, SwaptionSabrRateVolatilityDataSet.META_NU };
            // x-y-value order does not match sorted order in surface, thus sort it
            CurrencyParameterSensitivities sensiExpected = CurrencyParameterSensitivities.empty();

            for (int i = 0; i < exps.Length; ++i)
            {
                int size = exps[i].Length;
                IDictionary <DoublesPair, double> sensiMap = new SortedDictionary <DoublesPair, double>();
                for (int j = 0; j < size; ++j)
                {
                    sensiMap[DoublesPair.of(exps[i][j][0], exps[i][j][1])] = exps[i][j][2];
                }
                IList <ParameterMetadata> paramMetadata = new List <ParameterMetadata>(size);
                IList <double>            sensi         = new List <double>();
                foreach (KeyValuePair <DoublesPair, double> entry in sensiMap.SetOfKeyValuePairs())
                {
                    paramMetadata.Add(SwaptionSurfaceExpiryTenorParameterMetadata.of(entry.Key.First, entry.Key.Second));
                    sensi.Add(entry.Value);
                }
                SurfaceMetadata surfaceMetadata = metadata[i].withParameterMetadata(paramMetadata);
                sensiExpected = sensiExpected.combinedWith(CurrencyParameterSensitivity.of(surfaceMetadata.SurfaceName, surfaceMetadata.ParameterMetadata.get(), USD, DoubleArray.copyOf(sensi)));
            }
            testSurfaceParameterSensitivities(sensiComputed, sensiExpected, REGRESSION_TOL * NOTIONAL);
        }
        public virtual void test_presentValueVega_SwaptionSensitivity()
        {
            SwaptionSensitivity vegaRec = SWAPTION_PRICER.presentValueSensitivityModelParamsVolatility(SWAPTION_REC_LONG, RATE_PROVIDER, VOLS);

            assertEquals(VOLS.parameterSensitivity(vegaRec), CurrencyParameterSensitivities.empty());
        }