public static MarginProduct CalculateMarginProduct(DateTime valuationDate, Currency calculationCurrency, Product product, List <Notional> notionals, List <PresentValue> presentValues)
        {
            if (calculationCurrency == null)
            {
                throw new ArgumentNullException(nameof(calculationCurrency));
            }

            if (!Enum.IsDefined(typeof(Product), product))
            {
                throw new InvalidEnumArgumentException("Invalid product specified.");
            }

            if (notionals == null)
            {
                throw new ArgumentNullException(nameof(notionals));
            }

            if (presentValues == null)
            {
                throw new ArgumentNullException(nameof(presentValues));
            }

            Amount  netReplacementCost   = Amount.Max(Amount.Sum(presentValues.Select(x => - x.Amount), calculationCurrency), 0m);
            Amount  grossReplacementCost = Amount.Sum(presentValues.Select(x => Amount.Max(-x.Amount, 0m)), calculationCurrency);
            Decimal ngRatio = grossReplacementCost.IsZero ? 1m : (netReplacementCost / grossReplacementCost).Value;

            Amount  marginAmountGross = Amount.Sum(notionals.Select(x => Amount.Abs(x.Amount) * ScheduleParameters.GetNotionalFactor(valuationDate, x)), calculationCurrency);
            Decimal marginFactor      = ScheduleParameters.GetMarginFactor(ngRatio);
            Amount  marginAmountNet   = marginAmountGross * marginFactor;

            return(MarginProduct.Of(product, marginAmountNet));
        }
Exemple #2
0
        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));
        }