public override MarginSensitivity CalculateMargin(Currency calculationCurrency, FxRatesProvider ratesProvider, SensitivityRisk risk, SensitivityCategory category, List <Sensitivity> sensitivities) { if (calculationCurrency == null) { throw new ArgumentNullException(nameof(calculationCurrency)); } if (ratesProvider == null) { throw new ArgumentNullException(nameof(ratesProvider)); } if (!Enum.IsDefined(typeof(SensitivityRisk), risk)) { throw new InvalidEnumArgumentException("Invalid sensitivity risk specified."); } if (!Enum.IsDefined(typeof(SensitivityCategory), category)) { throw new InvalidEnumArgumentException("Invalid sensitivity category specified."); } if (sensitivities == null) { throw new ArgumentNullException(nameof(sensitivities)); } List <IBucket> buckets = sensitivities.Select(x => x.Bucket).Distinct().OrderBy(x => x.Name).ToList(); List <MarginBucket> bucketMargins = new List <MarginBucket>(buckets.Count); foreach (IBucket bucket in buckets) { List <Sensitivity> sensitivitiesByBucket = sensitivities.Where(x => x.Bucket == bucket).ToList(); List <MarginWeighting> weightingMargins = CalculateMarginsWeighting(SensitivityCategory.Curvature, sensitivitiesByBucket); Amount sumSquared = Amount.Sum(weightingMargins.Select(x => Amount.Square(x.Value)), calculationCurrency); Amount sumCorrelated = CalculateCorrelatedSumWeights(calculationCurrency, risk, weightingMargins); Amount bucketMarginAmount = Amount.SquareRoot(sumSquared + sumCorrelated); bucketMargins.Add(MarginBucket.Of(bucket, bucketMarginAmount, weightingMargins)); } Amount marginNonResidual = CalculateMarginByBuckets(calculationCurrency, risk, false, bucketMargins); Amount marginResidual = CalculateMarginByBuckets(calculationCurrency, risk, true, bucketMargins); Amount sensitivityMarginAmount = ModelParameters.GetCurvatureScaleFactor(risk) * (marginNonResidual + marginResidual); return(MarginSensitivity.Of(SensitivityCategory.Curvature, sensitivityMarginAmount, bucketMargins)); }