internal static bool Approve(Approval approval, ISINAvailability availability)
 {
     if (approval == null || availability == null || Math.Abs(approval.Amount) > availability.Available)
     {
         return false;
     }
     return true;
 }
        internal List<ISINAvailability> GetISINAvailability(DateTime settleDate)
        {
            //1. Get limits by ISIN (aggregate party limits)
            //2. Get approvals by ISIN (aggregate approvals)
            //3. Merge results
            //4. Include open positions

            List<PartyLimit> partyLimits = GetShortSalePartyLimits(settleDate);
            IEnumerable<IGrouping<String,PartyLimit>> partyLimitsByISIN =
                partyLimits.GroupBy(o => o.ISIN, o => o);
            IEnumerable<ISINAvailability> isinsLocated = partyLimitsByISIN.Select(o => new ISINAvailability
                {
                    ISIN = o.Key,
                    Date = settleDate,
                    Maturity = o.Max(p => p.Maturity),
                    Description = o.Max(p => p.Description),
                    Located = o.Sum(p => p.Size)
                });

            List<Approval> approvals = GetShortSaleApprovalRequests(settleDate);
            IEnumerable<IGrouping<String, Approval>> approvalsByISIN =
                approvals.Where(o => o.ApprovalStatus.Code == ApprovalStatus.Approved.Code).GroupBy(o => o.ISIN, o => o);
            IEnumerable<ISINAvailability> isinsApproved = approvalsByISIN.Select(o => new ISINAvailability
            {
                ISIN = o.Key,
                Date = o.Max(p => p.SettlementDate),
                Approved = o.Sum(p => p.Amount)
            });

            List<ISINAvailability> merged = isinsLocated.GroupJoin(
                 isinsApproved,
                 loc => new { loc.ISIN, loc.Date },
                 app => new { app.ISIN, app.Date },
                 (x, y) => new ISINAvailability
                 {
                     ISIN = x.ISIN,
                     Date = x.Date,
                     Maturity = x.Maturity,
                     Description = x.Description,
                     Located = x.Located,
                     Approved = y.SingleOrDefault() == null ? 0.0M : y.Single().Approved
                 }
             ).ToList();

            List<ISINAvailability> isinAvailabilityList =
                merged.Union(isinsApproved.Except(merged.Intersect(isinsLocated))).ToList();

            var currentPositions = OrchestradeUtils.GetPositionsForDate(settleDate, "Bond", "Repo", "ReverseRepo");
            foreach(var position in currentPositions)
            {
                var ia = isinAvailabilityList.FirstOrDefault(o => o.ISIN == position.Product.Isin);
                if(ia == null)
                {
                    ia = new ISINAvailability();
                    ia.ISIN = position.Product.Isin;
                    ia.Date = settleDate;
                    ia.Description = position.ProductDescription;
                    isinAvailabilityList.Add(ia);
                }
                if (ia.Maturity == null)
                {
                    ia.Maturity = position.Product.RiskMaturity.ToDateTime();
                }
                ia.CurrentPosition = ia.CurrentPosition + Convert.ToDecimal(position.TotalSettledNominal);
            }

            var openPositions = OrchestradeUtils.GetPositionsForDate(OrchestradeUtils.GetRelativeBusinessDate(settleDate, -1), "Bond", "Repo", "ReverseRepo");
            var trades = OrchestradeUtils.GetTradesForDateRange(null, settleDate, settleDate, "Bond", "Repo", "ReverseRepo");
            var maturingRepos = OrchestradeUtils.GetTradesForMaturityDate(null, settleDate, "Repo", "ReverseRepo");
            foreach (var ia in isinAvailabilityList)
            {
                var openingPositionValue = openPositions.
                    Where(o => o.Product.Isin.Equals(ia.ISIN, StringComparison.InvariantCultureIgnoreCase)).
                    Sum(o => o.TotalSettledNominal);

                ia.OpeningPosition = Convert.ToDecimal(openingPositionValue);

                Product p = Env.Current.Trade.GetProductByCode(Product.IsinProductCode, ia.ISIN);
                if (p != null)
                {
                    //ia.Trades = Convert.ToDecimal(
                    //    trades.Where(o => o.Product.UnderlyingAsset.Id == p.Id).Sum(o => o.Product.UnderlierNominal(o, o.TradeTime)));
                    ia.BondTrades = Convert.ToDecimal(
                        trades.Where(o => o.Product.UnderlyingAsset.Id == p.Id && o.Product.ProcessingType == "Bond")
                            .Sum(o => o.Product.UnderlierNominal(o, o.TradeTime)));
                    ia.RepoTrades = Convert.ToDecimal(
                        trades.Where(o => o.Product.UnderlyingAsset.Id == p.Id && o.Product.ProcessingType != "Bond")
                            .Sum(o => o.Product.UnderlierNominal(o, o.TradeTime)));
                    ia.MaturingRepos = Convert.ToDecimal(
                        -1 * maturingRepos.Where(o => o.Product.UnderlyingAsset.Id == p.Id).Sum(o => o.Product.UnderlierNominal(o, o.TradeTime)));
                }
            }

            return isinAvailabilityList;
        }