Exemple #1
0
        public virtual void sensitivity_single_curve()
        {
            CrossGammaParameterSensitivities forward  = FORWARD.calculateCrossGammaIntraCurve(RatesProviderDataSets.SINGLE_USD, this.sensiFn);
            CrossGammaParameterSensitivities central  = CENTRAL.calculateCrossGammaIntraCurve(RatesProviderDataSets.SINGLE_USD, this.sensiFn);
            CrossGammaParameterSensitivities backward = BACKWARD.calculateCrossGammaIntraCurve(RatesProviderDataSets.SINGLE_USD, this.sensiFn);
            DoubleArray times = RatesProviderDataSets.TIMES_1;

            foreach (CrossGammaParameterSensitivities sensi in new CrossGammaParameterSensitivities[] { forward, central, backward })
            {
                CurrencyParameterSensitivities diagonalComputed = sensi.diagonal();
                assertEquals(sensi.size(), 1);
                assertEquals(diagonalComputed.size(), 1);
                DoubleMatrix s = sensi.Sensitivities.get(0).Sensitivity;
                assertEquals(s.columnCount(), times.size());
                for (int i = 0; i < times.size(); i++)
                {
                    for (int j = 0; j < times.size(); j++)
                    {
                        double expected = 32d * times.get(i) * times.get(j);
                        assertEquals(s.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS);
                    }
                }
            }
            // no difference for single curve
            CrossGammaParameterSensitivities forwardCross = FORWARD.calculateCrossGammaCrossCurve(RatesProviderDataSets.SINGLE_USD, this.sensiFn);

            assertTrue(forward.equalWithTolerance(forwardCross, TOL));
            CrossGammaParameterSensitivities centralCross = CENTRAL.calculateCrossGammaCrossCurve(RatesProviderDataSets.SINGLE_USD, this.sensiFn);

            assertTrue(central.equalWithTolerance(centralCross, TOL));
            CrossGammaParameterSensitivities backwardCross = BACKWARD.calculateCrossGammaCrossCurve(RatesProviderDataSets.SINGLE_USD, this.sensiFn);

            assertTrue(backward.equalWithTolerance(backwardCross, TOL));
        }
