/// <summary>Calculates the total margin of each regulation for the specified regulation role, value entities and parameter entities.</summary> /// <param name="regulationRole">An enumerator value of type <see cref="T:InitialMargin.Core.RegulationRole"/> that specifies the target regulation role.</param> /// <param name="values">The <see cref="System.Collections.Generic.ICollection{T}"/> of <see cref="T:InitialMargin.Core.DataValue"/> objects representing the target value entities.</param> /// <param name="parameters">The <see cref="System.Collections.Generic.ICollection{T}"/> of <see cref="T:InitialMargin.Core.DataParameter"/> objects representing the target parameter entities.</param> /// <returns>An <see cref="System.Collections.Generic.IDictionary{TKey,TValue}"/> of pairs defined by <see cref="T:InitialMargin.Core.Regulation"/> keys and <see cref="T:InitialMargin.Core.Amount"/> values representing the regulation/margin couples.</returns> /// <exception cref="T:System.ArgumentNullException">Thrown when <paramref name="values">values</paramref> is <c>null</c> or when <paramref name="parameters">parameters</paramref> is <c>null</c>.</exception> /// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">Thrown when <paramref name="regulationRole">regulationRole</paramref> is undefined.</exception> public IDictionary <Regulation, MarginTotal> CalculateDetailedByRole(RegulationRole regulationRole, ICollection <DataValue> values, ICollection <DataParameter> parameters) { if (!Enum.IsDefined(typeof(RegulationRole), regulationRole)) { throw new InvalidEnumArgumentException("Invalid regulation role specified."); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } List <Regulation> regulations = values.SelectMany(x => SelectRegulations(x, regulationRole)) .Concat(parameters.SelectMany(x => SelectRegulations(x, regulationRole))) .OrderBy(x => x) .Distinct().ToList(); if (regulations.Count == 0) { return(new Dictionary <Regulation, MarginTotal>()); } List <DataValue> valuesFinal = values.Where(x => !(x is PresentValue) && !(x is Sensitivity)).Select(x => (DataValue)x.Clone()) .Concat(values.OfType <PresentValue>().Select(x => AdjustedClone(x, regulationRole))) .Concat(values.OfType <Sensitivity>().Select(x => AdjustedClone(x, regulationRole))) .ToList(); List <DataParameter> parametersFinal = parameters .Select(x => (DataParameter)x.Clone()) .ToList(); Dictionary <Regulation, MarginTotal> result = new Dictionary <Regulation, MarginTotal>(); foreach (Regulation regulation in regulations) { List <DataValue> valuesByRegulation = valuesFinal.Where(x => SelectRegulations(x, regulationRole).Contains(regulation)).ToList(); List <DataParameter> parametersByRegulation = parametersFinal.Where(x => SelectRegulations(x, regulationRole).Contains(regulation)).ToList(); List <IMargin> margins = new List <IMargin>(m_Processors.Count); foreach (Processor processor in m_Processors) { margins.Add(processor.Process(valuesByRegulation, parametersByRegulation)); } result[regulation] = MarginTotal.Of(regulationRole, regulation, m_ValuationDate, m_CalculationCurrency, margins); } return(result); }
private MarginTotal Process(List <Notional> notionals, List <PresentValue> presentValues) { if (notionals == null) { throw new ArgumentNullException(nameof(notionals)); } if (presentValues == null) { throw new ArgumentNullException(nameof(presentValues)); } List <ScheduleObject> scheduleObjects = SanitizeData(notionals, presentValues); if (scheduleObjects.Count == 0) { return(MarginTotal.Of(m_ValuationDate, m_CalculationCurrency)); } HashSet <Product> products = new HashSet <Product>(); List <Notional> notionalsNetted = new List <Notional>(scheduleObjects.Count); List <PresentValue> presentValuesNetted = new List <PresentValue>(scheduleObjects.Count); foreach (ScheduleObject obj in scheduleObjects) { Amount notionalsSum = Amount.Abs(Amount.Sum(obj.Notionals.Select(x => x.Amount), m_CalculationCurrency)); notionalsNetted.Add(Notional.Of(obj.Product, notionalsSum, RegulationsInfo.Empty, obj.TradeInfo)); Amount presentValuesSum = Amount.Sum(obj.PresentValues.Select(x => x.Amount), m_CalculationCurrency); presentValuesNetted.Add(PresentValue.Of(obj.Product, presentValuesSum, RegulationsInfo.Empty, obj.TradeInfo)); products.Add(obj.Product); } List <MarginProduct> productMargins = new List <MarginProduct>(products.Count); foreach (Product product in products.OrderBy(x => x)) { List <Notional> notionalsByProduct = notionalsNetted.Where(x => x.Product == product).ToList(); List <PresentValue> presentValuesByProduct = presentValuesNetted.Where(x => x.Product == product).ToList(); MarginProduct productMargin = ScheduleCalculations.CalculateMarginProduct(m_ValuationDate, m_CalculationCurrency, product, notionalsByProduct, presentValuesByProduct); productMargins.Add(productMargin); } Margin scheduleMargin = ScheduleCalculations.CalculateMargin(m_ValuationDate, m_CalculationCurrency, productMargins, notionals, presentValues); return(MarginTotal.Of(m_ValuationDate, m_CalculationCurrency, scheduleMargin)); }
/// <summary>Calculates the total margin for the specified regulation role, value entities and parameter entities.</summary> /// <param name="regulationRole">An enumerator value of type <see cref="T:InitialMargin.Core.RegulationRole"/> that specifies the target regulation role.</param> /// <param name="values">The <see cref="System.Collections.Generic.ICollection{T}"/> of <see cref="T:InitialMargin.Core.DataValue"/> objects representing the target value entities.</param> /// <param name="parameters">The <see cref="System.Collections.Generic.ICollection{T}"/> of <see cref="T:InitialMargin.Core.DataParameter"/> objects representing the target parameter entities.</param> /// <returns>A <see cref="T:InitialMargin.Core.MarginTotal"/> object representing the total margin.</returns> /// <exception cref="T:System.ArgumentNullException">Thrown when <paramref name="values">values</paramref> is <c>null</c> or when <paramref name="parameters">parameters</paramref> is <c>null</c>.</exception> /// <exception cref="T:System.InvalidOperationException">Thrown when <paramref name="values">values</paramref> contains elements defined on different regulations or when <paramref name="parameters">parameters</paramref> contains elements defined on different regulations.</exception> /// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">Thrown when <paramref name="regulationRole">regulationRole</paramref> is undefined.</exception> public MarginTotal CalculateDetailed(RegulationRole regulationRole, ICollection <DataValue> values, ICollection <DataParameter> parameters) { if (!Enum.IsDefined(typeof(RegulationRole), regulationRole)) { throw new InvalidEnumArgumentException("Invalid regulation role specified."); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } List <Regulation> regulations = values.SelectMany(x => SelectRegulations(x, regulationRole)) .Concat(parameters.SelectMany(x => SelectRegulations(x, regulationRole))) .OrderBy(x => x) .Distinct().ToList(); if (regulations.Count > 1) { throw new InvalidOperationException($"All data entities must either have no regulations defined or belong to a single {((regulationRole == RegulationRole.Pledgor) ? "post" : "collect")} regulation."); } List <DataValue> valuesFinal = values.Where(x => !(x is PresentValue) && !(x is Sensitivity)).Select(x => (DataValue)x.Clone()) .Concat(values.OfType <PresentValue>().Select(x => AdjustedClone(x, regulationRole))) .Concat(values.OfType <Sensitivity>().Select(x => AdjustedClone(x, regulationRole))) .ToList(); List <DataParameter> parametersFinal = parameters .Select(x => (DataParameter)x.Clone()) .ToList(); List <IMargin> margins = new List <IMargin>(m_Processors.Count); foreach (Processor processor in m_Processors) { margins.Add(processor.Process(valuesFinal, parametersFinal)); } return(MarginTotal.Of(regulationRole, regulations.Single(), m_ValuationDate, m_CalculationCurrency, margins)); }
private MarginTotal Process(List <Sensitivity> sensitivities, List <AddOnProductMultiplier> productMultipliers, List <AddOnNotional> notionals, List <AddOnNotionalFactor> notionalFactors, List <AddOnFixedAmount> fixedAmounts) { if (sensitivities == null) { throw new ArgumentNullException(nameof(sensitivities)); } if (productMultipliers == null) { throw new ArgumentNullException(nameof(productMultipliers)); } if (notionals == null) { throw new ArgumentNullException(nameof(notionals)); } if (notionalFactors == null) { throw new ArgumentNullException(nameof(notionalFactors)); } if (fixedAmounts == null) { throw new ArgumentNullException(nameof(fixedAmounts)); } ModelObject?modelObject = SanitizeData(sensitivities, productMultipliers, notionals, notionalFactors, fixedAmounts); if (!modelObject.HasValue) { return(MarginTotal.Of(m_ValuationDate, m_CalculationCurrency)); } ModelObject modelObjectValue = modelObject.Value; sensitivities = modelObjectValue.Sensitivities; notionals = modelObjectValue.Notionals; notionalFactors = modelObjectValue.NotionalFactors; productMultipliers = modelObjectValue.ProductMultipliers; fixedAmounts = modelObjectValue.FixedAmounts; List <Sensitivity> sensitivitiesVega = sensitivities .RemoveAllAndGet(x => x.Category == SensitivityCategory.Vega) .ToList(); if (sensitivitiesVega.Count > 0) { List <Sensitivity> sensitivitiesCurvature = sensitivitiesVega .Select(x => x.ToCurvature(ModelCalculations.CalculateCurvatureAmount(x))) .ToList(); List <Sensitivity> sensitivitiesVolatilityWeighted = sensitivitiesVega .Concat(sensitivitiesCurvature) .ToList(); foreach (Sensitivity sensitivity in sensitivitiesVolatilityWeighted) { sensitivity.ChangeAmount(sensitivity.Amount * ModelParameters.GetWeightVolatility(sensitivity)); } sensitivities.AddRange(sensitivitiesVolatilityWeighted); } List <Sensitivity> sensitivitiesNetted = ModelCalculations.NetSensitivities(m_CalculationCurrency, sensitivities); List <MarginProduct> productMargins = ModelCalculations.CalculateMarginsProduct(m_CalculationCurrency, m_RatesProvider, sensitivitiesNetted); Amount productMarginsAmount = Amount.Sum(productMargins.Select(x => x.Value), m_CalculationCurrency); MarginAddOn addOnMargin = ModelCalculations.CalculateMarginAddOn(m_CalculationCurrency, productMargins, productMultipliers, notionals, notionalFactors, fixedAmounts); Amount addOnMarginAmount = addOnMargin?.Value ?? Amount.OfZero(m_CalculationCurrency); Amount modelMarginAmount = productMarginsAmount + addOnMarginAmount; Margin modelMargin = Margin.Of(modelMarginAmount, productMargins, addOnMargin); return(MarginTotal.Of(m_ValuationDate, m_CalculationCurrency, modelMargin)); }