//------------------------------------------------------------------------- /// <summary> /// Computes the first order sensitivities of a function of a LegalEntityDiscountingProvider to a double by finite difference. /// <para> /// The finite difference is computed by forward type. /// The function should return a value in the same currency for any rates provider of LegalEntityDiscountingProvider. /// /// </para> /// </summary> /// <param name="provider"> the rates provider </param> /// <param name="valueFn"> the function from a rate provider to a currency amount for which the sensitivity should be computed </param> /// <returns> the curve sensitivity </returns> public virtual CurrencyParameterSensitivities sensitivity(LegalEntityDiscountingProvider provider, System.Func <ImmutableLegalEntityDiscountingProvider, CurrencyAmount> valueFn) { ImmutableLegalEntityDiscountingProvider immProv = provider.toImmutableLegalEntityDiscountingProvider(); CurrencyAmount valueInit = valueFn(immProv); CurrencyParameterSensitivities discounting = sensitivity(immProv, valueFn, ImmutableLegalEntityDiscountingProvider.meta().repoCurves(), valueInit); CurrencyParameterSensitivities forward = sensitivity(immProv, valueFn, ImmutableLegalEntityDiscountingProvider.meta().issuerCurves(), valueInit); return(discounting.combinedWith(forward)); }
//------------------------------------------------------------------------- /// <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); }