using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using YLErp.BLL; using YLErp.BLL.Eod; using YLErp.BLL.EodSettlement; using YLErp.DBModels; using YLErp.Model; using YLErp.Models; using YLErp.Modules.EodModule.QueryModule; using YLErp.QdpModule; namespace YLErp.Modules.SwapModule { /// /// trs交易端客户资金监控服务 /// public class SwapMonitorService : YLBaseService { public SwapMonitorService(OptUserInfo optUser) : base(optUser) { } public ClientBalanceMonitorForTrsRespone GetMonitorForTrsRespone(ClientBalanceMonitorFroTrsRequest request) { var valueDate = valuedateBLL.ValueDate; ClientBalanceMonitorForTrsRespone balanceMonitorForTrsRespone = new ClientBalanceMonitorForTrsRespone(); var swapMonitorConfgValue = AppManager.GetSwapMonitorValue(); SwapMonitorConfig monitorConfig = new SwapMonitorConfig(); if (!string.IsNullOrEmpty(swapMonitorConfgValue)) { monitorConfig = JsonHelper.Deserialize(swapMonitorConfgValue); } balanceMonitorForTrsRespone.WarningLine = monitorConfig.WarningLine * 0.01; balanceMonitorForTrsRespone.UnwindLine = monitorConfig.UnwindLine * 0.01; if (!request.ClientIds.Any()) { var clientPredicate = PredicateBuilder.Create(x => x.ProcessStatus == "已开户"); var clientquery = DataCacheProvider.GetClientDataSource().AsQueryable(clientPredicate); request.ClientIds = clientquery.Select(s => s.id).ToList(); } var balances = ClientBalanceUtility.GetClientBanlances(request.ClientIds, DateTime.MinValue, valueDate).ToList(); balanceMonitorForTrsRespone.BalanceMonitorForTrsItems = MapToMonitorForTrsItems(balances); var lastBalances = clientBalanceDailies(request.ClientIds, 1, valueDate); MapToClientBalanceMonitor(balanceMonitorForTrsRespone, balances, lastBalances); return balanceMonitorForTrsRespone; } /// /// 获取客户历史资金记录 /// /// /// public List GetMonitorForTrsBuyDailyRespone(ClientBalanceMonitorFroTrsRequest request) { var valueDate = valuedateBLL.ValueDate; var lastBalances = clientBalanceDailies(request.ClientIds, request.SearchDays, valueDate); return MapToMonitorForTrsItems(lastBalances); } /// /// 获取客户历史资金结算 /// /// /// /// /// private List clientBalanceDailies(List clientIds, int searchDays, DateTime valueDate) { List clientSettleBalances = new List(); if (!clientIds.Any()|| searchDays == 0) { return clientSettleBalances; } var lastBalanceDate = EodOperationBase.GetLastSettlementDate(valueDate); if (lastBalanceDate == valueDate) { lastBalanceDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(-1)); } var days = QdpCalendarHelper.GetWorkingDatesBeforeDate(lastBalanceDate, searchDays); var firstDay = days.OrderBy(s => s).First(); var endQuery = from t in DbContext.ClientBalanceDaily join cs in DbContext.client_span.Where(eod_cs => eod_cs.SpanType == ClientSpan.SpanType_Eod) on new { t.ClientId, ValueDate = t.BalanceDate } equals new { cs.ClientId, cs.ValueDate } into eodClientSpan from cs in eodClientSpan.DefaultIfEmpty() where t.BalanceDate >= firstDay && clientIds.Contains(t.ClientId) select new { ClientId = t.ClientId, ValueDate = t.BalanceDate, FreezePremium = t.FrozenPremium ?? 0.0, ReceivablesPremium = 0.0, AmountFund = t.ToDayRemainFund ?? 0.0, GuaranteesTotalAmount = t.TodayRemianFundProduct ?? 0.0, //仅用于广期资本可用资金计算 //可用资金1 = 净入金 + 已实现盈亏 + 浮动盈亏 - 次日最大亏损; //可用资金2 = 净入金 + 已实现盈亏 - 持仓期初净支付权利金; //可用资金 = min(可用资金1,可用资金2); AvailableAmount1 = (t.NetFundSum ?? 0) + (t.WinLossSum ?? 0) + (t.PositionPnl ?? 0) + (cs.WorstCastClientPayable ?? 0), AvailableAmount2 = (t.NetFundSum ?? 0) + (t.WinLossSum ?? 0) - (t.OptionPremiumSum ?? 0) - (t.OptionPremiumSwapSum ?? 0), AvailableAmount = (t.MarginBalance ?? 0.0) + (t.PayableMargin ?? 0.0) - (t.FrozenMarginMoney ?? 0.0) - (t.TodayRemianFundProduct ?? 0.0),//t.FrozenMarginMoney是通道业务显示所用到的 TotalCredit = t.Credit ?? 0.0, PayableMargin = t.PayableMargin ?? 0.0, DeltaMargin = t.DeltaMargin ?? 0d, SwapPayableMargin = t.SwapPayableMargin ?? 0.0, SwapUnPayableMargin = t.SwapUnPayableMargin ?? 0.0, TwoSideMargin = t.TwoSideMargin ?? 0.0, OtherSideMargin = t.OtherSideMargin ?? 0.0, MySideMargin = t.MySideMargin ?? 0.0, IsPayableMarginManual = t.IsPayableMarginManual, IsPayableMarginLock = cs == null ? false : cs.ModifiedFlag, FrozenMarginMoney = t.FrozenMarginMoney ?? 0.0, FrozenOutFund = t.FrozenOutFund ?? 0.0, MarginBalance = t.MarginBalance ?? 0.0, Coupon = t.Coupon ?? 0.0, SwapBalance = t.SwapBalance ?? 0.0, Margin = t.Margin ?? 0.0, //IsTradeCredit = t.IsTradeCredit ?? c.IsTradeCredit == 1, TodayNewMargin = 0, PositionPv = t.Pv ?? 0, RoundedPositionPv = t.RoundedPv ?? 0, SellPv = t.SellPv ?? 0, PrepaymentAmount = t.PrepaymentAmount ?? 0.0, DaliyPnl = t.DailyPnl ?? 0, PositionPnl = t.PositionPnl ?? 0, RoundedPositionPnl = t.RoundedPositionPnl ?? 0, ClientSellPositionPnl = t.ClientSellPositionPnl ?? 0, PositionPremiumNetCash = t.PositionPremiumNetCash ?? 0, LastDayPositionPremiumNetCash = t.LastDayPositionPremiumNetCash ?? 0, SellTradePrice = t.SellTradePrice, AvailableStockEqvNotional = t.AvailableStockEqvNotional ?? 0, FrozenBalance = t.FrozenBalance ?? 0, TdWinLoss = t.WinLoss, MarginJson = cs.PVJsons }; var endDatas = endQuery.ToArray(); foreach (var data in endDatas) { var client = DataCacheProvider.GetClientDataSource().GetData(data.ClientId); ClientSettleBalance balance = new ClientSettleBalance(); balance.ClientId = data.ClientId; balance.ValueDate = data.ValueDate; balance.FrozenBalance = data.FrozenBalance; balance.FreezePremium = data.FreezePremium; balance.ReceivablesPremium = data.ReceivablesPremium; balance.AmountFund = data.AmountFund; balance.AvailableAmount = data.AvailableAmount; balance.TotalCredit = data.TotalCredit; balance.PayableMargin = data.PayableMargin; balance.GuaranteesTotalAmount = data.GuaranteesTotalAmount; balance.AvailableAmount = balance.AmountFund + balance.TotalCredit + balance.PayableMargin + balance.GuaranteesTotalAmount; balance.DeltaMargin = data.DeltaMargin; balance.SwapPayableMargin = data.SwapPayableMargin; balance.SwapUnMargin = data.SwapUnPayableMargin; balance.TwoSideMargin = data.TwoSideMargin; balance.OtherSideMargin = data.OtherSideMargin; balance.MySideMargin = data.MySideMargin; balance.IsPayableMarginManual = data.IsPayableMarginManual; balance.IsPayableMarginLock = data.IsPayableMarginLock; balance.FrozenMarginMoney = data.FrozenMarginMoney; balance.FrozenOutFund = data.FrozenOutFund; balance.MarginBalance = data.MarginBalance; balance.Margin = data.Margin; balance.UpdateDate = DateTime.Now; balance.IsTradeCredit = client?.IsTradeCredit == 1; balance.TodayNewMargin = data.TodayNewMargin; balance.PositionPv = data.PositionPv; balance.RoundedPositionPv = data.RoundedPositionPv; balance.SellPv = data.SellPv; balance.PrepaymentAmount = data.PrepaymentAmount; balance.DaliyPnl = data.DaliyPnl; balance.PositionPnl = data.PositionPnl; balance.RoundedPositionPnl = data.RoundedPositionPnl; balance.ClientSellPositionPnl = data.ClientSellPositionPnl; balance.PositionPremiumNetCash = data.PositionPremiumNetCash; balance.SellTradePrice = data.SellTradePrice ?? 0; balance.LastDayPositionPremiumNetCash = data.LastDayPositionPremiumNetCash; balance.MarginOptionType = client?.MarginOptionType ?? 0; balance.IsLatestDate = true; balance.IsEodData = true; balance.TdWinLoss = data.TdWinLoss ?? 0; balance.AvailableStockEqvNotional = data.AvailableStockEqvNotional; balance.MarginJson = data.MarginJson; balance.ClientType = client.SwapTradeType ?? 0; balance.ClientName = client.Name; balance.ClientNumber = client.Number; clientSettleBalances.Add(balance); } return clientSettleBalances; } private List MapToMonitorForTrsItems(List clientSettleBalances) { List monitorForTrsItems = new List(); clientSettleBalances.ForEach(item => { ClientBalanceMonitorForTrsItem clientBalanceMonitorForTrsItem = new ClientBalanceMonitorForTrsItem() { ClientId=item.ClientId, ClientName = item.ClientName, ClientNumber = item.ClientNumber, ClientTypeStr = item.ClientTypeStr, AmountFund = item.AvailableAmount, MaintenanceLine = item.MaintenanceLine, MarginByPayableMarginTotal = item.MarginByPayableMargin, ValueDate = item.ValueDate }; monitorForTrsItems.Add(clientBalanceMonitorForTrsItem); }); return monitorForTrsItems; } /// /// 与昨日比较 /// /// /// /// private void MapToClientBalanceMonitor(ClientBalanceMonitorForTrsRespone balanceMonitorForTrsRespone, List balances, List lastBalances) { var lastDurationNotionalPrincipal = lastBalances.Sum(s => Math.Abs(s.PositionNotionalPrincipal)); var lastDurationClient = lastBalances.Count(s => s.PositionPv != 0); var lastUnwindlineClient = lastBalances.Count(s => s.MaintenanceLine <= balanceMonitorForTrsRespone.UnwindLine); var lastFundShortageClient = lastBalances.Count(s => s.AvailableAmount < 0); var lastWarninglineClient = lastBalances.Count(s => s.MaintenanceLine <= balanceMonitorForTrsRespone.WarningLine&&s.MaintenanceLine> balanceMonitorForTrsRespone.UnwindLine); balanceMonitorForTrsRespone.DurationNotionalPrincipal = balances.Sum(s => Math.Abs(s.PositionNotionalPrincipal)); var DurationNotionalPrincipalCompareLastDay= Convert.ToDouble(balanceMonitorForTrsRespone.DurationNotionalPrincipal - lastDurationNotionalPrincipal); if (lastDurationNotionalPrincipal==0) { if (DurationNotionalPrincipalCompareLastDay == 0) { balanceMonitorForTrsRespone.DurationNotionalPrincipalCompareLastDay = 0; } else { balanceMonitorForTrsRespone.DurationNotionalPrincipalCompareLastDay = 1; } } else { balanceMonitorForTrsRespone.DurationNotionalPrincipalCompareLastDay = DurationNotionalPrincipalCompareLastDay / Convert.ToDouble(lastDurationNotionalPrincipal); } balanceMonitorForTrsRespone.DurationClient = balances.Count(s => s.PositionPv != 0); var DurationClientCompareLastDay = Convert.ToDouble(balanceMonitorForTrsRespone.DurationClient - lastDurationClient); if (lastDurationClient == 0) { if (DurationClientCompareLastDay == 0) { balanceMonitorForTrsRespone.DurationClientCompareLastDay = 0; } else { balanceMonitorForTrsRespone.DurationClientCompareLastDay = 1; } } else { balanceMonitorForTrsRespone.DurationClientCompareLastDay = DurationClientCompareLastDay / Convert.ToDouble(lastDurationClient); } balanceMonitorForTrsRespone.UnwindlineClient = balances.Count(s => s.MaintenanceLine <= balanceMonitorForTrsRespone.UnwindLine); var UnwindlineClientCompareLastDay = Convert.ToDouble(balanceMonitorForTrsRespone.UnwindlineClient - lastUnwindlineClient); if (lastUnwindlineClient == 0) { if (UnwindlineClientCompareLastDay == 0) { balanceMonitorForTrsRespone.UnwindlineClientCompareLastDay = 0; } else { balanceMonitorForTrsRespone.UnwindlineClientCompareLastDay = 1; } } else { balanceMonitorForTrsRespone.UnwindlineClientCompareLastDay = UnwindlineClientCompareLastDay / Convert.ToDouble(lastUnwindlineClient); } balanceMonitorForTrsRespone.FundShortageClient = balances.Count(s => s.AvailableAmount < 0); var FundShortageClientCompareLastDay = Convert.ToDouble(balanceMonitorForTrsRespone.FundShortageClient - lastFundShortageClient); if (lastFundShortageClient == 0) { if (FundShortageClientCompareLastDay == 0) { balanceMonitorForTrsRespone.FundShortageClientCompareLastDay = 0; } else { balanceMonitorForTrsRespone.FundShortageClientCompareLastDay = 1; } } else { balanceMonitorForTrsRespone.FundShortageClientCompareLastDay = FundShortageClientCompareLastDay / Convert.ToDouble(lastFundShortageClient); } balanceMonitorForTrsRespone.WarninglineClient = balances.Count(s => s.MaintenanceLine <= balanceMonitorForTrsRespone.WarningLine && s.MaintenanceLine > balanceMonitorForTrsRespone.UnwindLine); var WarninglineClientCompareLastDay = Convert.ToDouble(balanceMonitorForTrsRespone.WarninglineClient - lastWarninglineClient); if (lastWarninglineClient == 0) { if (WarninglineClientCompareLastDay == 0) { balanceMonitorForTrsRespone.WarninglineClientCompareLastDay = 0; } else { balanceMonitorForTrsRespone.WarninglineClientCompareLastDay = 1; } } else { balanceMonitorForTrsRespone.WarninglineClientCompareLastDay = WarninglineClientCompareLastDay / Convert.ToDouble(lastWarninglineClient); } } } }