private CrossGammaParameterSensitivity computeGammaForCurve(CurveName curveName, Curve curve, Currency sensitivityCurrency, System.Func <Curve, ImmutableLegalEntityDiscountingProvider> ratesProviderFn, System.Func <ImmutableLegalEntityDiscountingProvider, CurrencyParameterSensitivities> sensitivitiesFn) { System.Func <DoubleArray, DoubleArray> function = (DoubleArray t) => { Curve newCurve = curve.withPerturbation((i, v, m) => t.get(i)); ImmutableLegalEntityDiscountingProvider newRates = ratesProviderFn(newCurve); CurrencyParameterSensitivities sensiMulti = sensitivitiesFn(newRates); return(sensiMulti.getSensitivity(curveName, sensitivityCurrency).Sensitivity); }; int nParams = curve.ParameterCount; DoubleMatrix sensi = fd.differentiate(function).apply(DoubleArray.of(nParams, n => curve.getParameter(n))); IList <ParameterMetadata> metadata = IntStream.range(0, nParams).mapToObj(i => curve.getParameterMetadata(i)).collect(toImmutableList()); return(CrossGammaParameterSensitivity.of(curveName, metadata, sensitivityCurrency, sensi)); }
// computes the sensitivity of baseDeltaSingle to Curve internal CrossGammaParameterSensitivity computeGammaForCurve(CurrencyParameterSensitivity baseDeltaSingle, Curve curve, System.Func <Curve, ImmutableRatesProvider> ratesProviderFn, System.Func <ImmutableRatesProvider, CurrencyParameterSensitivities> sensitivitiesFn) { System.Func <DoubleArray, DoubleArray> function = (DoubleArray t) => { Curve newCurve = replaceParameters(curve, t); ImmutableRatesProvider newRates = ratesProviderFn(newCurve); CurrencyParameterSensitivities sensiMulti = sensitivitiesFn(newRates); return(sensiMulti.getSensitivity(baseDeltaSingle.MarketDataName, baseDeltaSingle.Currency).Sensitivity); }; int nParams = curve.ParameterCount; DoubleMatrix sensi = fd.differentiate(function).apply(DoubleArray.of(nParams, n => curve.getParameter(n))); IList <ParameterMetadata> metadata = IntStream.range(0, nParams).mapToObj(i => curve.getParameterMetadata(i)).collect(toImmutableList()); return(CrossGammaParameterSensitivity.of(baseDeltaSingle.MarketDataName, baseDeltaSingle.ParameterMetadata, curve.Name, metadata, baseDeltaSingle.Currency, sensi)); }
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); }