using DocumentFormat.OpenXml.Drawing.Charts; using Newtonsoft.Json; using NPOI.SS.Formula.Functions; using NPOI.SS.UserModel; using Org.BouncyCastle.Asn1.Ocsp; using YieldChain.Helpers; using YLErp.BLL; using YLErp.BLL.MarginCalculation; using YLErp.Configuration; using YLErp.DBModels; using YLErp.DBModels.Enums; using YLErp.Helpers; using YLErp.Model; using YLErp.Model.Enum; using YLErp.Models; using YLErp.Modules.CalculationModule; using YLErp.Modules.EodModule.QueryModule; using YLErp.Modules.TradeRiskCalcModule; namespace YLErp.Modules.EodModule.SettlementModule { /// /// 客户结算 /// public class EodClientBalanceCalc : EodSettleServiceBaseV2 { public EodClientBalanceCalc(EodSettlementContextV2 context) : base(context) { } /// /// 客户结算 /// public bool ClientBalanceCalc() { var balanceDate = _context.SettleDate; var reqClientIds = _context.Request.ClientIds; var clientDb = DbContextFactory.GetClientDbContext(OptUser); var currencyCodes = _context.CurrencyCodes; var currencyProvider = _context.EodCurrencyProvider; //预付金可取上浮比率 var marginRatio = Math.Round((decimal)(_context.SystemValue.MarginRatio ?? 0.15), 2, MidpointRounding.AwayFromZero); var marginMaxRatio = marginRatio + 0.02m; var preBalanceDate = _context.PreSettleDate; var preClientbalancedailys = DbContext.ClientBalanceDaily.Where(t => t.BalanceDate == preBalanceDate).ToList(); if (reqClientIds != null && reqClientIds.Any()) { preClientbalancedailys = preClientbalancedailys.Where(t => reqClientIds.Contains(t.ClientId)).ToList(); } //获取所有客户信息 var clients = clientDb.client.Where(t => t.ProcessStatus != "未提交").ToList(); if (reqClientIds != null && reqClientIds.Any()) { clients = clients.Where(t => reqClientIds.Contains(t.id)).ToList(); } var allClientIds = clients.Select(t => t.id).ToList(); #region 客户结算相关数据初始化 eod_trade_position client_span eod_trade eodPrice //获取所有客户授信 var creditList = DbContext.credit.Where(t => t.ProcessStatus == "已审批" && (!t.CreditDeadLine.HasValue || t.CreditDeadLine >= balanceDate) && (!t.CreditStartDate.HasValue || t.CreditStartDate <= balanceDate)).ToList(); if (reqClientIds != null && reqClientIds.Any()) { creditList = creditList.Where(t => reqClientIds.Contains(t.ClientId ?? 0)).ToList(); } //获取所有资信等级 var creditRatingList = clientDb.credit_rating.Where(t => t.ValidState != "InValid").ToList(); //出入金记录 获取上个结算日到当前结算日之间的所有已结算和已确认的出入金(包含周末的出入金) var newValuedate = balanceDate.AddDays(1); var lastBalanceDateAddOne = preBalanceDate.AddDays(1); var entryexits = from cash in DbContext.ClientCashInCashOut.Where(t => t.ValidState != "InValid" && (t.HappenDate >= lastBalanceDateAddOne && t.HappenDate < newValuedate && (t.State == ClientCashInCashOut.已结算 || t.State == ClientCashInCashOut.已确认))) join trade in DbContext.trade on cash.TradeId equals trade.id into trade from td in trade.DefaultIfEmpty() where td.TradeType != "收益互换" && td.ValidState != ConsGlobal.InValid select cash; if (reqClientIds != null && reqClientIds.Any()) { entryexits = entryexits.Where(t => reqClientIds.Contains(t.ClientId ?? 0)); } var entryexits_swapAll = from cash in DbContext.ClientCashInCashOut.Where(t => t.ValidState != "InValid" && (t.HappenDate >= lastBalanceDateAddOne && (t.State == ClientCashInCashOut.已结算 || t.State == ClientCashInCashOut.已确认))) join trade in DbContext.trade.Where(x => x.TradeType == "收益互换") on cash.TradeId equals trade.id select cash; if (reqClientIds != null && reqClientIds.Any()) { entryexits_swapAll = entryexits_swapAll.Where(t => reqClientIds.Contains(t.ClientId ?? 0)); } var entryexits_swap = entryexits_swapAll.Where(t => t.HappenDate < newValuedate); var entryexits_swapFuture = entryexits_swapAll.Where(t => t.HappenDate >= newValuedate); //获取客户所有现存(抵押状态)抵押品信息 var clientProductList = (from product in DbContext.clientcashincashout_product join variety in DbContext.variety on product.VarietyId equals variety.id into varietyTemp from variety in varietyTemp.DefaultIfEmpty() join um in DbContext.underlying_manager on product.UnderlyingId equals um.id into umTemp from um in umTemp.DefaultIfEmpty() where (product.Status == Clientcashincashout_productStatusEnum.抵押.ToString() && product.OptStatus == ClientCashInCashOut.已确认 || product.Status == Clientcashincashout_productStatusEnum.赎回.ToString() && product.OptStatus != ClientCashInCashOut.已确认 || product.Status == Clientcashincashout_productStatusEnum.赎回.ToString() && product.OptStatus == ClientCashInCashOut.已确认 && product.BackDate >= newValuedate) && allClientIds.Contains(product.ClientId) && product.HappenDate < newValuedate select new { product, variety, um }).ToList(); if (reqClientIds != null && reqClientIds.Any()) { clientProductList = clientProductList.Where(t => reqClientIds.Contains(t.product.ClientId)).ToList(); } //获取所有用户当日Eod_Risk var eodRiskList = DbContext.eod_trade_risk.Where(t => t.ValueDate == balanceDate).ToList(); if (reqClientIds != null && reqClientIds.Any()) { eodRiskList = eodRiskList.Where(t => reqClientIds.Contains(t.ClientId)).ToList(); } //获取客户导入的所有持仓信息 -- 收益互换(国君) var EodPositionSwapMannual = DbContext.eod_trade_position_swap_mannual.Where(x => x.ValueDate == balanceDate).ToList(); if (reqClientIds != null && reqClientIds.Any()) { EodPositionSwapMannual = EodPositionSwapMannual.Where(t => reqClientIds.Contains(t.ClientId)).ToList(); } // 互换合约估值信息 var eodSwapQuery = from eod in DbContext.eod_swap.Where(x => x.ValueDate <= balanceDate && x.ValueDate >= preBalanceDate) join t in DbContext.trade.Where(x => x.TradeType == "收益互换" && x.ValidState != ConsGlobal.InValid && ConsTrade.TradeStatusAfterConfirmed.Contains(x.TradeStatus) && x.TradeDate <= balanceDate) on eod.SwapTradeId equals t.id select eod; // 互换合约估值持仓信息 var eodSwapPosiQuery = from eod in DbContext.eod_swap_position.Where(x => x.ValueDate <= balanceDate && x.ValueDate >= preBalanceDate) join t in DbContext.trade.Where(x => x.TradeType == "收益互换" && x.ValidState != ConsGlobal.InValid && ConsTrade.TradeStatusAfterConfirmed.Contains(x.TradeStatus) && x.TradeDate <= balanceDate) on eod.SwapTradeId equals t.id select eod; var positionList = DbContext.trade.Where(t => (ConsTrade.TradeStatusAfterConfirmed.Contains(t.TradeStatus)||t.UnWindDate> balanceDate) && t.ValidState != "InValid"&&t.TradeType=="收益互换"); var marignQuery = from t in positionList join s in DbContext.eod_swap_position on t.id equals s.SwapTradeId where ConsTrade.InterestMarginModels.Contains(s.InterestMode) && !s.Invalid && s.HappenDate <= balanceDate &&s.ValueDate==balanceDate select new { ClientId = t.ClientId, StructureType = t.StructureType, marin = s.InterestPrincipalFix * (s.InterestDirection == 1 ? -1m : 1m) }; // 互换平仓信息 var clientEventFlowQuery = from eod in DbContext.swap_flow_event.Where(x => x.EventDate <= balanceDate && x.EventDate > preBalanceDate && x.DataState == (int)SwapFlowDateStateEnum.完成 && x.EventType == (int)SwapFlowEventTypeEnum.平仓) join t in DbContext.trade.Where(x => x.TradeType == "收益互换" && x.ValidState != ConsGlobal.InValid && ConsTrade.TradeStatusAfterConfirmed.Contains(x.TradeStatus) && x.TradeDate <= balanceDate) on eod.SwapTradeId equals t.id select eod; var clientEventFlows = clientEventFlowQuery.ToList(); var eodSwaps = eodSwapQuery.ToList(); var eodSwapPosis = eodSwapPosiQuery.ToList(); if (reqClientIds != null && reqClientIds.Any()) { eodSwaps = eodSwaps.Where(t => reqClientIds.Contains(t.ClientId)).ToList(); eodSwapPosis= eodSwapPosis.Where(t => reqClientIds.Contains(t.ClientId)).ToList(); marignQuery = marignQuery.Where(t => reqClientIds.Contains(t.ClientId)); clientEventFlows.Where(t => reqClientIds.Contains(t.ClientId??0)); } var swapIds = eodSwaps.Select(s => s.SwapTradeId); var todaySwapTrades = DbContext.trade.Where(t => swapIds.Contains(t.id)).ToList(); // var swapMargins = DbContext.trade_initial_margin.Where(t => swapIds.Contains(t.TradeId)).ToList(); var underlyDataSource = DataCacheProvider.GetUnderlyingDataSource(); var varietyDataSource = DataCacheProvider.GetVarietyDataSource(); //客户预付金 var clientSpanList = DbContext.client_span.Where(t => t.ValueDate == balanceDate).ToList(); if (reqClientIds != null && reqClientIds.Any()) { clientSpanList = clientSpanList.Where(t => reqClientIds.Contains(t.ClientId)).ToList(); } //clientbalance var newClientBalanceDaily = new List(); //获取客户所有交易信息(所及为客户所有确认交易,以及当日平仓或者当日执行的交易) var trades = _context.OtcTrades.ToList(); //如果前一天是假日,要显示包含假日的交易 var preday = balanceDate.AddDays(-1); //获取上一个交易日的下一天(例如收盘日是周一,上一个交易日就是周五,他的下一天就是周六,获取的是周六) var nonHolidayAddOne = valuedateBLL.GetNonHolidayDefore(preday).AddDays(1); var finishedTradeCash = DbContext.trade_cash .Where(tc => (tc.ValueDate >= nonHolidayAddOne && tc.ValueDate <= balanceDate && tc.HappenedDate == null || tc.HappenedDate >= nonHolidayAddOne && tc.HappenedDate <= balanceDate) && tc.ValidState != ConsGlobal.InValid && !tc.IsDeleted && (tc.Action == ClientCashInCashOut.系统操作_平仓费 || tc.Action == ClientCashInCashOut.系统操作_行权费 || tc.Action == ClientCashInCashOut.系统操作_互换 || tc.Action == ClientCashInCashOut.系统操作_票息 || tc.Action == ClientCashInCashOut.人工操作_其他)); var finishedTradeNotionalPercentDic = finishedTradeCash .AsEnumerable() .GroupBy(tc => tc.TradeId) .ToDictionary(g => g.Key, g => g.Sum(tc => tc.UnwindPercentRate ?? 0)); var keys = finishedTradeNotionalPercentDic.Select(d => d.Key).ToArray(); var dayeods = _context.GetEodPriceProvider(); //期权交易行权平仓产生的资金流水 //var tradeCashList = db.trade_cash.Where(t => allTradeIds.Contains(t.TradeId)).ToList(); //获取冻结资金信息 var clientFrozenFunds = new ClientFrozenFundsService(this).GetDatas(balanceDate, allClientIds); #endregion #region 循环客户信息计算客户资金信息 foreach (var client in clients) { _context.CancellationToken.ThrowIfCancellationRequested(); #region 变量初始化 List clientEntryexits; List clientEntryexits_swap; FundObject fundObject = new FundObject(); foreach (var currencyCode in currencyCodes) { fundObject.InFund.Add(currencyCode, 0); fundObject.VmInFund.Add(currencyCode, 0); fundObject.OutFund.Add(currencyCode, 0); fundObject.VmOutFund.Add(currencyCode, 0); fundObject.NetFund.Add(currencyCode, 0); fundObject.InFundOther.Add(currencyCode, 0); fundObject.OutFundOther.Add(currencyCode, 0); fundObject.OtherFund.Add(currencyCode, 0); fundObject.TodayRemainFund.Add(currencyCode, 0); fundObject.LastDayRemainFund.Add(currencyCode, 0); } //入金 var inFund = 0.0; var vmInFund = 0.0; //出金 var outFund = 0.0; var vmOutFund = 0.0; //其他收入 var inFundOther = 0.0; //其他支出 var outFundOther = 0.0; //当日浮动盈亏 var CurrPnl = 0.0; //当日浮动盈亏 var PositionPnl = 0.0; var RoundedPositionPnl = 0.0; //期权空头浮动盈利=∑max(期权空头持仓*(期权合约成本价-期权合约现价), 0) 从客户角度看的 var ClientSellPositionPnl = 0.0; //当日总盈亏 var TotalPnl = 0.0; //当日盈亏 double DailyPnl = 0; //今日可用资金 var CurrAvailAmount = 0.0; //今日可用资金 var LastDayAvailAmount = 0.0; //当日资金变动 var CurrChangeAmount = 0.0; //资信等级 //credit_rating creditRating = null; //授信额度 var lineOfCredit = 0.0; //用户持仓价值 double? clientPv; double? roundedClientPv; //用户卖出部分持仓价值 double? clientSellPv; //客户持仓交易预付金总和,客户买入为正,客户卖出为负 double? PrepaymentAmount; //期权费收支 var OptionPremium = 0.0; //期权费收支 var OptionPremiumSwap = 0.0; //结算收支(平仓行权) var SettlementBalance = 0.0; //平仓收支 var UnwindBalance = 0.0; //行权收支 var ExerciseBalance = 0.0; //实现盈亏 var WinLoss = 0.0; //持仓期权费净额(客户角度卖出为负,买入为正) var PositionPremiumNetCash = 0.0; //权利金冻结(当日该客户所有持仓的卖出期权权利金) var SellTradePrice = 0.0; // 期初持仓交易净额 var LastDayPositionPremiumNetCash = 0.0; //潜在行权盈余 var PotentialSurpluses = 0.0; //权利金应付应收 总额 //var FrozenAndCopeWithExpirePremium = 0.0; //净资金流入,其他资金,票息,互换收益,预付金余额,冻结权利金(未到期支付),冻结资金 double NetFund = 0.0, OtherFund = 0.0, Coupon = 0.0, SwapBalance = 0.0, MarginBalance, FrozenPremium, FrozenBalance = 0.0; //应付到期权利金,应付存续权利金,应收存续权力金,了结权利金 double CopeWithExpirePremium, CopeWithLastPremium, ReceivablePremium, EndPremium = 0.0; //未了结名义成交金额 var TotalNominal = 0.0; //应付预付金,可提取预付金,Delta预付金,互换应付预付金 double PayableMargin = 0d, AdvisableMargin = 0d, DeltaMargin = 0d, SwapPayableMargin = 0.0; //互换容忍预付金额 互换追保金额 double SwapUnPayableMargin = 0.0, SwapMargin = 0.0; //双向预付金 var TwoSideMargin = 0.0; var OtherSideMargin = 0.0; var MySideMargin = 0.0; //额外追保 var AdditionalMargin = 0.0; //追保金额 var Margin = 0.0; //昨日抵押品价值 var LastGuaranteesTotalAmount = 0.0; //持仓名义本金规模 var AvailableStockEqvNotional = 0.0; //潜在风险暴露 var PFE = 0d; //互换存续预付金 var SwapMarinAmount = 0d; //交易费用 var tradeFee= 0d; //利息盈亏 var interestPnl= 0d; // ClientBalanceDaily clientbalancedaily = null; #endregion #region 客户授信 资信等级 客户昨日现金 clientbalancedaily对象初始化 //获取客户授信 var credits = creditList?.Where(t => t.ClientId == client.id); if (credits.Any()) { //设置的全部授信 lineOfCredit = credits.Sum(t => t.Credit ?? 0); } else { lineOfCredit = 0.0; } //资信等级授信额度 //creditRating = creditRatingList != null ? creditRatingList.FirstOrDefault(t => t.id == client.CreditRatingId) : null; //if (creditRating != null) //{ // lineOfCredit += creditRating.CreditLine ?? 0.0; //} clientbalancedaily = new ClientBalanceDaily() { ClientId = client.id, ClientName = client.Name, ClientNumber = client.Number, BalanceDate = balanceDate }; //获取用户最后结算日可用资金 var clientbalancedailyPre = preClientbalancedailys.FirstOrDefault(t => t.ClientId == client.id); if (clientbalancedailyPre != null) { if (!string.IsNullOrEmpty(clientbalancedailyPre.FundJson)) { clientbalancedailyPre.FundObject = JsonConvert.DeserializeObject(clientbalancedailyPre.FundJson); if (clientbalancedailyPre.FundObject.InFund.Count() == 1 && clientbalancedailyPre.FundObject.InFund.ContainsKey(string.Empty) && currencyCodes.FirstOrDefault() != string.Empty) { if (string.IsNullOrEmpty(client.SettlementCurrency)) { throw new Exception("客户:" + client.Name + "未配置结算币种"); } clientbalancedailyPre.FundObject.InFund.Add(client.SettlementCurrency, clientbalancedailyPre.InFund ?? 0); clientbalancedailyPre.FundObject.VmInFund.Add(client.SettlementCurrency, clientbalancedailyPre.vm_in_fund ?? 0); clientbalancedailyPre.FundObject.InFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.InFundSum ?? 0); clientbalancedailyPre.FundObject.VmInFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.vm_in_fund_sum ?? 0); clientbalancedailyPre.FundObject.OutFund.Add(client.SettlementCurrency, clientbalancedailyPre.OutFund ?? 0); clientbalancedailyPre.FundObject.VmOutFund.Add(client.SettlementCurrency, clientbalancedailyPre.vm_out_fund ?? 0); clientbalancedailyPre.FundObject.OutFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.OutFundSum ?? 0); clientbalancedailyPre.FundObject.VmOutFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.vm_out_fund_sum ?? 0); clientbalancedailyPre.FundObject.NetFund.Add(client.SettlementCurrency, clientbalancedailyPre.NetFund ?? 0); clientbalancedailyPre.FundObject.NetFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.NetFundSum ?? 0); clientbalancedailyPre.FundObject.OtherFund.Add(client.SettlementCurrency, clientbalancedailyPre.OtherFund ?? 0); clientbalancedailyPre.FundObject.OtherFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.OtherFundSum ?? 0); clientbalancedailyPre.FundObject.TodayRemainFund.Add(client.SettlementCurrency, clientbalancedailyPre.ToDayRemainFund ?? 0); } foreach (var currencyCode in currencyCodes) { if (clientbalancedailyPre.FundObject.TodayRemainFund.ContainsKey(currencyCode)) { fundObject.LastDayRemainFund[currencyCode] = clientbalancedailyPre.FundObject.TodayRemainFund[currencyCode]; } } } else { clientbalancedailyPre.FundObject = new FundObject(); if (currencyCodes.Count() == 1 && currencyCodes.FirstOrDefault() == string.Empty) { clientbalancedailyPre.FundObject.InFund.Add(string.Empty, clientbalancedailyPre.InFund ?? 0); clientbalancedailyPre.FundObject.VmInFund.Add(string.Empty, clientbalancedailyPre.vm_in_fund ?? 0); clientbalancedailyPre.FundObject.InFundSum.Add(string.Empty, clientbalancedailyPre.InFundSum ?? 0); clientbalancedailyPre.FundObject.VmInFundSum.Add(string.Empty, clientbalancedailyPre.vm_in_fund_sum ?? 0); clientbalancedailyPre.FundObject.OutFund.Add(string.Empty, clientbalancedailyPre.OutFund ?? 0); clientbalancedailyPre.FundObject.VmOutFund.Add(string.Empty, clientbalancedailyPre.vm_out_fund ?? 0); clientbalancedailyPre.FundObject.OutFundSum.Add(string.Empty, clientbalancedailyPre.OutFundSum ?? 0); clientbalancedailyPre.FundObject.VmOutFundSum.Add(string.Empty, clientbalancedailyPre.vm_out_fund_sum ?? 0); clientbalancedailyPre.FundObject.NetFund.Add(string.Empty, clientbalancedailyPre.NetFund ?? 0); clientbalancedailyPre.FundObject.NetFundSum.Add(string.Empty, clientbalancedailyPre.NetFundSum ?? 0); clientbalancedailyPre.FundObject.OtherFund.Add(string.Empty, clientbalancedailyPre.OtherFund ?? 0); clientbalancedailyPre.FundObject.OtherFundSum.Add(string.Empty, clientbalancedailyPre.OtherFundSum ?? 0); fundObject.LastDayRemainFund[string.Empty] = clientbalancedailyPre.ToDayRemainFund ?? 0; } else { clientbalancedailyPre.FundObject.InFund.Add(client.SettlementCurrency, clientbalancedailyPre.InFund ?? 0); clientbalancedailyPre.FundObject.VmInFund.Add(client.SettlementCurrency, clientbalancedailyPre.vm_in_fund ?? 0); clientbalancedailyPre.FundObject.InFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.InFundSum ?? 0); clientbalancedailyPre.FundObject.VmInFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.vm_in_fund_sum ?? 0); clientbalancedailyPre.FundObject.OutFund.Add(client.SettlementCurrency, clientbalancedailyPre.OutFund ?? 0); clientbalancedailyPre.FundObject.VmOutFund.Add(client.SettlementCurrency, clientbalancedailyPre.vm_out_fund ?? 0); clientbalancedailyPre.FundObject.OutFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.OutFundSum ?? 0); clientbalancedailyPre.FundObject.VmOutFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.vm_out_fund_sum ?? 0); clientbalancedailyPre.FundObject.NetFund.Add(client.SettlementCurrency, clientbalancedailyPre.NetFund ?? 0); clientbalancedailyPre.FundObject.NetFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.NetFundSum ?? 0); clientbalancedailyPre.FundObject.OtherFund.Add(client.SettlementCurrency, clientbalancedailyPre.OtherFund ?? 0); clientbalancedailyPre.FundObject.OtherFundSum.Add(client.SettlementCurrency, clientbalancedailyPre.OtherFundSum ?? 0); fundObject.LastDayRemainFund[client.SettlementCurrency] = clientbalancedailyPre.ToDayRemainFund ?? 0; } } LastDayPositionPremiumNetCash = clientbalancedailyPre.PositionPremiumNetCash ?? 0.0; LastGuaranteesTotalAmount = clientbalancedailyPre.TodayRemianFundProduct ?? 0.0; } AvailableStockEqvNotional = credits.Sum(t => t.StockEqvNotional) - trades.Where(O => ConsTrade.PositionTradeStatusList.Contains(O.TradeStatus) && O.ClientId == client.id) .Sum(O => (double?)O.StockEqvNotionalReal) ?? 0.0; #endregion #region 出金 入金 当日可用资金计算 //获取客户所有出入金列表 clientEntryexits = entryexits.Where(t => t.ClientId == client.id).ToList(); var tradeCashGroupIds = clientEntryexits.Where(y => y.IsGroup == 1).Select(y => y.TradeCashId).ToArray(); var tradeCashGroups = DbContext.trade_cash.Where(x => tradeCashGroupIds.Contains(x.id)); if (clientEntryexits != null) { clientEntryexits.ForEach(clientEntryexit => { if (null == clientEntryexit.Direction) { throw new Exception("客户:" + client.Name + "有一条出入记录存在出入金方向存在问题!"); } if (currencyCodes.Count()==1) { clientEntryexit.CurrencyCode = ""; } //之前单币种环境改为多币种环境后历史数据为""和配置的币种匹配不上 if (currencyCodes.Count() >= 1 && string.IsNullOrWhiteSpace(clientEntryexit.CurrencyCode)) { if (currencyCodes.Contains("CNY")) { clientEntryexit.CurrencyCode = "CNY"; } else if (currencyCodes.Contains("RMB")) { clientEntryexit.CurrencyCode = "RMB"; } } if (clientEntryexit.Direction.Equals("入金")) { // 根据 cash_type 判断资金进入哪个部分 if (clientEntryexit.cash_type == CashTypeEnum.初保账户.ToString()) { AddToFund(fundObject.InFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); // 更新 NetFund AddToFund(fundObject.NetFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } else { AddToFund(fundObject.VmInFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } } else if (clientEntryexit.Direction.Equals("出金")) { // 根据 cash_type 判断资金退出到哪个部分 if (clientEntryexit.cash_type == CashTypeEnum.初保账户.ToString()) { AddToFund(fundObject.OutFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); // 更新 NetFund AddToFund(fundObject.NetFund, clientEntryexit.CurrencyCode, -(clientEntryexit.Money ?? 0)); } else { AddToFund(fundObject.VmOutFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } } else if (clientEntryexit.Direction.Equals("其他收入")) { if (fundObject.InFundOther.ContainsKey(clientEntryexit.CurrencyCode)) { fundObject.InFundOther[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0; } else { fundObject.InFundOther.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } if (fundObject.OtherFund.ContainsKey(clientEntryexit.CurrencyCode)) { fundObject.OtherFund[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0; } else { fundObject.OtherFund.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } } else if (clientEntryexit.Direction.Equals("其他支出")) { if (fundObject.OutFundOther.ContainsKey(clientEntryexit.CurrencyCode)) { fundObject.OutFundOther[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0; } else { fundObject.OutFundOther.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } if (fundObject.OtherFund.ContainsKey(clientEntryexit.CurrencyCode)) { fundObject.OtherFund[clientEntryexit.CurrencyCode] += clientEntryexit.Money ?? 0; } else { fundObject.OtherFund.Add(clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } } else if (clientEntryexit.Direction.Equals("划转")) { if (clientEntryexit.TransferOutAccount == "初保账户") { AddToFund(fundObject.InFund, clientEntryexit.CurrencyCode, -clientEntryexit.Money ?? 0); // 更新 NetFund AddToFund(fundObject.NetFund, clientEntryexit.CurrencyCode, -clientEntryexit.Money ?? 0); if (clientEntryexit.TransferInAccount == "追保账户") { AddToFund(fundObject.VmInFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } else { WinLoss += clientEntryexit.Money ?? 0; CurrChangeAmount += clientEntryexit.Money ?? 0; } } else if (clientEntryexit.TransferOutAccount == "追保账户") { AddToFund(fundObject.VmInFund, clientEntryexit.CurrencyCode, -clientEntryexit.Money ?? 0); if (clientEntryexit.TransferInAccount == "初保账户") { AddToFund(fundObject.InFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); // 更新 NetFund AddToFund(fundObject.NetFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } else { WinLoss += clientEntryexit.Money ?? 0; CurrChangeAmount += clientEntryexit.Money ?? 0; } } else { WinLoss -= clientEntryexit.Money ?? 0; CurrChangeAmount -= clientEntryexit.Money ?? 0; if (clientEntryexit.TransferInAccount == "初保账户") { AddToFund(fundObject.InFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); // 更新 NetFund AddToFund(fundObject.NetFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } else { AddToFund(fundObject.VmInFund, clientEntryexit.CurrencyCode, clientEntryexit.Money ?? 0); } } } else { if (ClientCashInCashOut.系统操作_期权费.Equals(clientEntryexit.Action)) { //CurrPnl += clientEntryexit.Money ?? 0.0; CurrChangeAmount += clientEntryexit.Money ?? 0.0; OptionPremium += clientEntryexit.Money ?? 0.0; } //黑箱了结资金按照主交易来进行归类 else if ((ClientCashInCashOut.系统操作_行权费.Equals(clientEntryexit.Action) || ClientCashInCashOut.系统操作_平仓费.Equals(clientEntryexit.Action)) && clientEntryexit.IsGroup != 2) { var money = clientEntryexit.Money ?? 0; //如果是黑箱主交易了结资金(主交易Money没有赋值),取对应tradeCash数据 if (money == 0 && clientEntryexit.IsGroup == 1) { var tradeCash = tradeCashGroups.FirstOrDefault(x => x.id == clientEntryexit.TradeCashId); money = -(tradeCash?.Amount ?? 0); } //CurrPnl += money; CurrChangeAmount += money; SettlementBalance += money; if (ClientCashInCashOut.系统操作_平仓费.Equals(clientEntryexit.Action)) { UnwindBalance += money; } else { ExerciseBalance += money; } } //黑箱了结资金按照主交易来进行归类 else if (ClientCashInCashOut.系统操作_票息.Equals(clientEntryexit.Action) && clientEntryexit.IsGroup != 2) { var money = clientEntryexit.Money ?? 0; //如果是黑箱主交易了结资金(主交易Money没有赋值),取对应tradeCash数据 if (money == 0 && clientEntryexit.IsGroup == 1) { var tradeCash = tradeCashGroups.FirstOrDefault(x => x.id == clientEntryexit.TradeCashId); money = -(tradeCash?.Amount ?? 0); } CurrChangeAmount += money; Coupon += money; } } if (ClientCashInCashOut.已确认.Equals(clientEntryexit.State)) { clientEntryexit.SettleDate = balanceDate; clientEntryexit.State = ClientCashInCashOut.已结算; } }); } clientEntryexits_swap = entryexits_swap.Where(t => t.ClientId == client.id).ToList(); if (clientEntryexits_swap != null) { clientEntryexits_swap.ForEach(clientEntryexit => { if (null == clientEntryexit.Direction) { throw new Exception("客户:" + client.Name + "有一条出入记录存在出入金方向存在问题!"); } if (currencyCodes.Count() == 1) { clientEntryexit.CurrencyCode = ""; } //之前单币种环境改为多币种环境后历史数据为""和配置的币种匹配不上 if (currencyCodes.Count() >= 1 && string.IsNullOrWhiteSpace(clientEntryexit.CurrencyCode)) { if (currencyCodes.Contains("CNY")) { clientEntryexit.CurrencyCode = "CNY"; } else if (currencyCodes.Contains("RMB")) { clientEntryexit.CurrencyCode = "RMB"; } } if (ClientCashInCashOut.系统操作_期权费.Equals(clientEntryexit.Action) || ClientCashInCashOut.系统操作_应付预付金.Equals(clientEntryexit.Action) || ClientCashInCashOut.系统操作_预付金返息.Equals(clientEntryexit.Action)) { CurrChangeAmount += clientEntryexit.Money ?? 0.0; OptionPremiumSwap += clientEntryexit.Money ?? 0.0; } else if (ClientCashInCashOut.系统操作_平仓费.Equals(clientEntryexit.Action)) { CurrChangeAmount += clientEntryexit.Money ?? 0.0; SwapBalance += clientEntryexit.Money ?? 0.0; WinLoss += clientEntryexit.Money ?? 0.0; } else if (ClientCashInCashOut.系统操作_互换.Equals(clientEntryexit.Action)) { CurrChangeAmount += clientEntryexit.Money ?? 0.0; SwapBalance += clientEntryexit.Money ?? 0.0; WinLoss += clientEntryexit.Money ?? 0.0; } if (ClientCashInCashOut.已确认.Equals(clientEntryexit.State)) { clientEntryexit.SettleDate = balanceDate; clientEntryexit.State = ClientCashInCashOut.已结算; } }); } foreach (var item in currencyCodes) { if (fundObject.TodayRemainFund.ContainsKey(item)) { fundObject.TodayRemainFund[item] = (fundObject.LastDayRemainFund.ContainsKey(item) ? fundObject.LastDayRemainFund[item] : 0) + (fundObject.NetFund.ContainsKey(item) ? fundObject.NetFund[item] : 0) + (fundObject.VmInFund.ContainsKey(item) ? fundObject.VmInFund[item] : 0) - (fundObject.VmOutFund.ContainsKey(item) ? fundObject.VmOutFund[item] : 0); } else { fundObject.TodayRemainFund.Add(item, (fundObject.LastDayRemainFund.ContainsKey(item) ? fundObject.LastDayRemainFund[item] : 0) + (fundObject.NetFund.ContainsKey(item) ? fundObject.NetFund[item] : 0) + (fundObject.VmInFund.ContainsKey(item) ? fundObject.VmInFund[item] : 0) - (fundObject.VmOutFund.ContainsKey(item) ? fundObject.VmOutFund[item] : 0)); } if ((client.SettlementCurrency ?? "CNY") == item || item == "") { fundObject.TodayRemainFund[item] += CurrChangeAmount; } var rateObj = new eod_currency_rate { Rate = 1, SellRate = 1, BuyRate = 1, ForeignCurrency = item, LocalCurrency = client.SettlementCurrency, }; if (PS.Config.ErpElement.SupportMultiCurrency) { currencyProvider.TryGetCurrencyRate(item, client.SettlementCurrency, out rateObj); if (rateObj == null) { _context.RaiseError("结算客户资金", $"[{client.Name}]找不到汇率:{item}{client.SettlementCurrency}"); } } CurrAvailAmount += fundObject.TodayRemainFund[item] * rateObj.Rate; LastDayAvailAmount += fundObject.LastDayRemainFund[item] * rateObj.Rate; inFund += fundObject.InFund[item] * rateObj.Rate; vmInFund += fundObject.VmInFund[item] * rateObj.Rate; outFund += fundObject.OutFund[item] * rateObj.Rate; vmOutFund += fundObject.VmOutFund[item] * rateObj.Rate; NetFund += fundObject.NetFund[item] * rateObj.Rate; inFundOther += fundObject.InFundOther[item] * rateObj.Rate; outFundOther += fundObject.OutFundOther[item] * rateObj.Rate; OtherFund += fundObject.OtherFund[item] * rateObj.Rate; } #endregion #region 抵押品 //抵押品资金价值 var tempClientProductList = clientProductList.Where(a => a.product.ClientId == client.id).ToList(); var GuaranteesTotalAmount = 0.0; if (tempClientProductList.Any()) { tempClientProductList.ForEach(t => { if (t.um == null) { throw new Exception($"抵押品,出入金单号[{t.product.Number}]标的ID[{t.product.UnderlyingId}]未找到对应标的基本信息!"); } if (t.variety == null) { throw new Exception($"抵押品,出入金单号[{t.product.Number}]品种ID[{t.product.VarietyId}]未找到对应品种基本信息!"); } if (dayeods.TryGetPrice(t.um.UnderlyingCode, SettlementTypeEnum.ClosePrice, out var price)) { GuaranteesTotalAmount += (t.product.ProductAmount ?? 0) * (t.product.Rate ?? 0.0) * price; } else { throw new Exception($"抵押品,出入金单号[{t.product.Number}]标的[{t.um.UnderlyingCode}]在{balanceDate:yyyy-MM-dd}收盘价不存在!"); } }); } #endregion #region 当日冻结权利金 当日应收权利金 潜在行权盈余 持仓市值 持仓Pnl //持仓交易 var positionTrades = trades.Where(t => t.TradeStatus.Equals(ConsTrade.确认成交) && t.ClientId == client.id && t.TradeType != "收益互换").ToList(); var clientEodSwaps = eodSwaps.Where(t => t.ClientId == client.id && t.ValueDate == balanceDate).ToList(); var clientEodSwapPosis= eodSwapPosis.Where(t => t.ClientId == client.id && t.ValueDate == balanceDate).ToList(); //var tradeIds = clientTrades.Where(t => t.ClientId == client.id).Select(t => t.id).ToList(); //获取所有持仓交易ids var positionTradeIds = positionTrades == null || positionTrades.Count == 0 ? new List() : positionTrades.Select(t => t.id).ToList(); //获取客户冻结资金 var clientFrozenFund = clientFrozenFunds[client.id]; //当前持仓并且未到支付日的卖出交易(客户为买入,渠道为卖出)则为冻结的权利金 //FrozenPremium = positionTrade == null || positionTrade.Count == 0 ? 0.0 : (positionTrade.Where(t => t.PremiumPayDate > balanceDate && t.BuySell == "卖出").Sum(t => t.TradePrice ?? 0.0)); FrozenPremium = clientFrozenFund.FrozenPayableOptionMoney; //应收存续权利金 //ReceivablePremium = positionTrade == null || positionTrade.Count == 0 ? 0.0 : (positionTrade.Where(t => t.PremiumPayDate > balanceDate && t.BuySell == "买入").Sum(t => t.TradePrice ?? 0.0)); ReceivablePremium = clientFrozenFund.FrozenReceivableOptionMoney; //冻结预付金(绝对值) var FrozenMarginMoney = clientFrozenFund.FrozenMarginMoney; //冻结资金=冻结权利金+到期停牌股票名义金额×6.5%*30/365(默认收取一个月资金利息,多追少补) //todo 此处需要增加股票停复牌信息,同时检查到期交易不能默认执行到期 //FrozenBalance = FrozenPremium; //应付到期权利金 CopeWithExpirePremium = OptionPremium + OptionPremiumSwap; //应付存续权利金 CopeWithLastPremium = FrozenPremium; //未了结名义成交金额 todo //持仓的买入 以及卖出是否都统计 TotalNominal = positionTrades == null || positionTrades.Count == 0 ? 0 : positionTrades.Sum(t => t.UnderlyingInstrumentType == "Stock" ? t.StockEqvNotional : (t.Notional * (t.SpotPrice ?? 0.0))); TotalNominal += Convert.ToDouble(clientEodSwaps.Sum(x => x.NotionalValue)); //计算潜在客户行权盈余 max{名义成交金额*(标的当日结算价-标的初始价格)/行权价格, 0} foreach (var t in positionTrades) { if (t.TradeType != "现金流交易" && t.TradeType != "自定义交易") { var spotPrice = t.SpotPrice ?? t.SpotPrice ?? 0.0; var nominal = t.UnderlyingInstrumentType == "Stock" ? t.StockEqvNotional : (t.Notional * spotPrice); if (!dayeods.TryGetPrice(t.UnderlyingCode, t.SettlementType, out var nowPrice)) { throw new Exception($"找不到收盘价({t.UnderlyingCode}),无法结算!"); } var Strike = t.IsMoneynessOptionData ? ((t.Strike ?? 0) * t.SpotPrice ?? 0) : t.Strike ?? 0; //如果期初价格未0则已份额计算潜在行权盈余 if (spotPrice == 0) { PotentialSurpluses += Math.Max(Strike == 0 ? 0 : (t.Notional * (nowPrice - Strike) * ("Call".Equals(t.CallPut) ? 1 : -1)), 0) * TradeCalcHelper.GetSign(t.BuySell) * -1; } else { PotentialSurpluses += Math.Max(Strike == 0 ? 0 : (nominal * (nowPrice - Strike) / spotPrice * ("Call".Equals(t.CallPut) ? 1 : -1)), 0) * TradeCalcHelper.GetSign(t.BuySell) * -1; } } if (t.BuySell == "买入" && t.TradeType != "现金流交易") { var um = underlyDataSource.GetData(t.UnderlyingCode); //deltaS/S var rate = um.DeltaS_S; if (!rate.IsNormalize()) { var variety = varietyDataSource.GetData(um.CommodityCode); if (ConsGlobal.InstrumentType.IsStockIndex(um.UnderlyingInstrumentType) || ConsGlobal.InstrumentType.IsStockIF(um.UnderlyingInstrumentType)) { rate = variety.UpLimitValue; } else { rate = variety.Margin ?? 0; } } var risk = eodRiskList.Where(O => O.TradeId == t.id).FirstOrDefault(); var pfe1 = t.StockEqvNotional == 0 ? (t.Notional * t.SpotPrice ?? 0) : t.StockEqvNotional; var pfe2 = Math.Abs(risk.DeltaCash) * rate.Value + 0.5 * 100 * rate.Value * rate.Value * Math.Abs(Math.Min(risk.GammaCash, 0)); PFE += Math.Min(pfe1, pfe2); } } PositionPremiumNetCash = positionTrades.Sum(t => -TradeCalcHelper.GetSign(t.BuySell) * ((t.TradePrice ?? 0) * (t.OriginalNotional != null && t.OriginalNotional != 0 ? t.Notional / t.OriginalNotional.Value : 1))); //现金流交易没有份额的概念 SellTradePrice = positionTrades.Where(x => x.BuySell == "买入").Sum( t => t.OriginalNotional.HasValue && t.OriginalNotional > 0 ? (t.TradePrice ?? 0) * t.Notional / t.OriginalNotional.Value : (t.TradePrice ?? 0)); //客户持仓交易预付金总和,客户买入为正,客户卖出为负 PrepaymentAmount = positionTrades.Sum(x => x.StockEqvNotional * (x.trade_snowball?.PrepaymentRatio ?? 0) * (x.BuySell == "卖出" ? 1 : -1)); var todayFinishedTrades = DbContext.trade.Where(t => keys.Contains(t.id) && t.IsGroup != 1 && t.ClientId == client.id) .Select(x => new { x.id, x.TradeType, x.BuySell, x.TradePrice }).ToList(); var clientSwapIds = clientEodSwaps.Select(s => s.SwapTradeId).Distinct(); var todaySwapFinishedTrades = todaySwapTrades.Where(t => clientSwapIds.Contains(t.id) && ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus)); var todayFinishedTradeCash = from tc in finishedTradeCash join td in DbContext.trade on tc.TradeId equals td.id where td.IsGroup != 1 && td.ClientId == client.id group tc by td.id into g select new { tradeId = g.Key, amountSum = g.Sum(n => n.Amount) }; var todaySwapFinishedTradeIds = todaySwapFinishedTrades.Select(s => s.id).ToList(); var todaySwapFinishedCash = clientEntryexits_swap.Where(x => todaySwapFinishedTradeIds.Contains(x.TradeId ?? 0)).ToList(); var list = todayFinishedTradeCash.ToList(); //了结开仓费用 EndPremium = todayFinishedTrades.Sum(t => t.TradeType != "远期" ? -TradeCalcHelper.GetSign(t.BuySell) * (t.TradePrice ?? 0) * finishedTradeNotionalPercentDic[t.id] : (t.TradePrice ?? 0) * finishedTradeNotionalPercentDic[t.id]) * -1; EndPremium = EndPremium + todaySwapFinishedCash.Sum(s => s.Money ?? 0); var eodPnlSum = new EodPnlGridSum(); #region 收益互换V2 var clientEodSwapsLast = clientEodSwaps.ToList(); var clientEodSwapPositionLast = clientEodSwapPosis.ToList(); foreach (var item in clientEodSwapsLast) { var lastEodSwap = eodSwaps.FirstOrDefault(t => t.SwapTradeId == item.SwapTradeId && t.ValueDate == preBalanceDate); item.PostionValue=Math.Round(item.PostionValue, ConsGlobal.MoneyRound,MidpointRounding.AwayFromZero); PotentialSurpluses += Convert.ToDouble(item.PostionValue) * (-1); // WinLoss += Convert.ToDouble(item.TdRealizedPnL) * (-1); var lastPv = lastEodSwap != null ? Convert.ToDouble(lastEodSwap.PostionValue) * (-1) : 0; eodPnlSum.LastPvSum = eodPnlSum.LastPvSum.HasValue ? eodPnlSum.LastPvSum + lastPv : lastPv; var pnl = item.PostionValue; eodPnlSum.PvSum = Convert.ToDouble(item.PostionValue) * (-1); eodPnlSum.SellPvSum = Convert.ToDouble(item.MarketValueShort) * (-1); eodPnlSum.RoundedPvSum = Math.Round(Convert.ToDouble(item.PostionValue), 2) * (-1); eodPnlSum.DailyPnLSum = Convert.ToDouble(item.TdRealizedPnL) * (-1); PositionPnl += Convert.ToDouble(pnl) * (-1); RoundedPositionPnl += Math.Round(Convert.ToDouble(pnl), 2) * (-1); TotalPnl += Convert.ToDouble(item.RealizedPnL) * (-1); ClientSellPositionPnl += Math.Max(-Convert.ToDouble(item.MarketValueShort), 0); var lastPnl = lastEodSwap != null ? lastEodSwap.PostionValue : 0; DailyPnl += Convert.ToDouble(pnl - lastPnl + item.TdRealizedPnL) * (-1); //PayableMargin += Convert.ToDouble(item.InitMarginLoss + item.InitMarginGain+ item.PostionMarginLoss + item.PostionMarginGain); } var clientEventFlowList = clientEventFlows.Where(x=>x.ClientId== client.id); foreach (var item in clientEventFlowList.GroupBy(x => x.SwapTradeId)) { var eventPosis = item.Where(t => t.PayDirection > 0).ToList(); var eventInterests = item.Where(t => t.PayDirection == 0).ToList(); interestPnl += Convert.ToDouble(eventInterests.Sum(s => s.InterestClosePnL)) * (-1); tradeFee += Convert.ToDouble(eventPosis.Sum(s => s.TradingFee + s.TradingFeePending)) * (-1); } var clientmarignQuery = marignQuery.Where(x => x.ClientId == client.id&&x.StructureType!="多空组合"); SwapMarinAmount = Convert.ToDouble(clientmarignQuery.Sum(s => s.marin)); #endregion //合计持仓浮动盈亏 CurrPnl = eodPnlSum.DailyPnLSum ?? 0; clientPv = eodPnlSum.PvSum; roundedClientPv = eodPnlSum.RoundedPvSum; clientSellPv = eodPnlSum.SellPvSum; #endregion #region 应缴预付金 预付金余额 可取预付金 追保额度 //获取tradespan 追保金额 = (当日资金余额 - 维持预付金) + 授信额度 var clientSpan = clientSpanList == null || clientSpanList.Count == 0 ? null : clientSpanList.FirstOrDefault(t => t.ClientId == client.id && t.ValueDate == balanceDate && t.SpanType == ClientSpan.SpanType_Eod); if (clientSpan != null) { PayableMargin += clientSpan.WorstCastClientPayable ?? 0d; DeltaMargin = clientSpan.DeltaMargin ?? 0d; SwapPayableMargin = clientSpan.SwapWorstCastClientPayable ?? 0d; SwapUnPayableMargin = clientSpan.SwapUnMargin ?? 0d; TwoSideMargin = clientSpan.TwoSideMargin ?? 0d; OtherSideMargin = clientSpan.OtherSideMargin ?? 0d; MySideMargin = clientSpan.MySideMargin ?? 0d; AdditionalMargin = (clientSpan.AdditionalWorstCastClientPayable) ?? 0d; } //var todaySwapMargins = clientEntryexits_swap.Where(x=>x.Action== ClientCashInCashOut.系统操作_应付预付金).ToList().Sum(s=>s.Money)??0; //var swapFrozenBalance = entryexits_swapFuture.Where(x => x.Action == ClientCashInCashOut.系统操作_应付预付金 || x.Action == ClientCashInCashOut.系统操作_期权费).ToList().Sum(s => s.Money) ?? 0; //PayableMargin += todaySwapMargins; //SwapPayableMargin += todaySwapMargins; //冻结资金 //FrozenMarginMoney += swapFrozenBalance; FrozenBalance = ReceivablePremium - FrozenPremium - (clientFrozenFund.OutFunds + clientFrozenFund.RedeemFunds) - FrozenMarginMoney; //预付金余额 MarginBalance = CurrAvailAmount + GuaranteesTotalAmount + FrozenBalance; if (PS.Config.Is申万) { //期权空头浮动盈亏 MarginBalance -= ClientSellPositionPnl; //空头持仓市值 MarginBalance -= Math.Abs(clientSellPv ?? 0); } else { //判断潜在行权盈余是否计入预付金余额 if ((valuedateBLL.SystemDate.IsPotentialSurplusUseMargin ?? 0) == 1) { MarginBalance += PotentialSurpluses; } } //可取预付金为预付金余额 - 应缴预付金(上浮2%) 20220207新增减去互换预付金容忍额 AdvisableMargin = Math.Max(MarginBalance + (PayableMargin - SwapUnPayableMargin) * (double)(marginMaxRatio / marginRatio), 0); //计算追保金额 维持预付金带方向 所以计算追保金额是 为相加 var IsTradeCredit = (client.IsTradeCredit ?? 0) == 1; // 场外预付金资金占用后剩余资金 var marginBalanceSurplus = 0d; //是否期权费授信 if (IsTradeCredit) { //授信是否可用于互换 if (client.creditCanApplySwap) { //期权费授信可以支付权利金 则预付金余额未0时 资金从 Margin = Math.Min(MarginBalance + lineOfCredit + (PayableMargin - SwapUnPayableMargin), 0); } else { //互换最大可用资金 marginBalanceSurplus = Math.Max(Math.Min(Math.Max(MarginBalance - OptionPremiumSwap + lineOfCredit + (PayableMargin - SwapPayableMargin), 0), Math.Max(MarginBalance - OptionPremiumSwap, 0)), 0); //收益互换追保金额 剩余可支付互换资金 - (互换占用预付金 - 互换容忍预付金额度) SwapMargin = Math.Min(marginBalanceSurplus + OptionPremiumSwap + (SwapPayableMargin - SwapUnPayableMargin), 0); //计算期权追保 Margin = Math.Min(MarginBalance - OptionPremiumSwap + lineOfCredit + (PayableMargin - SwapPayableMargin), 0) + SwapMargin; } } else { //授信是否可用于互换 if (client.creditCanApplySwap) { //期权费授信不可以支付权力金时 Margin = Math.Min(Math.Max(MarginBalance, 0) + lineOfCredit + (PayableMargin - SwapUnPayableMargin), 0) + Math.Min(MarginBalance, 0); } else { //互换最大可用资金 marginBalanceSurplus = Math.Max(Math.Min(Math.Max(Math.Max(MarginBalance - OptionPremiumSwap, 0) + lineOfCredit + (PayableMargin - SwapUnPayableMargin), 0), Math.Max(MarginBalance - OptionPremiumSwap, 0)), 0); //收益互换追保金额 剩余可支付互换资金 - (互换占用预付金 - 互换容忍预付金额度) SwapMargin = Math.Min(marginBalanceSurplus + OptionPremiumSwap + (SwapPayableMargin - SwapUnPayableMargin), 0) + Math.Min(marginBalanceSurplus + OptionPremiumSwap, 0); //计算期权追保 Margin = Math.Min(Math.Max(MarginBalance - OptionPremiumSwap, 0) + lineOfCredit + (PayableMargin - SwapUnPayableMargin), 0) + Math.Min(MarginBalance - OptionPremiumSwap, 0) + SwapMargin; } } #endregion #region ClientBalacedaily ClientBalace对象赋值 if (client.BoundSide == BoundSideEnum.南向 && clientSpan != null) { var credit = DbContext.credit.FirstOrDefault(x => x.CreditStartDate <= balanceDate && x.CreditDeadLine >= balanceDate && x.ClientId == client.id && x.ProcessStatus == "已审批"); var PFECredit = credit != null ? credit.PFECredit : 0; clientSpan.PFEUsed = Math.Max(Math.Min((clientSpan.PFEUsed ?? 0) - CurrAvailAmount, PFECredit ?? 0), 0); } clientbalancedaily.ToDayRemainFund = CurrAvailAmount; clientbalancedaily.LastDayRemainFund = LastDayAvailAmount; clientbalancedaily.PositionPremiumNetCash = PositionPremiumNetCash; clientbalancedaily.SellTradePrice = SellTradePrice; clientbalancedaily.LastDayPositionPremiumNetCash = LastDayPositionPremiumNetCash; clientbalancedaily.WinLoss = WinLoss; clientbalancedaily.EndPremium = EndPremium; clientbalancedaily.InFundOther = inFundOther; clientbalancedaily.OutFundOther = outFundOther; clientbalancedaily.BalanceDate = balanceDate; clientbalancedaily.DayGainLoss = CurrPnl; clientbalancedaily.PositionPnl = PositionPnl; clientbalancedaily.RoundedPositionPnl = RoundedPositionPnl; clientbalancedaily.ClientSellPositionPnl = ClientSellPositionPnl; clientbalancedaily.TotalPnl = TotalPnl; clientbalancedaily.DailyPnl = DailyPnl; clientbalancedaily.OptionPremium = OptionPremium; clientbalancedaily.OptionPremiumSwap = OptionPremiumSwap; clientbalancedaily.SettlementBalance = SettlementBalance; clientbalancedaily.UnwindBalance = UnwindBalance; clientbalancedaily.Coupon = Coupon; clientbalancedaily.SwapBalance = SwapBalance; clientbalancedaily.ExerciseBalance = ExerciseBalance; clientbalancedaily.AdvisableMargin = AdvisableMargin; clientbalancedaily.TotalNominal = TotalNominal; clientbalancedaily.trade_fee = tradeFee; clientbalancedaily.interest_pnl = interestPnl; clientbalancedaily.Pv = clientPv ?? 0; clientbalancedaily.RoundedPv = roundedClientPv ?? 0; clientbalancedaily.SellPv = clientSellPv ?? 0; clientbalancedaily.PrepaymentAmount = PrepaymentAmount; clientbalancedaily.CopeWithLastPremium = CopeWithLastPremium; clientbalancedaily.CopeWithExpirePremium = CopeWithExpirePremium; clientbalancedaily.FrozenBalance = FrozenBalance; clientbalancedaily.FrozenPremium = FrozenPremium; clientbalancedaily.FrozenOutFund = clientFrozenFund.OutFunds; clientbalancedaily.FrozenRedeemFunds = clientFrozenFund.RedeemFunds; clientbalancedaily.MarginBalance = MarginBalance; clientbalancedaily.InFund = inFund; clientbalancedaily.vm_in_fund = vmInFund; clientbalancedaily.OutFund = outFund; clientbalancedaily.vm_out_fund = vmOutFund; clientbalancedaily.NetFund = NetFund; clientbalancedaily.OtherFund = OtherFund; clientbalancedaily.IsTradeCredit = IsTradeCredit; clientbalancedaily.Credit = lineOfCredit; clientbalancedaily.CashDeposit = PayableMargin; clientbalancedaily.PayableMargin = PayableMargin; clientbalancedaily.DeltaMargin = DeltaMargin; clientbalancedaily.SwapPayableMargin = SwapPayableMargin; clientbalancedaily.SwapUnPayableMargin = SwapUnPayableMargin; clientbalancedaily.TwoSideMargin = TwoSideMargin; clientbalancedaily.OtherSideMargin = OtherSideMargin; clientbalancedaily.MySideMargin = MySideMargin; clientbalancedaily.IsPayableMarginManual = clientSpan?.ModifiedFlag; clientbalancedaily.FrozenMarginMoney = FrozenMarginMoney; clientbalancedaily.Margin = Margin; clientbalancedaily.TodayRemianFundProduct = GuaranteesTotalAmount; clientbalancedaily.CashInCashOutProductChange = GuaranteesTotalAmount - LastGuaranteesTotalAmount; clientbalancedaily.PotentialSurpluses = PotentialSurpluses; clientbalancedaily.OptId = UserId; clientbalancedaily.OptName = UserName; clientbalancedaily.OptDate = DateTime.Now; clientbalancedaily.AdditionalMargin = AdditionalMargin; clientbalancedaily.AvailableStockEqvNotional = AvailableStockEqvNotional; clientbalancedaily.PFE = PFE; clientbalancedaily.EAD = Math.Max(PFE - (clientbalancedaily.Pv ?? 0) - (clientbalancedaily.ToDayRemainFund ?? 0), 0); var clientAmount = clientbalancedaily.ToDayRemainFund + clientbalancedaily.Credit + clientbalancedaily.TodayRemianFundProduct; var clientSwapMarinAmount = clientAmount + SwapMarinAmount; var MaintenanceLine = clientSwapMarinAmount == 0 ? 0 : (clientAmount + clientbalancedaily.PayableMargin) / clientSwapMarinAmount; clientbalancedaily.MaintenanceLine = Math.Round(MaintenanceLine ?? 0, 2); if (PS.Config.Is厦门象屿) { var xmxyClient = new XiaMenXiangYuClientInfo { ClientId = client.id, ClientName = client.Name, ClientNumber = client.Number, FundThreshold = client.FundThreshold }; if (balanceDate != DateTime.Today && clientDb.client_Axis_Fundthresholds.Where(x => x.ClientId == client.id).Any()) { xmxyClient.FundThreshold = clientDb.client_Axis_Fundthresholds.Where(x => x.ValueDate <= balanceDate && x.ClientId == client.id).OrderByDescending(x => x.ValueDate)?.FirstOrDefault()?.FundThreshold; } new XiaMenXiangYuCashService(this).ExecuteV2(xmxyClient, clientbalancedaily, fundObject, out var InOutFund, _context.SettleDate, positionTrades.Count); NetFund += InOutFund; MarginBalance += InOutFund; } clientbalancedaily.FundObject = fundObject; clientbalancedaily.FundJson = JsonHelper.Serialize(fundObject); #endregion #region 客户冻结状态 //如果应付资金总额PayableFund大于0 则设置client //PayableFund => Math.Max(ClosedTradePayableFund + PositionTradePayableFund + MarginByPayableMarginCalc, 0); var ToDayRemainFund = clientbalancedaily.ToDayRemainFund ?? 0; //var PositionPremiumNetCash = clientbalancedaily.PositionPremiumNetCash ?? 0; //请知道d1、d2、d3含义的注释一下 var d1 = Math.Min(ToDayRemainFund + PositionPremiumNetCash, 0); var d2 = Math.Max(PositionPremiumNetCash - Math.Max(ToDayRemainFund + PositionPremiumNetCash, 0), 0); var d3 = -(clientbalancedaily.PayableMargin ?? 0.0) - Math.Max(ToDayRemainFund - d1 + d2, 0) - (clientbalancedaily.TodayRemianFundProduct ?? 0.0) - (clientbalancedaily.Credit ?? 0.0); if (Math.Max(-d1 + d2 + d3, 0) > 0) { client.PendingMarginCallPayment = 1; clientbalancedaily.State = "冻结"; } else { //如果计算追保金额小于等于0则解冻 if (client.PendingMarginCallPayment == 1) { client.PendingMarginCallPayment = 0; clientbalancedaily.State = "正常"; } } #endregion #region 结算合计 clientbalancedaily.OptionPremiumSum = clientbalancedaily.OptionPremium; clientbalancedaily.OptionPremiumSwapSum = clientbalancedaily.OptionPremiumSwap; clientbalancedaily.SettlementBalanceSum = clientbalancedaily.SettlementBalance; clientbalancedaily.UnwindBalanceSum = clientbalancedaily.UnwindBalance; clientbalancedaily.ExerciseBalanceSum = clientbalancedaily.ExerciseBalance; clientbalancedaily.CouponSum = clientbalancedaily.Coupon; clientbalancedaily.SwapBalanceSum = clientbalancedaily.SwapBalance; clientbalancedaily.WinLossSum = clientbalancedaily.WinLoss; clientbalancedaily.trade_fee_sum = clientbalancedaily.trade_fee; clientbalancedaily.interest_pnl_sum = clientbalancedaily.interest_pnl; clientbalancedaily.EndPremiumSum = clientbalancedaily.EndPremium; clientbalancedaily.CashInCashOutProductChangeSum = clientbalancedaily.CashInCashOutProductChange; if (clientbalancedailyPre != null) { clientbalancedaily.NetFundSum = 0; clientbalancedaily.InFundSum = 0; clientbalancedaily.OutFundSum = 0; clientbalancedaily.OtherFundSum = 0; clientbalancedaily.vm_in_fund_sum = 0; clientbalancedaily.vm_out_fund_sum = 0; foreach (var item in currencyCodes) { var rateObj = new eod_currency_rate { Rate = 1, SellRate = 1, BuyRate = 1, ForeignCurrency = item, LocalCurrency = client.SettlementCurrency, }; if (PS.Config.ErpElement.SupportMultiCurrency) { currencyProvider.TryGetCurrencyRate(item, client.SettlementCurrency, out rateObj); if (rateObj == null) { _context.RaiseError("结算客户资金", $"[{client.Name}]找不到汇率:{item}{client.SettlementCurrency}"); } } clientbalancedailyPre.FundObject.NetFundSum.TryGetValue(item, out var preNetFundSum); clientbalancedaily.FundObject.NetFund.TryGetValue(item, out var netFundToday); clientbalancedaily.FundObject.NetFundSum[item] = preNetFundSum + netFundToday; clientbalancedaily.NetFundSum += clientbalancedaily.FundObject.NetFundSum[item] * rateObj.Rate; clientbalancedailyPre.FundObject.InFundSum.TryGetValue(item, out var preInFundSum); clientbalancedailyPre.FundObject.VmInFundSum.TryGetValue(item, out var vmpreInFundSum); clientbalancedaily.FundObject.InFund.TryGetValue(item, out var inFundToday); clientbalancedaily.FundObject.VmInFund.TryGetValue(item, out var vminFundToday); clientbalancedaily.FundObject.InFundSum[item] = preInFundSum + inFundToday; clientbalancedaily.FundObject.VmInFundSum[item] = vmpreInFundSum + vminFundToday; clientbalancedaily.InFundSum += clientbalancedaily.FundObject.InFundSum[item] * rateObj.Rate; clientbalancedaily.vm_in_fund_sum += clientbalancedaily.FundObject.VmInFundSum[item] * rateObj.Rate; clientbalancedailyPre.FundObject.OutFundSum.TryGetValue(item, out var preOutFundSum); clientbalancedaily.FundObject.OutFund.TryGetValue(item, out var outFundToday); clientbalancedailyPre.FundObject.VmOutFundSum.TryGetValue(item, out var vmpreOutFundSum); clientbalancedaily.FundObject.VmOutFund.TryGetValue(item, out var vmoutFundToday); clientbalancedaily.FundObject.OutFundSum[item] = preOutFundSum + outFundToday; clientbalancedaily.FundObject.VmOutFundSum[item] = vmpreOutFundSum + vmoutFundToday; clientbalancedaily.OutFundSum += clientbalancedaily.FundObject.OutFundSum[item] * rateObj.Rate; clientbalancedaily.vm_out_fund_sum += clientbalancedaily.FundObject.VmOutFundSum[item] * rateObj.Rate; clientbalancedailyPre.FundObject.OtherFundSum.TryGetValue(item, out var preOtherFundSum); clientbalancedaily.FundObject.OtherFund.TryGetValue(item, out var otherFundToday); clientbalancedaily.FundObject.OtherFundSum[item] = preOtherFundSum + otherFundToday; clientbalancedaily.OtherFundSum += clientbalancedaily.FundObject.OtherFundSum[item] * rateObj.Rate; } clientbalancedaily.OptionPremiumSum += clientbalancedailyPre.OptionPremiumSum; clientbalancedaily.OptionPremiumSwapSum += (clientbalancedailyPre.OptionPremiumSwapSum ?? 0); clientbalancedaily.SettlementBalanceSum += clientbalancedailyPre.SettlementBalanceSum; clientbalancedaily.UnwindBalanceSum += clientbalancedailyPre.UnwindBalanceSum; clientbalancedaily.ExerciseBalanceSum += clientbalancedailyPre.ExerciseBalanceSum; clientbalancedaily.CouponSum += clientbalancedailyPre.CouponSum; clientbalancedaily.SwapBalanceSum += clientbalancedailyPre.SwapBalanceSum; clientbalancedaily.WinLossSum += clientbalancedailyPre.WinLossSum; clientbalancedaily.trade_fee_sum += clientbalancedailyPre.trade_fee_sum??0; clientbalancedaily.interest_pnl_sum += clientbalancedailyPre.interest_pnl_sum??0; clientbalancedaily.EndPremiumSum += (clientbalancedailyPre.EndPremiumSum ?? 0); clientbalancedaily.CashInCashOutProductChangeSum += clientbalancedailyPre.CashInCashOutProductChangeSum; } else { clientbalancedaily.FundObject.NetFundSum = clientbalancedaily.FundObject.NetFund; clientbalancedaily.FundObject.InFundSum = clientbalancedaily.FundObject.InFund; clientbalancedaily.FundObject.OutFundSum = clientbalancedaily.FundObject.OutFund; clientbalancedaily.FundObject.VmInFundSum = clientbalancedaily.FundObject.VmInFund; clientbalancedaily.FundObject.VmOutFundSum = clientbalancedaily.FundObject.VmOutFund; clientbalancedaily.FundObject.OtherFundSum = clientbalancedaily.FundObject.OtherFund; clientbalancedaily.NetFundSum = clientbalancedaily.NetFund; clientbalancedaily.InFundSum = clientbalancedaily.InFund; clientbalancedaily.vm_in_fund_sum= clientbalancedaily.vm_in_fund; clientbalancedaily.OutFundSum = clientbalancedaily.OutFund; clientbalancedaily.vm_out_fund_sum = clientbalancedaily.vm_out_fund; clientbalancedaily.OtherFundSum = clientbalancedaily.OtherFund; } #endregion clientbalancedaily.FundJson = JsonHelper.Serialize(clientbalancedaily.FundObject); newClientBalanceDaily.Add(clientbalancedaily); if (PS.Config.Is广发商贸) { clientbalancedaily.PositionPnl = 0; clientbalancedaily.RoundedPositionPnl = 0; clientbalancedaily.RoundedPv = 0; clientbalancedaily.Pv = 0; } } #endregion #region 计算渠道方合计 var baseName = PS.Config.CompanyFullName; var baseClient = clientDb.client.FirstOrDefault(t => baseName.Equals(t.Name)); //判断存在渠道商配置信息时 if (baseClient != null) { //获取当前结算的非渠道本身的所有客户的结算信息(当日) var allNewClientbalanceList = newClientBalanceDaily.Where(t => t.ClientId != baseClient.id); //渠道客户当日结算信息(不包括其他客户合计) var baseClientBalanceDaily = newClientBalanceDaily.FirstOrDefault(t => t.ClientId == baseClient.id); #region 处理渠道商历史资金结算信息 //检查当前渠道商是否已有过结算记录 var tempBaseClientbalancedaily = preClientbalancedailys.FirstOrDefault(t => t.ClientId == baseClient.id); //如果渠道商客户结算数据不存在则按结算日期顺序结算历史数据行 var RemainFund = 0.0; if (tempBaseClientbalancedaily == null) { var allOldClientbalancedaily = DbContext.ClientBalanceDaily.AsNoTracking().Where(t => t.BalanceDate < balanceDate && allClientIds.Contains(t.ClientId) && t.ClientId != baseClient.id).ToList(); var balanceDateList = allOldClientbalancedaily.Select(t => t.BalanceDate).Distinct().OrderBy(t => t).ToList(); for (var i = 0; i < balanceDateList.Count; i++) { var tempBalancedaily = allOldClientbalancedaily.Where(t => t.BalanceDate == balanceDateList[i]); var tempNewclientbalancedaily = new ClientBalanceDaily { ClientId = baseClient.id, ClientName = baseClient.Name, ClientNumber = baseClient.Number, BalanceDate = balanceDateList[i], ToDayRemainFund = RemainFund + tempBalancedaily.Sum(t => -((t.OptionPremium ?? 0.0) + (t.OptionPremiumSwap ?? 0.0) + (t.SettlementBalance ?? 0.0) + (t.Coupon ?? 0.0) + (t.SwapBalance ?? 0.0))), LastDayRemainFund = RemainFund, DayGainLoss = tempBalancedaily.Sum(t => -(t.DayGainLoss ?? 0.0)), OptionPremium = tempBalancedaily.Sum(t => -(t.OptionPremium ?? 0.0)), OptionPremiumSwap = tempBalancedaily.Sum(t => -(t.OptionPremiumSwap ?? 0.0)), SettlementBalance = tempBalancedaily.Sum(t => -(t.SettlementBalance ?? 0.0)), UnwindBalance = tempBalancedaily.Sum(t => -(t.UnwindBalance ?? 0.0)), SwapBalance = tempBalancedaily.Sum(t => -(t.SwapBalance ?? 0.0)), Coupon = tempBalancedaily.Sum(t => -(t.Coupon ?? 0.0)), ExerciseBalance = tempBalancedaily.Sum(t => -(t.ExerciseBalance ?? 0.0)), AdvisableMargin = RemainFund + tempBalancedaily.Sum(t => -((t.OptionPremium ?? 0.0) + (t.OptionPremiumSwap ?? 0.0) + (t.SettlementBalance ?? 0.0) + (t.Coupon ?? 0.0) + (t.SwapBalance ?? 0.0))), TotalNominal = tempBalancedaily.Sum(t => (t.TotalNominal ?? 0.0)), Pv = tempBalancedaily.Sum(t => -(t.Pv ?? 0.0)), MarginBalance = RemainFund + tempBalancedaily.Sum(t => -((t.OptionPremium ?? 0.0) + (t.OptionPremiumSwap ?? 0.0) + (t.SettlementBalance ?? 0.0) + (t.Coupon ?? 0.0) + (t.SwapBalance ?? 0.0))), OptId = UserId, OptName = UserName, OptDate = DateTime.Now, }; RemainFund = tempNewclientbalancedaily.ToDayRemainFund ?? 0.0; newClientBalanceDaily.Add(tempNewclientbalancedaily); } } #endregion if (allNewClientbalanceList.Any()) { if (baseClientBalanceDaily == null) { baseClientBalanceDaily = new ClientBalanceDaily { ClientId = baseClient.id, ClientName = baseClient.Name, ClientNumber = baseClient.Number, BalanceDate = balanceDate, OptId = UserId, OptName = UserName, OptDate = DateTime.Now, }; } baseClientBalanceDaily.ToDayRemainFund += allNewClientbalanceList.Sum(t => -((t.OptionPremium ?? 0.0) + (t.OptionPremiumSwap ?? 0.0) + (t.SettlementBalance ?? 0.0) + (t.Coupon ?? 0.0) + (t.SwapBalance ?? 0.0))) + RemainFund; baseClientBalanceDaily.LastDayRemainFund += RemainFund; baseClientBalanceDaily.DayGainLoss = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.DayGainLoss) + allNewClientbalanceList.Sum(t => -(t.DayGainLoss ?? 0.0)); baseClientBalanceDaily.OptionPremium = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.OptionPremium) + allNewClientbalanceList.Sum(t => -(t.OptionPremium ?? 0.0)); baseClientBalanceDaily.OptionPremiumSwap = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.OptionPremiumSwap) + allNewClientbalanceList.Sum(t => -(t.OptionPremiumSwap ?? 0.0)); baseClientBalanceDaily.SettlementBalance = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.SettlementBalance) + allNewClientbalanceList.Sum(t => -(t.SettlementBalance ?? 0.0)); baseClientBalanceDaily.UnwindBalance = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.UnwindBalance) + allNewClientbalanceList.Sum(t => -(t.UnwindBalance ?? 0.0)); baseClientBalanceDaily.ExerciseBalance = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.ExerciseBalance) + allNewClientbalanceList.Sum(t => -(t.ExerciseBalance ?? 0.0)); baseClientBalanceDaily.Coupon = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.Coupon) + allNewClientbalanceList.Sum(t => -(t.Coupon ?? 0.0)); baseClientBalanceDaily.SwapBalance = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.SwapBalance) + allNewClientbalanceList.Sum(t => -(t.SwapBalance ?? 0.0)); baseClientBalanceDaily.AdvisableMargin = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.ToDayRemainFund) + allNewClientbalanceList.Sum(t => -((t.OptionPremium ?? 0.0) + (t.OptionPremiumSwap ?? 0.0) + (t.SettlementBalance ?? 0.0) + (t.Coupon ?? 0.0) + (t.SwapBalance ?? 0.0))) + RemainFund; baseClientBalanceDaily.TotalNominal = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.TotalNominal) + allNewClientbalanceList.Sum(t => (t.TotalNominal ?? 0.0)); baseClientBalanceDaily.Pv = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.Pv) + allNewClientbalanceList.Sum(t => -(t.Pv ?? 0.0)); baseClientBalanceDaily.MarginBalance = (baseClientBalanceDaily == null ? 0 : baseClientBalanceDaily.MarginBalance) + allNewClientbalanceList.Sum(t => -((t.OptionPremium ?? 0.0) + (t.OptionPremiumSwap ?? 0.0) + (t.SettlementBalance ?? 0.0) + (t.Coupon ?? 0.0) + (t.SwapBalance ?? 0.0))) + RemainFund; } } #endregion #region DB删除历史数据 增加当日数据 var sql = $"{nameof(ClientBalanceDaily.BalanceDate)}='{balanceDate.ToSqlDate()}'"; if (_context.ClienIds != null && _context.ClienIds.Any()) { sql += $" and ClientId in ({string.Join(",", _context.ClienIds)})"; } //删除 当日导入的old日数据 DbContext.BulkDelete(sql); //MySqlBulkExtensions.BulkInsert(DbContext, newClientBalanceDaily); DbContext.ClientBalanceDaily.AddRange(newClientBalanceDaily); DbContext.SaveChanges(); #endregion return true; } /// /// 客户资金未确认状态检查 /// public void ClientCashInCashOutCheck() { var balanceDate = _context.SettleDate; var reqClientIds = _context.Request.ClientIds; var newValuedate = balanceDate.AddDays(1); var cashInCashOuts = DbContext.ClientCashInCashOut.Where(x => x.HappenDate >= balanceDate && x.HappenDate < newValuedate && x.ValidState != ConsGlobal.InValid && ClientCashInCashOut.calcCashs.Contains(x.State) && ClientCashInCashOut.cashStateChecks.Contains(x.Direction)).AsNoTracking().ToList(); if (reqClientIds != null && reqClientIds.Any()) { cashInCashOuts = cashInCashOuts.Where(x => reqClientIds.Contains(x.ClientId ?? 0)).ToList(); } if (cashInCashOuts.Any()) { _context.RaiseError("客户资金结算", $"{balanceDate:yyyy年MM月dd日}存在未确认的资金,请先将资金确认后再操作"); } } private void AddToFund(Dictionary fundDictionary, string currencyCode, double amount) { if (fundDictionary.ContainsKey(currencyCode)) { fundDictionary[currencyCode] += amount; } else { fundDictionary.Add(currencyCode, amount); } } } }