Exemple #2
0
        public virtual void sensitivity_multi_combined_bond_curve()
        {
            CrossGammaParameterSensitivities sensiComputed = CENTRAL.calculateCrossGammaIntraCurve(RatesProviderDataSets.MULTI_BOND_COMBINED, this.sensiCombinedFnBond);
            DoubleArray timesUsL3      = RatesProviderDataSets.TIMES_2;
            DoubleArray timesUsRepo    = RatesProviderDataSets.TIMES_1;
            DoubleArray timesUsIssuer1 = RatesProviderDataSets.TIMES_3;
            DoubleArray timesUsIssuer2 = RatesProviderDataSets.TIMES_2;

            assertEquals(sensiComputed.size(), 4);
            DoubleMatrix s1 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_L3_NAME, USD).Sensitivity;

            assertEquals(s1.columnCount(), timesUsL3.size());
            for (int i = 0; i < timesUsL3.size(); i++)
            {
                for (int j = 0; j < timesUsL3.size(); j++)
                {
                    double expected = 2d * timesUsL3.get(i) * timesUsL3.get(j) * 3d * 3d;
                    assertEquals(s1.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s2 = sensiComputed.getSensitivity(RatesProviderDataSets.US_REPO_CURVE_NAME, USD).Sensitivity;

            assertEquals(s2.columnCount(), timesUsRepo.size());
            for (int i = 0; i < timesUsRepo.size(); i++)
            {
                for (int j = 0; j < timesUsRepo.size(); j++)
                {
                    double expected = 2d * timesUsRepo.get(i) * timesUsRepo.get(j);
                    assertEquals(s2.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s3 = sensiComputed.getSensitivity(RatesProviderDataSets.US_ISSUER_CURVE_1_NAME, USD).Sensitivity;

            assertEquals(s3.columnCount(), timesUsIssuer1.size());
            for (int i = 0; i < timesUsIssuer1.size(); i++)
            {
                for (int j = 0; j < timesUsIssuer1.size(); j++)
                {
                    double expected = 2d * timesUsIssuer1.get(i) * timesUsIssuer1.get(j);
                    assertEquals(s3.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s4 = sensiComputed.getSensitivity(RatesProviderDataSets.US_ISSUER_CURVE_2_NAME, USD).Sensitivity;

            assertEquals(s4.columnCount(), timesUsIssuer2.size());
            for (int i = 0; i < timesUsIssuer2.size(); i++)
            {
                for (int j = 0; j < timesUsIssuer2.size(); j++)
                {
                    double expected = 2d * timesUsIssuer2.get(i) * timesUsIssuer2.get(j);
                    assertEquals(s4.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 20d);
                }
            }
        }
Exemple #3
0
        public virtual void sensitivity_intra_multi_curve()
        {
            CrossGammaParameterSensitivities sensiComputed = CENTRAL.calculateCrossGammaIntraCurve(RatesProviderDataSets.MULTI_CPI_USD, this.sensiFn);
            DoubleArray times1 = RatesProviderDataSets.TIMES_1;
            DoubleArray times2 = RatesProviderDataSets.TIMES_2;
            DoubleArray times3 = RatesProviderDataSets.TIMES_3;
            DoubleArray times4 = RatesProviderDataSets.TIMES_4;

            assertEquals(sensiComputed.size(), 4);
            DoubleMatrix s1 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_DSC_NAME, USD).Sensitivity;

            assertEquals(s1.columnCount(), times1.size());
            for (int i = 0; i < times1.size(); i++)
            {
                for (int j = 0; j < times1.size(); j++)
                {
                    double expected = 8d * times1.get(i) * times1.get(j);
                    assertEquals(s1.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s2 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_L3_NAME, USD).Sensitivity;

            assertEquals(s2.columnCount(), times2.size());
            for (int i = 0; i < times2.size(); i++)
            {
                for (int j = 0; j < times2.size(); j++)
                {
                    double expected = 2d * times2.get(i) * times2.get(j);
                    assertEquals(s2.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS);
                }
            }
            DoubleMatrix s3 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_L6_NAME, USD).Sensitivity;

            assertEquals(s3.columnCount(), times3.size());
            for (int i = 0; i < times3.size(); i++)
            {
                for (int j = 0; j < times3.size(); j++)
                {
                    double expected = 2d * times3.get(i) * times3.get(j);
                    assertEquals(s3.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS);
                }
            }
            DoubleMatrix s4 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_CPI_NAME, USD).Sensitivity;

            assertEquals(s4.columnCount(), times4.size());
            for (int i = 0; i < times4.size(); i++)
            {
                for (int j = 0; j < times4.size(); j++)
                {
                    double expected = 2d * times4.get(i) * times4.get(j);
                    assertEquals(s4.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS);
                }
            }
        }
Exemple #4
0
        public virtual void sensitivity_cross_multi_curve_empty()
        {
            CrossGammaParameterSensitivities sensiComputed = CENTRAL.calculateCrossGammaCrossCurve(RatesProviderDataSets.MULTI_CPI_USD, this.sensiModFn);
            DoubleArray times2      = RatesProviderDataSets.TIMES_2;
            DoubleArray times3      = RatesProviderDataSets.TIMES_3;
            int         paramsTotal = times2.size() + times3.size();

            double[] timesTotal = new double[paramsTotal];
            Array.Copy(times2.toArray(), 0, timesTotal, 0, times2.size());
            Array.Copy(times3.toArray(), 0, timesTotal, times2.size(), times3.size());
            assertEquals(sensiComputed.size(), 2);
            DoubleMatrix s2 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_L3_NAME, USD).Sensitivity;

            assertEquals(s2.columnCount(), paramsTotal);
            for (int i = 0; i < times2.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 2d * times2.get(i) * timesTotal[j];
                    assertEquals(s2.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS);
                }
            }
            DoubleMatrix s3 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_L6_NAME, USD).Sensitivity;

            assertEquals(s3.columnCount(), paramsTotal);
            for (int i = 0; i < times3.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 2d * times3.get(i) * timesTotal[j];
                    assertEquals(s3.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS);
                }
            }
            Optional <CrossGammaParameterSensitivity> oisSensi = sensiComputed.findSensitivity(RatesProviderDataSets.USD_DSC_NAME, USD);

            assertFalse(oisSensi.Present);
            Optional <CrossGammaParameterSensitivity> priceIndexSensi = sensiComputed.findSensitivity(RatesProviderDataSets.USD_CPI_NAME, USD);

            assertFalse(priceIndexSensi.Present);
        }
Exemple #5
0
        // single-node gamma PV01 for one scenario
        private CurrencyParameterSensitivities pv01SingleNodeGammaBucketed(ResolvedFraTrade trade, RatesProvider ratesProvider)
        {
            CrossGammaParameterSensitivities crossGamma = CROSS_GAMMA.calculateCrossGammaIntraCurve(ratesProvider, p => p.parameterSensitivity(tradePricer.presentValueSensitivity(trade, p)));

            return(crossGamma.diagonal().multipliedBy(ONE_BASIS_POINT * ONE_BASIS_POINT));
        }
Exemple #6
0
        public virtual void sensitivity_multi_combined_curve()
        {
            CrossGammaParameterSensitivities sensiCrossComputed = CENTRAL.calculateCrossGammaCrossCurve(RatesProviderDataSets.MULTI_CPI_USD_COMBINED, this.sensiCombinedFn);
            DoubleArray times1      = RatesProviderDataSets.TIMES_1; // ois
            DoubleArray times2      = RatesProviderDataSets.TIMES_2; // l3
            DoubleArray times3      = RatesProviderDataSets.TIMES_3; // l6
            DoubleArray times4      = RatesProviderDataSets.TIMES_4; // cpi
            int         paramsTotal = times1.size() + times2.size() + times3.size() + times4.size();

            double[]    timesTotal  = new double[paramsTotal];
            DoubleArray times1Twice = times1.multipliedBy(2d);

            Array.Copy(times4.toArray(), 0, timesTotal, 0, times4.size());
            Array.Copy(times1Twice.toArray(), 0, timesTotal, times4.size(), times1.size());
            Array.Copy(times2.toArray(), 0, timesTotal, times1.size() + times4.size(), times2.size());
            Array.Copy(times3.toArray(), 0, timesTotal, times1.size() + times2.size() + times4.size(), times3.size());

            assertEquals(sensiCrossComputed.size(), 4);
            DoubleMatrix s1 = sensiCrossComputed.getSensitivity(RatesProviderDataSets.USD_DSC_NAME, USD).Sensitivity;

            assertEquals(s1.columnCount(), paramsTotal);
            for (int i = 0; i < times1.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 4d * times1.get(i) * timesTotal[j];
                    assertEquals(s1.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s2 = sensiCrossComputed.getSensitivity(RatesProviderDataSets.USD_L3_NAME, USD).Sensitivity;

            assertEquals(s2.columnCount(), paramsTotal);
            for (int i = 0; i < times2.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 8d * times2.get(i) * timesTotal[j];
                    assertEquals(s2.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s3 = sensiCrossComputed.getSensitivity(RatesProviderDataSets.USD_L6_NAME, USD).Sensitivity;

            assertEquals(s3.columnCount(), paramsTotal);
            for (int i = 0; i < times3.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 2d * times3.get(i) * timesTotal[j];
                    assertEquals(s3.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s4 = sensiCrossComputed.getSensitivity(RatesProviderDataSets.USD_CPI_NAME, USD).Sensitivity;

            assertEquals(s4.columnCount(), paramsTotal);
            for (int i = 0; i < times4.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 2d * times4.get(i) * timesTotal[j];
                    assertEquals(s4.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 20d);
                }
            }

            CrossGammaParameterSensitivities sensiIntraComputed = CENTRAL.calculateCrossGammaIntraCurve(RatesProviderDataSets.MULTI_CPI_USD_COMBINED, this.sensiCombinedFn);
            DoubleMatrix s1Intra   = sensiIntraComputed.getSensitivity(RatesProviderDataSets.USD_DSC_NAME, USD).Sensitivity;
            DoubleMatrix s2Intra   = sensiIntraComputed.getSensitivity(RatesProviderDataSets.USD_L3_NAME, USD).Sensitivity;
            DoubleMatrix s3Intra   = sensiIntraComputed.getSensitivity(RatesProviderDataSets.USD_L6_NAME, USD).Sensitivity;
            DoubleMatrix s4Intra   = sensiIntraComputed.getSensitivity(RatesProviderDataSets.USD_CPI_NAME, USD).Sensitivity;
            int          offsetOis = times4.size();

            for (int i = 0; i < times1.size(); i++)
            {
                for (int j = 0; j < times1.size(); j++)
                {
                    assertEquals(s1Intra.get(i, j), s1.get(i, offsetOis + j), TOL);
                }
            }
            int offset3m = times4.size() + times1.size();

            for (int i = 0; i < times2.size(); i++)
            {
                for (int j = 0; j < times2.size(); j++)
                {
                    assertEquals(s2Intra.get(i, j), s2.get(i, offset3m + j), TOL);
                }
            }
            int offset6m = times4.size() + times1.size() + times2.size();

            for (int i = 0; i < times3.size(); i++)
            {
                for (int j = 0; j < times3.size(); j++)
                {
                    assertEquals(s3Intra.get(i, j), s3.get(i, offset6m + j), TOL);
                }
            }
            for (int i = 0; i < times4.size(); i++)
            {
                for (int j = 0; j < times4.size(); j++)
                {
                    assertEquals(s4Intra.get(i, j), s4.get(i, j), TOL);
                }
            }
        }
Exemple #7
0
        public virtual void sensitivity_cross_multi_curve()
        {
            CrossGammaParameterSensitivities sensiComputed = CENTRAL.calculateCrossGammaCrossCurve(RatesProviderDataSets.MULTI_CPI_USD, this.sensiFn);
            DoubleArray times1      = RatesProviderDataSets.TIMES_1;
            DoubleArray times2      = RatesProviderDataSets.TIMES_2;
            DoubleArray times3      = RatesProviderDataSets.TIMES_3;
            DoubleArray times4      = RatesProviderDataSets.TIMES_4;
            int         paramsTotal = times1.size() + times2.size() + times3.size() + times4.size();

            double[]    timesTotal  = new double[paramsTotal];
            DoubleArray times1Twice = times1.multipliedBy(2d);

            Array.Copy(times4.toArray(), 0, timesTotal, 0, times4.size());
            Array.Copy(times1Twice.toArray(), 0, timesTotal, times4.size(), times1.size());
            Array.Copy(times2.toArray(), 0, timesTotal, times1.size() + times4.size(), times2.size());
            Array.Copy(times3.toArray(), 0, timesTotal, times1.size() + times2.size() + times4.size(), times3.size());

            assertEquals(sensiComputed.size(), 4);
            DoubleMatrix s1 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_DSC_NAME, USD).Sensitivity;

            assertEquals(s1.columnCount(), paramsTotal);
            for (int i = 0; i < times1.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 4d * times1.get(i) * timesTotal[j];
                    assertEquals(s1.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s2 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_L3_NAME, USD).Sensitivity;

            assertEquals(s2.columnCount(), paramsTotal);
            for (int i = 0; i < times2.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 2d * times2.get(i) * timesTotal[j];
                    assertEquals(s2.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s3 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_L6_NAME, USD).Sensitivity;

            assertEquals(s3.columnCount(), paramsTotal);
            for (int i = 0; i < times3.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 2d * times3.get(i) * timesTotal[j];
                    assertEquals(s3.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 10d);
                }
            }
            DoubleMatrix s4 = sensiComputed.getSensitivity(RatesProviderDataSets.USD_CPI_NAME, USD).Sensitivity;

            assertEquals(s4.columnCount(), paramsTotal);
            for (int i = 0; i < times4.size(); i++)
            {
                for (int j = 0; j < paramsTotal; j++)
                {
                    double expected = 2d * times4.get(i) * timesTotal[j];
                    assertEquals(s4.get(i, j), expected, Math.Max(Math.Abs(expected), 1d) * EPS * 20d);
                }
            }
        }
        private CrossGammaParameterSensitivity combineSensitivities(CurrencyParameterSensitivity baseDeltaSingle, CrossGammaParameterSensitivities blockCrossGamma)
        {
            double[][] valuesTotal = new double[baseDeltaSingle.ParameterCount][];
//JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET:
//ORIGINAL LINE: java.util.List<com.opengamma.strata.collect.tuple.Pair<com.opengamma.strata.data.MarketDataName<?>, java.util.List<? extends com.opengamma.strata.market.param.ParameterMetadata>>> order = new java.util.ArrayList<>();
            IList <Pair <MarketDataName <object>, IList <ParameterMetadata> > > order = new List <Pair <MarketDataName <object>, IList <ParameterMetadata> > >();

            for (int i = 0; i < baseDeltaSingle.ParameterCount; ++i)
            {
                List <double> innerList = new List <double>();
                foreach (CrossGammaParameterSensitivity gammaSingle in blockCrossGamma.Sensitivities)
                {
                    innerList.AddRange(gammaSingle.Sensitivity.row(i).toList());
                    if (i == 0)
                    {
                        order.Add(gammaSingle.Order.get(0));
                    }
                }
                valuesTotal[i] = Doubles.toArray(innerList);
            }
            return(CrossGammaParameterSensitivity.of(baseDeltaSingle.MarketDataName, baseDeltaSingle.ParameterMetadata, order, baseDeltaSingle.Currency, DoubleMatrix.ofUnsafe(valuesTotal)));
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes cross-curve gamma by applying finite difference method to curve delta.
        /// <para>
        /// This computes the cross-curve gamma, i.e., the second order sensitivities to full curves.
        /// Thus the sensitivities of curve delta to other curves are produced.
        /// </para>
        /// <para>
        /// The sensitivities are computed for discount curves, and forward curves for {@code RateIndex} and {@code PriceIndex}.
        /// This implementation works only for single currency trades.
        ///
        /// </para>
        /// </summary>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="sensitivitiesFn">  the sensitivity function </param>
        /// <returns> the cross gamma </returns>
        public CrossGammaParameterSensitivities calculateCrossGammaCrossCurve(RatesProvider ratesProvider, System.Func <ImmutableRatesProvider, CurrencyParameterSensitivities> sensitivitiesFn)
        {
            ImmutableRatesProvider           immProv   = ratesProvider.toImmutableRatesProvider();
            CurrencyParameterSensitivities   baseDelta = sensitivitiesFn(immProv);   // used to check target sensitivity exits.
            CrossGammaParameterSensitivities result    = CrossGammaParameterSensitivities.empty();

            foreach (CurrencyParameterSensitivity baseDeltaSingle in baseDelta.Sensitivities)
            {
                CrossGammaParameterSensitivities resultInner = CrossGammaParameterSensitivities.empty();
                // discount curve
                foreach (KeyValuePair <Currency, Curve> entry in immProv.DiscountCurves.entrySet())
                {
                    Currency currency = entry.Key;
                    Curve    curve    = entry.Value;
                    if (baseDelta.findSensitivity(curve.Name, currency).Present)
                    {
                        CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(baseDeltaSingle, curve, c => immProv.toBuilder().discountCurve(currency, c).build(), sensitivitiesFn);
                        resultInner = resultInner.combinedWith(gammaSingle);
                    }
                    else if (curve.split().size() > 1)
                    {
                        ImmutableList <Curve> curves = curve.split();
                        int nCurves = curves.size();
                        for (int i = 0; i < nCurves; ++i)
                        {
                            int   currentIndex    = i;
                            Curve underlyingCurve = curves.get(currentIndex);
                            if (baseDelta.findSensitivity(underlyingCurve.Name, currency).Present)
                            {
                                CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(baseDeltaSingle, underlyingCurve, c => immProv.toBuilder().discountCurve(currency, curve.withUnderlyingCurve(currentIndex, c)).build(), sensitivitiesFn);
                                resultInner = resultInner.combinedWith(gammaSingle);
                            }
                        }
                    }
                }
                // forward curve
                foreach (KeyValuePair <Index, Curve> entry in immProv.IndexCurves.entrySet())
                {
                    Index index = entry.Key;
                    if (index is RateIndex || index is PriceIndex)
                    {
                        Currency currency = getCurrency(index);
                        Curve    curve    = entry.Value;
                        if (baseDelta.findSensitivity(curve.Name, currency).Present)
                        {
                            CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(baseDeltaSingle, curve, c => immProv.toBuilder().indexCurve(index, c).build(), sensitivitiesFn);
                            resultInner = resultInner.combinedWith(gammaSingle);
                        }
                        else if (curve.split().size() > 1)
                        {
                            ImmutableList <Curve> curves = curve.split();
                            int nCurves = curves.size();
                            for (int i = 0; i < nCurves; ++i)
                            {
                                int   currentIndex    = i;
                                Curve underlyingCurve = curves.get(currentIndex);
                                if (baseDelta.findSensitivity(underlyingCurve.Name, currency).Present)
                                {
                                    CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(baseDeltaSingle, underlyingCurve, c => immProv.toBuilder().indexCurve(index, curve.withUnderlyingCurve(currentIndex, c)).build(), sensitivitiesFn);
                                    resultInner = resultInner.combinedWith(gammaSingle);
                                }
                            }
                        }
                    }
                }
                result = result.combinedWith(combineSensitivities(baseDeltaSingle, resultInner));
            }
            return(result);
        }
        //-------------------------------------------------------------------------
        /// <summary>
        /// Computes intra-curve cross gamma for bond curves by applying finite difference method to curve delta.
        /// <para>
        /// This computes the intra-curve cross gamma, i.e., the second order sensitivities to individual curves.
        /// Thus the sensitivity of a curve delta to another curve is not produced.
        /// </para>
        /// <para>
        /// The underlying instruments must be single-currency, i.e., the curve currency must be the same as the sensitivity currency.
        ///
        /// </para>
        /// </summary>
        /// <param name="ratesProvider">  the rates provider </param>
        /// <param name="sensitivitiesFn">  the sensitivity function </param>
        /// <returns> the cross gamma </returns>
        public CrossGammaParameterSensitivities calculateCrossGammaIntraCurve(LegalEntityDiscountingProvider ratesProvider, System.Func <ImmutableLegalEntityDiscountingProvider, CurrencyParameterSensitivities> sensitivitiesFn)
        {
            LocalDate valuationDate = ratesProvider.ValuationDate;
            ImmutableLegalEntityDiscountingProvider immProv   = ratesProvider.toImmutableLegalEntityDiscountingProvider();
            CurrencyParameterSensitivities          baseDelta = sensitivitiesFn(immProv); // used to check target sensitivity exits
            CrossGammaParameterSensitivities        result    = CrossGammaParameterSensitivities.empty();

            // issuer curve
            foreach (KeyValuePair <Pair <LegalEntityGroup, Currency>, DiscountFactors> entry in immProv.IssuerCurves.entrySet())
            {
                Pair <LegalEntityGroup, Currency> legCcy = entry.Key;
                Currency  currency  = legCcy.Second;
                Curve     curve     = getCurve(entry.Value);
                CurveName curveName = curve.Name;
                if (baseDelta.findSensitivity(curveName, currency).Present)
                {
                    CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(curveName, curve, currency, c => replaceIssuerCurve(immProv, legCcy, DiscountFactors.of(currency, valuationDate, c)), sensitivitiesFn);
                    result = result.combinedWith(gammaSingle);
                }
                else
                {
                    ImmutableList <Curve> curves = curve.split();
                    int nCurves = curves.size();
                    if (nCurves > 1)
                    {
                        for (int i = 0; i < nCurves; ++i)
                        {
                            int       currentIndex        = i;
                            Curve     underlyingCurve     = curves.get(currentIndex);
                            CurveName underlyingCurveName = underlyingCurve.Name;
                            if (baseDelta.findSensitivity(underlyingCurveName, currency).Present)
                            {
                                CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(underlyingCurveName, underlyingCurve, currency, c => replaceIssuerCurve(immProv, legCcy, DiscountFactors.of(currency, valuationDate, curve.withUnderlyingCurve(currentIndex, c))), sensitivitiesFn);
                                result = result.combinedWith(gammaSingle);
                            }
                        }
                    }
                }
            }
            // repo curve
            foreach (KeyValuePair <Pair <RepoGroup, Currency>, DiscountFactors> entry in immProv.RepoCurves.entrySet())
            {
                Pair <RepoGroup, Currency> rgCcy = entry.Key;
                Currency  currency  = rgCcy.Second;
                Curve     curve     = getCurve(entry.Value);
                CurveName curveName = curve.Name;
                if (baseDelta.findSensitivity(curveName, currency).Present)
                {
                    CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(curveName, curve, currency, c => replaceRepoCurve(immProv, rgCcy, DiscountFactors.of(currency, valuationDate, c)), sensitivitiesFn);
                    result = result.combinedWith(gammaSingle);
                }
                else
                {
                    ImmutableList <Curve> curves = curve.split();
                    int nCurves = curves.size();
                    if (nCurves > 1)
                    {
                        for (int i = 0; i < nCurves; ++i)
                        {
                            int       currentIndex        = i;
                            Curve     underlyingCurve     = curves.get(currentIndex);
                            CurveName underlyingCurveName = underlyingCurve.Name;
                            if (baseDelta.findSensitivity(underlyingCurveName, rgCcy.Second).Present)
                            {
                                CrossGammaParameterSensitivity gammaSingle = computeGammaForCurve(underlyingCurveName, underlyingCurve, currency, c => replaceRepoCurve(immProv, rgCcy, DiscountFactors.of(currency, valuationDate, curve.withUnderlyingCurve(currentIndex, c))), sensitivitiesFn);
                                result = result.combinedWith(gammaSingle);
                            }
                        }
                    }
                }
            }
            return(result);
        }