using BaseOUDAL; using Qdp.Foundation.Implementations; using YLErp.BLL; using YLErp.BLL.EodSettlement; using YLErp.CustomizedBizLogic; using YLErp.DBModels.Consts; using YLErp.Model; using YLErp.Model.Enum; using YLErp.QdpModule; namespace YLErp.Modules.TradeModule.SwapModule { /// /// 互换交易服务 /// public class TradeSwapService : YLBaseService { public TradeSwapService(OptUserInfo userInfo) : base(userInfo) { } /// /// 查询trade /// public SearchListResult SearchList(TradeReq req, out tradeGridSum gsum, bool isUnionToday = false, bool isExerciseDateReport = false, bool isWithStructTrade = false) { var query = CreateTradeQuery(req, isUnionToday, isExerciseDateReport); var resultTrade = query.ToList(); var todaybalanceStatus = new List { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 }; var observateTrades = new List(); if (req.ValueDate != null) { var dateStr = req.ValueDate?.ToString("yyyy-MM-dd"); var swapTradeIds = resultTrade.Select(o => o.id).ToList(); var swapTrades = DbContext.swap_position.Where(t => swapTradeIds.Contains(t.SwapTradeId) && t.InterestDirection > 0 && t.IsInitial&&!t.Invalid).ToList(); foreach (var r in resultTrade) { var interests = swapTrades.Where(x => x.SwapTradeId == r.id).ToList(); if (interests.Any(s => s.SwapIntervalList.Any(x => x.Date == req.ValueDate))) { observateTrades.Add(r); } } query = observateTrades.AsQueryable(); } var retListResult = query.ToSearchList(req); if (req.TabIndex == (int)TradeTabIndexEnum.互换观察日) { var list = new List(); list.AddRange(retListResult.rows.Where(t => !todaybalanceStatus.Contains(t.TradeStatus))); list.AddRange(retListResult.rows.Where(t => todaybalanceStatus.Contains(t.TradeStatus))); retListResult.rows = list; } gsum = new tradeGridSum(); if (query.Any()) { gsum.TradePriceSum = query.Sum(q => q.TradePrice); } //获取销售提成信息 foreach (var item in retListResult.rows) { item.SalesCommission = new SalesModule.SalesCommissionDataService(OptUser).GetTradeCommissionInfo(item.id); if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && item.SalesCommission?.Commission != null) { item.SalesCommission.Commission = item.SalesCommission.Commission * item.SalesCommission.SalesIds.Count(); } item.SettlementDate ??= item.ExerciseDate; } retListResult.Sum = gsum; return retListResult; } /// /// trade_swap_flow /// public SearchListResult SearchFlowList(TradeFlowReq req) { var query = from source in DbContext.trade_swap_flow select source; if (!string.IsNullOrEmpty(req.ClientNumber)) { query = query.Where(d => d.ClientNumber == req.ClientNumber); } if (!string.IsNullOrEmpty(req.TradeNumber)) { query = query.Where(d => d.TradeNumber == req.TradeNumber); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { query = query.Where(d => d.UnderlyingCode.Contains(req.UnderlyingCode)); } if (req.AssetUnitNames != null && req.AssetUnitNames.Count > 0) { query = query.Where(d => req.AssetUnitNames.Contains(d.AssetUnitName)); } if (req.TradeDateStart != DateTime.MinValue) { query = query.Where(d => d.TradeDate >= req.TradeDateStart); } if (req.TradeDateEnd != DateTime.MinValue) { var TradeDateTemp = req.TradeDateEnd.AddDays(1); query = query.Where(d => d.TradeDate < TradeDateTemp); } if (req.ExerciseDateStart != DateTime.MinValue) { query = query.Where(d => d.ExerciseDate >= req.ExerciseDateStart); } if (req.ExerciseDateEnd != DateTime.MinValue) { var ExerciseDateTemp = req.ExerciseDateEnd.AddDays(1); query = query.Where(d => d.ExerciseDate < ExerciseDateTemp); } if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "TradeDate,id"; req.sord = "asc"; } var retListResult = query.ToSearchList(req); return retListResult; } /// /// trade_swap_flow /// public SearchListResult SearchFlowHistoryList(TradeFlowReq req) { var query = from source in DbContext.trade_flow_history select source; if (req.ClientIds != null && req.ClientIds.Any()) { query = query.Where(d => req.ClientIds.Contains(d.ClientId)); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { query = query.Where(d => d.UnderlyingCode.Contains(req.UnderlyingCode)); } if (req.TradeDateStart != DateTime.MinValue) { query = query.Where(d => d.TradeDate >= req.TradeDateStart); } if (req.TradeDateEnd != DateTime.MinValue) { query = query.Where(d => d.TradeDate <= req.TradeDateEnd); } if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "id"; req.sord = "desc"; } var retListResult = query.ToSearchList(req); return retListResult; } /// /// client_variety_config /// public SearchListResult SearchClientVarietyConfigList(ClientVarietyConfigReq req) { var query = from source in DbContext.client_variety_config select source; if (req.ClientId > 0) { query = query.Where(d => d.ClientId == req.ClientId); } if (req.VarietyId > 0) { query = query.Where(d => d.VarietyId == req.VarietyId); } if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "id"; req.sord = "desc"; } var retListResult = query.ToSearchList(req); foreach (var item in retListResult.rows) { var client = DataCacheProvider.GetClientDataSource().GetData(item.ClientId); item.ClientName = client?.Name; item.ClientNumber = client?.Number; var variety = DataCacheProvider.GetVarietyDataSource().GetData(item.VarietyId); item.VarietyCode = variety?.VarietyCode; item.VarietyName = variety?.VarietyName; } return retListResult; } // isWithStructTrade 是否 查找结构化交易的子交易默认false private IQueryable CreateTradeQuery(TradeReq req, bool isUnionToday = false, bool isExerciseDateReport = false) { var predicate = PredicateBuilder.Create(n => n.ValidState != "InValid" && n.TradeType == "收益互换" && n.IsGroup != 2); if (req.UserAssets != null && req.UserClients != null) { predicate = predicate.And(n => req.UserAssets.Contains(n.AssetId) || req.UserClients.Contains(n.ClientId)); } if (req.TagIds != null && req.TagIds.Count > 0) { var tradeTagIdQuery = from tt in DbContext.trade_tag where req.TagIds.Contains(tt.TagId) select tt.TradeId; predicate = predicate.And(p => tradeTagIdQuery.Contains(p.id)); } var query = DbContext.trade.Where(predicate); if (!string.IsNullOrEmpty(req.ContractCode)) { query = from source in query join tcrConfirm in DbContext.trade_contract_r.Where(aa => aa.Type == ContractTypeEnum.Trade && aa.IsValid) on new { id = source.ParentTradeId > 0 ? source.ParentTradeId : source.id } equals new { id = tcrConfirm.TradeId } into tcrConfirms from tcrConfirm in tcrConfirms.DefaultIfEmpty() where tcrConfirm.ContractCode.Contains(req.ContractCode) select source; } var predicate_sw = PredicateBuilder.Create(x => 1 == 1); var issw = false; if (!string.IsNullOrEmpty(req.UnderlyingIds)) { predicate_sw = predicate_sw.And(n => req.UnderlyingIdsInt.Contains(n.GetUnderlyingId ?? 0) || req.UnderlyingIdsInt.Contains(n.PayUnderlyingId ?? 0)); issw = true; } if (req.UnderlyingId != null) { predicate_sw = predicate_sw.And(d => d.GetUnderlyingId == req.UnderlyingId || d.PayUnderlyingId == req.UnderlyingId); issw = true; } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { predicate_sw = predicate_sw.And(d => d.GetUnderlyingCode.Contains(req.UnderlyingCode) || d.PayUnderlyingCode.Contains(req.UnderlyingCode)); issw = true; } if (req.UnderlyingCodeList != null) { predicate_sw = predicate_sw.And(d => req.UnderlyingCodeList.Contains(d.GetUnderlyingCode) || req.UnderlyingCodeList.Contains(d.PayUnderlyingCode)); issw = true; } if (issw) { query = from source in query join sw in DbContext.trade_swap.Where(predicate_sw) on source.id equals sw.TradeId select source; } if (!string.IsNullOrEmpty(req.UnderlyingAssetClass)) { query = query.Where(d => d.UnderlyingAssetClass.Contains(req.UnderlyingAssetClass)); } if (!string.IsNullOrEmpty(req.ClientIds)) { query = query.Where(d => req.ClientIdsInt.Contains(d.ClientId)); } if (!string.IsNullOrEmpty(req.UnderlyingInstrumentTypes)) { query = query.Where(d => req.UnderlyingInstrumentTypesList.Contains(d.UnderlyingInstrumentType)); } if (!string.IsNullOrEmpty(req.OptIds)) { query = query.Where(d => req.OptIdsList.Contains(d.OptId + "")); } if (!string.IsNullOrEmpty(req.Comments)) { query = query.Where(d => d.Comments.Contains(req.Comments)); } if (!string.IsNullOrEmpty(req.TradeIds)) { query = query.Where(d => req.TradeIdList.Contains(d.id)); } if (req.AssetIdList.Any()) { query = query.Where(d => req.AssetIdList.Contains(d.AssetId)); } //获取当日成交的数据 //当日成交包括操作日期和交易日为当前系统日期的数据 if (req.TabIndex == (int)TradeTabIndexEnum.今日成交) { var optDateStart = valuedateBLL.ValueDate; var optDateEnd = valuedateBLL.ValueDate.AddDays(1); var tradeDateStart = valuedateBLL.ValueDate; var tradeDateEnd = valuedateBLL.ValueDate.AddDays(1); query = query.Where(d => (d.TradeDate >= tradeDateStart && d.TradeDate < tradeDateEnd) || (d.OptDate >= optDateStart && d.OptDate < tradeDateEnd)); } else { if (req.TradeDateStart != DateTime.MinValue) { query = query.Where(d => d.TradeDate >= req.TradeDateStart); } if (req.TradeDateEnd != DateTime.MinValue) { var TradeDateTemp = req.TradeDateEnd.AddDays(1); query = query.Where(d => d.TradeDate < TradeDateTemp); } if (req.OptDateStart != DateTime.MinValue) { query = query.Where(d => d.OptDate >= req.OptDateStart); } if (req.OptDateEnd != DateTime.MinValue) { var OptDateTemp = req.OptDateEnd.AddDays(1); query = query.Where(d => d.OptDate < OptDateTemp); } } //获取当日到期日数据 if (req.TabIndex == (int)TradeTabIndexEnum.今日到期) { query = query.Where(d => d.ExerciseDate == valuedateBLL.ValueDate); } //获取明日到期日数据 else if (req.TabIndex == (int)TradeTabIndexEnum.明日到期) { var tommorow = QdpCalendarHelper.GetNonHoliday(valuedateBLL.ValueDate.AddDays(1)); query = query.Where(d => d.ExerciseDate == tommorow); } else { if (req.ExerciseDateEnd == null) { req.ExerciseDateEnd = DateTime.MaxValue; } if (req.ExerciseDateStart == null) { req.ExerciseDateStart = DateTime.MinValue; } if (isExerciseDateReport) { query = query.Where(d => d.ExerciseDate >= req.ExerciseDateStart && d.ExerciseDate <= req.ExerciseDateEnd); } else { query = query.Where(d => d.ExerciseDate == null || (d.ExerciseDate >= req.ExerciseDateStart && d.ExerciseDate <= req.ExerciseDateEnd)); } } if (req.SettlementDateEnd != null && req.SettlementDateEnd != DateTime.MinValue) { var TradeDateTemp = req.SettlementDateEnd.Value.AddDays(1); query = query.Where(d => (d.SettlementDate ?? d.ExerciseDate) < TradeDateTemp); } if (req.SettlementDateStart != null && req.SettlementDateStart != DateTime.MinValue) { query = query.Where(d => (d.SettlementDate ?? d.ExerciseDate) >= req.SettlementDateStart); } if (!string.IsNullOrEmpty(req.TraderNames)) { query = query.Where(d => req.TraderNamesList.Contains(d.TraderId)); } if (!string.IsNullOrEmpty(req.TradeNumber)) { var tradequery = DbContext.trade.Where(t => t.TradeNumber.Equals(req.TradeNumber)); query = query.Where(d => d.TradeNumber.Contains(req.TradeNumber) || tradequery.Select(x => x.ParentTradeId).Contains(d.id) || (tradequery.Select(x => x.ParentTradeId).Contains(d.ParentTradeId) && d.ParentTradeId > 0)); } if (req.ClientId != null) { query = query.Where(d => d.ClientId == req.ClientId); } if (!string.IsNullOrEmpty(req.ClientName)) { query = query.Where(d => d.ClientName.Contains(req.ClientName)); } if (!string.IsNullOrEmpty(req.BuySell)) { query = query.Where(d => d.BuySell.Contains(req.BuySell)); } if (!string.IsNullOrEmpty(req.OptionType)) { query = query.Where(d => d.OptionType == req.OptionType); } if (req.StartDateStart != DateTime.MinValue) { query = query.Where(d => d.StartDate >= req.StartDateStart); } if (req.StartDateEnd != DateTime.MinValue) { var StartDateTemp = req.StartDateEnd.AddDays(1); query = query.Where(d => d.StartDate < StartDateTemp); } //过滤已平仓,已到期,已执行数据 else if (req.TabIndex == (int)TradeTabIndexEnum.今日到期 || req.TabIndex == (int)TradeTabIndexEnum.明日到期) { query = query.Where(d => d.TradeStatus != ConsTrade.已平仓 && d.TradeStatus != ConsTrade.已到期 && d.TradeStatus != ConsTrade.已执行); } if (!string.IsNullOrEmpty(req.TradeStatus)) { var statuses = req.TradeStatus.Split(',').ToList(); query = query.Where(d => statuses.Contains(d.TradeStatus)); } if (req.TradeStatusList != null) { query = query.Where(d => req.TradeStatusList.Contains(d.TradeStatus)); } if (req.AssetIdList.Any()) { query = query.Where(d => req.AssetIdList.Contains(d.AssetId)); } if (req.ClientIdsInt.Any()) { query = query.Where(d => req.ClientIdsInt.Contains(d.ClientId)); } if (req.SettlementFlags != null && req.SettlementFlags.Any()) { query = query.Where(d => req.SettlementFlags.Contains(d.SettlementFlag)); } if (!string.IsNullOrEmpty(req.OptName)) { query = query.Where(d => d.OptName.Contains(req.OptName)); } query = query.Where(d => !d.ValidState.Equals("InValid")); if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "id"; req.sord = "desc"; } if (isUnionToday) { var todaybalanceStatus = new List { "已到期", "已执行", "已平仓" }; var curDate = valuedateBLL.ValueDate; //+ trade今天被exercise/expire的option. 排序按照optDate,从新到旧排 query = query.Union(from s in DbContext.trade where s.ClientId == req.ClientId && todaybalanceStatus.Contains(s.TradeStatus) && s.OptDate >= curDate select s); } query = query.OrderByDescending(s => s.OptDate); return query; } public void DeleteTradeFlowOnly(int id) { var tradeSwapFlow = DbContext.trade_swap_flow.Find(id); DbContext.trade_swap_flow.Remove(tradeSwapFlow); DbContext.SaveChanges(); } public void DeleteTradeFlow(int id) { using var trans = BeginTransaction(); var tradeSwapFlow = DbContext.trade_swap_flow.Find(id); new SwapTradeFlowImportService(this).BackSwapTradeByTradeFlow(tradeSwapFlow); var tradeSwapFlows = DbContext.trade_swap_flow.Where(x => x.UnderlyingCode == tradeSwapFlow.UnderlyingCode && x.ClientNumber == tradeSwapFlow.ClientNumber && ((x.id > tradeSwapFlow.id && x.TradeDate == tradeSwapFlow.TradeDate) || x.TradeDate > tradeSwapFlow.TradeDate)).OrderBy(x => x.TradeDate).ThenBy(x => x.id).ToList(); tradeSwapFlows.ForEach(x => { new SwapTradeFlowImportService(this).HandleSwapTrade(x); x.Status = "已完成"; }); DbContext.trade_swap_flow.Remove(tradeSwapFlow); DbContext.SaveChanges(); trans.Commit(); } public void ComposeTrade(List ids) { var service = new SwapTradeFlowImportService(UserInfo); var flows = DbContext.trade_swap_flow.Where(x => ids.Contains(x.id)).ToList(); if (flows.Any(x => x.Status == "已完成")) { throw new ServiceException("存在已完成的交易流水,不能重复合成"); } if (true) { var flowGroups = flows.GroupBy(x => new { x.ClientNumber, x.UnderlyingCode, x.BuySell, x.TradeDate }).Select(x => new trade_swap_flow() { id = x.Min(y => y.id), ClientNumber = x.Key.ClientNumber, UnderlyingCode = x.Key.UnderlyingCode, BuySell = x.Key.BuySell, AssetUnitName = x.FirstOrDefault().AssetUnitName, ClearingAgency = x.FirstOrDefault().ClearingAgency, ClientShortName = x.FirstOrDefault().ClientShortName, Comments = "", ExerciseDate = x.Max(y => y.ExerciseDate), IsNight = x.FirstOrDefault().IsNight, IsTradePriceWhenOpen = x.FirstOrDefault().IsTradePriceWhenOpen, Lots = x.Sum(y => y.Lots), NeedCostFee = x.FirstOrDefault().NeedCostFee, Number = "", UnAnnualRate = x.FirstOrDefault().UnAnnualRate, QuoteCurrency = x.FirstOrDefault().QuoteCurrency, SettlementDate = x.FirstOrDefault().SettlementDate, SingleFee = x.FirstOrDefault().SingleFee, SpotPrice = x.Sum(y => y.SpotPrice * y.Lots) / x.Sum(y => y.Lots), StartDate = x.FirstOrDefault().StartDate, TradeDate = x.Key.TradeDate, OptDate = DateTime.Now, OptName = UserName, OptId = UserId }).OrderBy(x => x.id).ToList(); flowGroups.ForEach(x => { service.HandleSwapTrade(x); }); } else { //flows.ForEach(x => //{ // service.HandleSwapTrade(x); //}); } flows.ForEach(x => { x.Status = "已完成"; x.OptDate = DateTime.Now; x.OptName = UserName; x.OptId = UserId; }); DbContext.SaveChanges(); } public void FIFOTradeFlow() { using var trans = BeginTransaction(); var tradeSwapFlows = DbContext.trade_swap_flow.Where(x => x.TradeDate == valuedateBLL.ValueDate && x.Status != "已完成").OrderBy(x => x.id).ToList(); tradeSwapFlows.ForEach(x => { if (string.IsNullOrEmpty(x.TradeNumber)) { new SwapTradeFlowImportService(this).HandleSwapTrade(x); x.Status = "已完成"; } }); DbContext.SaveChanges(); trans.Commit(); } public trade_swap_flow SaveTradeFlow(trade_swap_flow req) { if (req.UnAnnualRate != null) { req.UnAnnualRate /= 100; } if (req is null) { throw new ArgumentNullException(nameof(req)); } if (req.id > 0) { return UpdateTradeFlow(req); } else { return AddTradeFlow(req); } } public trade_swap_flow AddOrUpdateTradeFlowOnly(trade_swap_flow req) { req.UnAnnualRate /= 100; if (string.IsNullOrEmpty(req.TradeNumber) && string.IsNullOrEmpty(req.ClientNumber)) { throw new ServiceException($"普通互换客户编号不能为空"); } if (string.IsNullOrEmpty(req.TradeNumber) && string.IsNullOrEmpty(req.AssetUnitName)) { throw new ServiceException($"普通互换簿记账户不能为空"); } if (req.ExerciseDate == null) { //标的代码(必需) var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(req.UnderlyingCode); if (underlying == null) { throw new ServiceException($"该标的代码[{req.UnderlyingCode}]在系统中不存在"); } else { req.ExerciseDate = underlying.MaturityDate; } } var variety = DataCacheProvider.GetVariety(req.UnderlyingCode); if (variety == null) { throw new Exception($"该标的[{req.UnderlyingCode}]对应的品种在系统中不存在"); } else { if (string.IsNullOrWhiteSpace(variety.QuoteCurrency) && DbContext.currency.Any()) { throw new Exception($"标的代码[{req.UnderlyingCode}]对应的品种币种不能为空"); } else { req.QuoteCurrency = variety.QuoteCurrency; } } if (req.ExerciseDate == null) { throw new Exception($"客户编号[{req.ClientNumber}]标的代码[{req.UnderlyingCode}]到期日不能为空"); } if (req.SettlementDate != null && req.SettlementDate < req.ExerciseDate) { throw new Exception($"客户编号[{req.ClientNumber}]标的代码[{req.UnderlyingCode}]的结算日期不应该小于到期日"); } if (string.IsNullOrEmpty(req.Number) && PS.Config.Company == Configuration.CompanyEnum.中金) { req.Number = new BizLogicZJ().GenerateFlowNumber(req, DbContext); } var flow = new trade_swap_flow(); if (req.id > 0) { flow = DbContext.trade_swap_flow.Find(req.id); flow.ClientNumber = req.ClientNumber; flow.UnderlyingCode = req.UnderlyingCode; flow.TradeNumber = req.TradeNumber; flow.Number = req.Number; flow.AssetUnitName = req.AssetUnitName; flow.ClientShortName = req.ClientShortName; flow.SpotPrice = req.SpotPrice; flow.Lots = req.Lots; flow.BuySell = req.BuySell; flow.TradeDate = req.TradeDate; flow.StartDate = req.StartDate; flow.ExerciseDate = req.ExerciseDate; flow.SettlementDate = req.SettlementDate; flow.SingleFee = req.SingleFee; flow.UnAnnualRate = req.UnAnnualRate; flow.IsTradePriceWhenOpen = req.IsTradePriceWhenOpen; flow.NeedCostFee = req.NeedCostFee; flow.IsNight = req.IsNight; flow.Comments = req.Comments; flow.ClearingAgency = req.ClearingAgency; flow.Status = "已修改"; } else { flow = req; SetDBModelCreator(flow); DbContext.trade_swap_flow.Add(flow); } flow.OptId = UserId; flow.OptName = UserName; flow.OptDate = DateTime.Now; DbContext.SaveChanges(); return flow; } private trade_swap_flow UpdateTradeFlow(trade_swap_flow req) { using var trans = BeginTransaction(); var tradeSwapFlow = DbContext.trade_swap_flow.Find(req.id); var originalClientNumber = tradeSwapFlow.ClientNumber; var originalUnderlyingCode = tradeSwapFlow.UnderlyingCode; var originalTradeDate = tradeSwapFlow.TradeDate; var tradeDate = req.TradeDate < tradeSwapFlow.TradeDate ? req.TradeDate : tradeSwapFlow.TradeDate; var isDiff = tradeSwapFlow.ClientNumber != req.ClientNumber || tradeSwapFlow.UnderlyingCode != req.UnderlyingCode; //相同客户相同标的不同交易日,需要选取小的来进行回退 if (req.TradeDate != tradeSwapFlow.TradeDate || req.ClientNumber != tradeSwapFlow.ClientNumber || req.UnderlyingCode != tradeSwapFlow.UnderlyingCode || req.BuySell != tradeSwapFlow.BuySell) { req.Number = new BizLogicZJ().GenerateFlowNumber(req, DbContext); } if (!isDiff) { tradeSwapFlow.TradeDate = tradeDate; } new SwapTradeFlowImportService(this).BackSwapTradeByTradeFlow(tradeSwapFlow); if (isDiff) { var client = ClientModule.ClientDataQueryService.GetClientByNumber(req.ClientNumber); if (client == null) { throw new ServiceException($"该客户编号[{req.ClientNumber}]在系统中不存在"); } tradeSwapFlow.ClientNumber = req.ClientNumber; tradeSwapFlow.UnderlyingCode = req.UnderlyingCode; var flow = DbContext.trade_swap_flow.Where(x => x.ClientNumber == req.ClientNumber && x.UnderlyingCode == req.UnderlyingCode && ((x.id > tradeSwapFlow.id && x.TradeDate == req.TradeDate) || x.TradeDate > req.TradeDate)).OrderBy(x => x.TradeDate).ThenBy(x => x.id).FirstOrDefault(); if (flow != null) { new SwapTradeFlowImportService(this).BackSwapTradeByTradeFlow(flow); } } tradeSwapFlow.Number = req.Number; tradeSwapFlow.AssetUnitName = req.AssetUnitName; tradeSwapFlow.ClientShortName = req.ClientShortName; tradeSwapFlow.SpotPrice = req.SpotPrice; tradeSwapFlow.Lots = req.Lots; tradeSwapFlow.BuySell = req.BuySell; tradeSwapFlow.TradeDate = req.TradeDate; tradeSwapFlow.StartDate = req.StartDate; tradeSwapFlow.ExerciseDate = req.ExerciseDate; tradeSwapFlow.SettlementDate = req.SettlementDate; tradeSwapFlow.SingleFee = req.SingleFee; tradeSwapFlow.UnAnnualRate = req.UnAnnualRate; tradeSwapFlow.IsTradePriceWhenOpen = req.IsTradePriceWhenOpen; tradeSwapFlow.NeedCostFee = req.NeedCostFee; tradeSwapFlow.IsNight = req.IsNight; tradeSwapFlow.Comments = req.Comments; tradeSwapFlow.ClearingAgency = req.ClearingAgency; tradeSwapFlow.OptId = UserId; tradeSwapFlow.OptName = UserName; tradeSwapFlow.OptDate = DateTime.Now; if (tradeSwapFlow.ExerciseDate == null) { //标的代码(必需) var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(req.UnderlyingCode); if (underlying == null) { throw new ServiceException($"该标的代码[{req.UnderlyingCode}]在系统中不存在"); } else { tradeSwapFlow.ExerciseDate = underlying.MaturityDate; } } if (tradeSwapFlow.ExerciseDate == null) { throw new ServiceException($"客户编号[{tradeSwapFlow.ClientNumber}]标的代码[{tradeSwapFlow.UnderlyingCode}]到期日不能为空"); } if (tradeSwapFlow.SettlementDate != null && tradeSwapFlow.SettlementDate < tradeSwapFlow.ExerciseDate) { throw new ServiceException($"客户编号[{tradeSwapFlow.ClientNumber}]标的代码[{tradeSwapFlow.UnderlyingCode}]的结算日期不应该小于到期日"); } DbContext.SaveChanges(); //同一客户同一标的(可能不同交易日)的场景 var tradeSwapFlows = DbContext.trade_swap_flow.Where(x => x.UnderlyingCode == tradeSwapFlow.UnderlyingCode && x.ClientNumber == tradeSwapFlow.ClientNumber && ((x.id >= tradeSwapFlow.id && x.TradeDate == tradeDate) || x.TradeDate > tradeDate)).OrderBy(x => x.TradeDate).ThenBy(x => x.id).ToList(); //不同客户或者不同标的的场景 if (isDiff) { //新客户或者标的 tradeSwapFlows = DbContext.trade_swap_flow.Where(x => x.UnderlyingCode == tradeSwapFlow.UnderlyingCode && x.ClientNumber == tradeSwapFlow.ClientNumber && ((x.id >= tradeSwapFlow.id && x.TradeDate == tradeSwapFlow.TradeDate) || x.TradeDate > tradeSwapFlow.TradeDate)).OrderBy(x => x.TradeDate).ThenBy(x => x.id).ToList(); //原始客户标的 tradeSwapFlows.AddRange(DbContext.trade_swap_flow.Where(x => x.UnderlyingCode == originalUnderlyingCode && x.ClientNumber == originalClientNumber && ((x.id >= tradeSwapFlow.id && x.TradeDate == originalTradeDate) || x.TradeDate > originalTradeDate)).OrderBy(x => x.TradeDate).ThenBy(x => x.id).ToList()); } tradeSwapFlows.ForEach(x => { new SwapTradeFlowImportService(this).HandleSwapTrade(x); x.Status = "已完成"; }); DbContext.SaveChanges(); trans.Commit(); return tradeSwapFlow; } private trade_swap_flow AddTradeFlow(trade_swap_flow req) { using var trans = BeginTransaction(); var flow = DbContext.trade_swap_flow.Where(x => x.ClientNumber == req.ClientNumber && x.UnderlyingCode == req.UnderlyingCode && x.TradeDate > req.TradeDate).OrderBy(x => x.TradeDate).ThenBy(x => x.id).FirstOrDefault(); if (flow != null) { new SwapTradeFlowImportService(this).BackSwapTradeByTradeFlow(flow); } req.Number = new BizLogicZJ().GenerateFlowNumber(req, DbContext); DbContext.trade_swap_flow.Add(req); req.OptId = UserId; req.OptName = UserName; req.OptDate = DateTime.Now; req.CreatorId = UserId; req.CreatorName = UserName; req.CreateDate = DateTime.Now; if (req.ExerciseDate == null) { //标的代码(必需) var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(req.UnderlyingCode); if (underlying == null) { throw new ServiceException($"该标的代码[{req.UnderlyingCode}]在系统中不存在"); } else { req.ExerciseDate = underlying.MaturityDate; } } var variety = DataCacheProvider.GetVariety(req.UnderlyingCode); if (variety == null) { throw new Exception($"该标的[{req.UnderlyingCode}]对应的品种在系统中不存在"); } else { if (string.IsNullOrWhiteSpace(variety.QuoteCurrency) && DbContext.currency.Any()) { throw new Exception($"标的代码[{req.UnderlyingCode}]对应的品种币种不能为空"); } else { req.QuoteCurrency = variety.QuoteCurrency; } } if (req.ExerciseDate == null) { throw new Exception($"客户编号[{req.ClientNumber}]标的代码[{req.UnderlyingCode}]到期日不能为空"); } if (req.SettlementDate != null && req.SettlementDate < req.ExerciseDate) { throw new Exception($"客户编号[{req.ClientNumber}]标的代码[{req.UnderlyingCode}]的结算日期不应该小于到期日"); } DbContext.SaveChanges(); var tradeSwapFlows = DbContext.trade_swap_flow.Where(x => x.UnderlyingCode == req.UnderlyingCode && x.ClientNumber == req.ClientNumber && ((x.id >= req.id && x.TradeDate == req.TradeDate) || x.TradeDate > req.TradeDate)).OrderBy(x => x.TradeDate).ThenBy(x => x.id).ToList(); tradeSwapFlows.ForEach(x => { new SwapTradeFlowImportService(this).HandleSwapTrade(x); x.Status = "已完成"; }); DbContext.SaveChanges(); trans.Commit(); return req; } public client_variety_config SaveClientVarietyConfig(client_variety_config req) { if (req is null) { throw new ArgumentNullException(nameof(req)); } if (DbContext.client_variety_config.Any(x => x.id != req.id && x.ClientId == req.ClientId && x.VarietyId == req.VarietyId && x.ValueDate == req.ValueDate)) { throw new Exception("同一客户同一品种不支持在同一天有多条配置记录"); } if (req.SingleFee > 0 && req.UnAnnualRate > 0) { throw new Exception($"按手数收费和按名义本金收费不能同时设置"); } var clientVarietyConfig = DbContext.client_variety_config.Find(req.id); if (clientVarietyConfig == null) { clientVarietyConfig = new client_variety_config(); DbContext.client_variety_config.Add(clientVarietyConfig); } UpdateChanges(clientVarietyConfig, req); var types = new List(); if (clientVarietyConfig.SingleFee != 0) { types.Add(1); } if (clientVarietyConfig.AnnualRate != 0) { types.Add(2); } if (clientVarietyConfig.UnAnnualRate != 0) { types.Add(3); } clientVarietyConfig.FeeType = string.Join(",", types); clientVarietyConfig.OptDate = DateTime.Now; clientVarietyConfig.OptId = UserId; clientVarietyConfig.OptName = UserName; DbContext.SaveChanges(); return clientVarietyConfig; } #region 交易流水 -- 国君 /// /// trade_swap_flow_more /// public SearchListResult SearchFlowMoreList(TradeFlowMoreReq req) { var query = from source in DbContext.trade_swap_flow_more.Where(x => !x.IsDelete) select source; if (!string.IsNullOrEmpty(req.ClientNumber)) { query = query.Where(d => d.ClientNumber.Contains(req.ClientNumber)); } if (!string.IsNullOrEmpty(req.TradeNumber)) { query = query.Where(d => d.TradeNumber.Contains(req.TradeNumber)); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { query = query.Where(d => d.UnderlyingCode.Contains(req.UnderlyingCode)); } if (!string.IsNullOrEmpty(req.BuySell)) { query = query.Where(d => d.BuySell == req.BuySell); } if (req.TradeDateStart != DateTime.MinValue) { query = query.Where(d => d.TradeDate >= req.TradeDateStart); } if (req.TradeDateEnd != DateTime.MinValue) { var TradeDateTemp = req.TradeDateEnd.AddDays(1); query = query.Where(d => d.TradeDate < TradeDateTemp); } if (req.ExerciseDateStart != DateTime.MinValue) { query = query.Where(d => d.ExerciseDate >= req.ExerciseDateStart); } if (req.ExerciseDateEnd != DateTime.MinValue) { var ExerciseDateTemp = req.ExerciseDateEnd.AddDays(1); query = query.Where(d => d.ExerciseDate < ExerciseDateTemp); } if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "TradeDate,id"; req.sord = "asc"; } var retListResult = query.ToSearchList(req); foreach (var item in retListResult.rows) { item.ClientName = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(x => x.Number == item.ClientNumber)?.Name; item.UnderlyingName = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode)?.UnderlyingName; } return retListResult; } public trade_swap_flow_more SaveTradeFlowMore(trade_swap_flow_more req) { if (req is null) { throw new ArgumentNullException(nameof(req)); } using var trans = BeginTransaction(); var client = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(n => req.ClientNumber.Equals(n.Number, StringComparison.OrdinalIgnoreCase)); if (client == null) { throw new ServiceException($"该客户编号[{req.ClientNumber}]在系统中不存在"); } var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(req.UnderlyingCode); if (underlying == null) { throw new ServiceException($"该标的代码[{req.UnderlyingCode}]在系统中不存在"); } var swapFlow = DbContext.trade_swap_flow_more.Find(req.id); if (req.BuySell == "开仓") { if (DbContext.trade.Where(x => x.TradeNumber == req.TradeNumber && x.ValidState != "InValid" && x.id != swapFlow.id).Any()) { throw new ServiceException($"该交易已存在,编号[{req.TradeNumber}]"); } if (DbContext.trade_swap_flow_more.Where(x => x.TradeNumber == req.TradeNumber && x.BuySell == "开仓" && !x.IsDelete && x.id != swapFlow.id).Any()) { throw new ServiceException($"开仓流水已存在该交易编号,编号[{req.TradeNumber}]"); } } var traders = UserBLL.GetUsersByPosition().FirstOrDefault(x => x.Id == req.TraderId); swapFlow.TraderId = traders.Id; swapFlow.TraderName = traders.Name; var assetUnit = DataCacheProvider.GetAssetUnitDataSource().AsQueryable().FirstOrDefault(x => x.Name == req.AssetBookName); if (!("," + assetUnit.TraderIds + ",").Contains("," + swapFlow.TraderId + ",")) { throw new ServiceException($"该交易员[{swapFlow.TraderName}]不在簿记账户[{req.AssetBookName}]中"); } swapFlow.AssetId = assetUnit.id; swapFlow.AssetBookName = assetUnit.Name; swapFlow.ClientNumber = req.ClientNumber; swapFlow.ClientId = client.id; swapFlow.UnderlyingCode = req.UnderlyingCode; var longShort = req.Notional > 0 ? "多头" : "空头"; swapFlow.LongShort = longShort; swapFlow.Notional = req.Notional; swapFlow.BuySell = req.BuySell; ; swapFlow.TradeNumber = req.TradeNumber; swapFlow.TradeDate = req.TradeDate; swapFlow.ExerciseDate = req.ExerciseDate; swapFlow.Price = req.Price; swapFlow.CurrencyRate = req.CurrencyRate; swapFlow.AnnualRate = req.AnnualRate; swapFlow.TotalFee = req.TotalFee; swapFlow.MargeRate = req.MargeRate; if (swapFlow.BuySell == "平仓") { swapFlow.UnwindDate = req.UnwindDate; swapFlow.UnwindPrice = req.UnwindPrice; swapFlow.UnwindNotional = req.UnwindNotional; swapFlow.Amount = req.Amount; } swapFlow.OptId = UserId; swapFlow.OptName = UserName; swapFlow.OptDate = DateTime.Now; DbContext.SaveChanges(); trans.Commit(); return swapFlow; } public SearchListResult SearchFlowMoreHistory(TradeReq req) { var query = SearchFlowMoreQuery(req); var retListResult = query.ToSearchList(req); foreach (var item in retListResult.rows) { item.ClientName = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(x => x.Number == item.ClientNumber)?.Name; item.UnderlyingName = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode)?.UnderlyingName; item.LongShort = item.LongShort == "多头" ? "空头" : "多头"; item.Notional = -item.Notional; item.TotalFee = -item.TotalFee; item.FixedIncome = -item.FixedIncome; item.UnwindNotional = -item.UnwindNotional; item.AnnualRate = -item.AnnualRate; item.NotionalString = int.TryParse(item.NotionalString, out var n) ? n.ToString() : "0"; item.UnwindNotional = int.TryParse((item.UnwindNotional ?? 0).ToString(), out var un) ? un : 0; item.Amount = -item.Amount ?? 0; item.QuoteAmount = (item.CurrencyRate ?? 0) * (item.Amount ?? 0); } var gsum = new trade_contract_groupGridSum(); if (query.Any()) { gsum.WinLossSum = retListResult.rows.Where(x => x.BuySell != "开仓").Sum(x => x.Amount.OtcFormatValue(OtcFormatFlag.tradePrice)); gsum.QuoteWinLossSum = retListResult.rows.Where(x => x.BuySell != "开仓").Sum(x => x.QuoteAmount.OtcFormatValue(OtcFormatFlag.tradePrice)); } retListResult.Sum = gsum; return retListResult; } public List SearchFlowMoreHistoryList(TradeReq req) { var query = SearchFlowMoreQuery(req); var list = query.ToList(); foreach (var item in list) { item.ClientName = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(x => x.Number == item.ClientNumber)?.Name; item.LongShort = item.LongShort == "多头" ? "空头" : "多头"; item.Notional = -item.Notional; item.TotalFee = -item.TotalFee; item.FixedIncome = -item.FixedIncome; item.UnwindNotional = -item.UnwindNotional; item.AnnualRate = -item.AnnualRate; item.NotionalString = int.TryParse(item.NotionalString, out var n) ? n.ToString() : "0"; item.UnwindNotional = int.TryParse((item.UnwindNotional ?? 0).ToString(), out var un) ? un : 0; item.Amount = -item.Amount ?? 0; item.QuoteAmount = (item.CurrencyRate ?? 0) * (item.Amount ?? 0); } return list; } private IQueryable SearchFlowMoreQuery(TradeReq req) { var query = from source in DbContext.trade_swap_flow_more.Where(x => !x.IsDelete && x.IsCompose) select source; if (req.ClientId != null && req.ParentFlag) { var lists = ClientBalanceUtility.GetSubclientId(req.ClientId.Value); query = query.Where(d => lists.Contains(d.ClientId)); } else if (req.ClientId != null && !req.ParentFlag) { query = query.Where(x => x.ClientId == req.ClientId); } if (req.ValueDateStart.Year > 2000) { query = query.Where(x => (x.BuySell == "开仓" && x.TradeDate >= req.ValueDateStart) || (x.BuySell == "平仓" && x.UnwindDate >= req.ValueDateStart)); } if (req.ValueDateEnd.Year > 2000) { var TradeDateTemp = req.ValueDateEnd.AddDays(1); query = query.Where(x => (x.BuySell == "开仓" && x.TradeDate < TradeDateTemp) || (x.BuySell == "平仓" && x.UnwindDate < TradeDateTemp)); } if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "TradeDate,id"; req.sord = "asc"; } return query; } public int SearchFlowMoreCount(int clientId, DateTime ValueDateStart, DateTime ValueDateEnd) { var query = from source in DbContext.trade_swap_flow_more select source; if (clientId > 0) { query = query.Where(x => x.ClientId == clientId); } if (ValueDateStart.Year > 2000) { query = query.Where(x => (x.BuySell == "开仓" && x.TradeDate >= ValueDateStart) || (x.BuySell == "平仓" && x.UnwindDate >= ValueDateStart)); } if (ValueDateEnd.Year > 2000) { var TradeDateTemp = ValueDateEnd.AddDays(1); query = query.Where(x => (x.BuySell == "开仓" && x.TradeDate < TradeDateTemp) || (x.BuySell == "平仓" && x.UnwindDate < TradeDateTemp)); } var result = query.Count(); return result; } public void FlowMoreComposeTrade() { var service = new SwapTradeFlowMoreImportService(UserInfo); var tradeNumbers = DbContext.trade_swap_flow_more.Where(x => !x.IsCompose && !x.IsDelete).Select(x => x.TradeNumber).Distinct().ToList(); tradeNumbers.ForEach(x => { service.HandleSwapTrade(x); }); } #endregion } }