using BaseOUDAL; using MoreLinq; using NPOI.SS.Formula.Functions; using OfficeOpenXml; using Org.BouncyCastle.Ocsp; using YieldChain.Security; using YLErp.BLL.Eod; using YLErp.DBModels; using YLErp.Helpers; using YLErp.Model; using YLErp.Model.Enum; using YLErp.Modules.SwapModule.Dto; using YLErp.Office; using YLErp.QdpModule; namespace YLErp.Modules.SwapModule { /// /// 互换流水导入 /// public class SwapFlowService : SwapTradeBaseService { public SwapFlowService(OptUserInfo optUser) : base(optUser) { } public SwapFlowService(YLBaseService baseService) : base(baseService) { } /// /// 查询今天是否有FR007的数据 /// /// public eod_commodity_future_price SearchTodayFRData(DateTime dateTime) { var data = DbContext.eod_commodity_future_price.Where(a => a.ValueDate == dateTime && a.UnderlyingCode == "FR007").FirstOrDefault(); if (data == null) { data = new eod_commodity_future_price(); } return data; } /// /// 查询选择的时间是否拥有FR007的数据 /// /// public List SearchdateFRData(List date) { var datafr007 = DbContext.eod_commodity_future_price.Where(a => date.Contains(a.ValueDate)).ToList(); return datafr007; } /// /// 删除的RF007数据 /// /// 要删除的RF007数据Id /// public bool DeleteFRData(int id) { var frdata = DbContext.eod_commodity_future_price.Find(id); if (frdata == null) { throw new ServiceException("未找到FR007流水"); } DbContext.eod_commodity_future_price.Remove(frdata); DbContext.SaveChanges(); return true; } /// /// 新增或者修改FR007数据 /// /// FR007价格 /// 新增或者修改时间 /// public bool AddOrUpdateFRdata(Double price, DateTime dateTime) { string beforedate = ""; var frdata = DbContext.eod_commodity_future_price.Where(a => a.ValueDate == dateTime && a.UnderlyingCode == "FR007").FirstOrDefault(); if (frdata == null) { frdata = new eod_commodity_future_price(); } //修改 if (frdata != null && frdata?.UnderlyingCode != null) { frdata.ValueDate = dateTime; frdata.HighPrice = 0; frdata.LowPrice = 0; beforedate = JsonHelper.Serialize(frdata); } else { //新增 var newestdata = DbContext.eod_commodity_future_price.OrderByDescending(a => a.ValueDate).FirstOrDefault(); if (newestdata == null) { var underlyingCode = DbContext.underlying_manager.Where(a => a.UnderlyingCode == "FR007").FirstOrDefault(); if (underlyingCode == null) { throw new ServiceException("找不到FR007的标的"); } newestdata = new eod_commodity_future_price(); newestdata.UnderlyingId = underlyingCode.id; } frdata.ValueDate = dateTime; frdata.UnderlyingCode = "FR007"; frdata.UnderlyingId = newestdata.UnderlyingId; frdata.DataSource = EodPriceBase.人工; DbContext.Add(frdata); } frdata.ClosePrice = Math.Round(price, 4); frdata.SettlePrice = Math.Round(price, 4); frdata.ReferencePrice = Math.Round(price, 4); frdata.OptId = UserInfo.UserId; frdata.OptName = UserInfo.UserName; frdata.OptDate = DateTime.Now; DbContext.SaveChanges(); return true; } /// /// 查询互换流水导入 /// public SearchListResult SearchList(SwapFlowQueryRequest req) { var predicate = PredicateBuilder.Create(n => n.DataState == (int)SwapFlowDateStateEnum.等待完成); if (req.TradeDateStart.HasValue) { predicate = predicate.And(n => n.OccurTime >= req.TradeDateStart.Value); } if (req.TradeDateEnd.HasValue) { predicate = predicate.And(n => n.OccurTime <= req.TradeDateEnd.Value); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { predicate = predicate.And(n => n.UnderlyingCode==req.UnderlyingCode); } if (req.TradeDate.HasValue) { predicate = predicate.And(n => n.OccurTime == req.TradeDate); } if (req.ClientId.HasValue) { predicate = predicate.And(n => n.ClientId == req.ClientId); } var flowquery = DbContext.swap_flow.Where(predicate); if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "id"; req.sord = "desc"; } var retListResult = flowquery.AsNoTracking().ToSearchList(req); var trsIds= retListResult.rows.Where(x=>x.trs_deal_id>0).Select(r => r.trs_deal_id).ToList(); var underlyingCodes= retListResult.rows.Select(r => r.UnderlyingCode).ToList(); var riskChecks = DbContext.trade_risk_check_log.Where(x=> trsIds.Contains(x.flow_id)).ToList(); var underlyings=DbContext.underlying_manager.Where(x=>underlyingCodes.Contains(x.UnderlyingCode)).AsNoTracking().ToList(); foreach (var item in retListResult.rows) { var riskCheck = riskChecks.FirstOrDefault(x=>x.flow_id==item.trs_deal_id); item.limit_alert_remark = riskCheck?.remark; var um = underlyings.FirstOrDefault(x=>x.UnderlyingCode==item.UnderlyingCode); if (um!=null&&um.IsBond()) { // 入库小数(0.995)→展示报价(99.5),价格字段统一走 BondPriceConverter item.TradingAmountAvg = BondPriceConverter.ToDisplay(item.TradingAmountAvg); item.TradingAmountFeeAvg = BondPriceConverter.ToDisplay(item.TradingAmountFeeAvg); item.TradingAmountNet = item.TradingAmountNet.HasValue ? BondPriceConverter.ToDisplay(item.TradingAmountNet.Value) : item.TradingAmountNet; item.TradingAmountNetFee = item.TradingAmountNetFee.HasValue ? BondPriceConverter.ToDisplay(item.TradingAmountNetFee.Value) : item.TradingAmountNetFee; // 数量÷100(手→万手展示),与价格维度无关,保留常量 item.TradingQty /= ConsGlobal.bondShowPriceMultiple; } } return retListResult; } /// /// 查询互换流水汇总 /// public SearchListResult SearchMergeList(SwapFlowQueryRequest req) { var predicate = PredicateBuilder.Create(n => n.DataState == (int)SwapFlowDateStateEnum.等待完成 && n.OccurTime == req.TradeDate); var capitalQuery = DbContext.swap_fund_account.Where(x => x.Status == (int)SwapFoundAccountStatusEnum.正常); if (!string.IsNullOrEmpty(req.TradeNumber)) { capitalQuery = capitalQuery.Where(n => n.SwapTradeNo.Contains(req.TradeNumber.Trim())); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { predicate = predicate.And(n => n.UnderlyingCode==req.UnderlyingCode); } if (req.ClientId.HasValue) { predicate = predicate.And(n => n.ClientId == req.ClientId); } var flowquery = DbContext.swap_flow_merge.Where(predicate); var query = from flow in flowquery join capital in capitalQuery on flow.FundAccount equals capital.FundAccount select new SwapFlowQueryResponse { id = flow.id, FundAccount = flow.FundAccount, OccurTime = flow.OccurTime, SwapTradeId = capital.SwapTradeId, SwapTradeNo = capital.SwapTradeNo, BsType = flow.BsType, UnderlyingCode = flow.UnderlyingCode, TradingQty = flow.TradingQty, TradingAmount = flow.TradingAmount, TradingFee = flow.TradingFee, TradingAmountAvg = flow.TradingAmountAvg, TradingAmountFeeAvg = flow.TradingAmountFeeAvg, TradingAmountNet=flow.TradingAmountNetFeeAvg??0, ContractSize = flow.ContractSize }; if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "OccurTime,FundAccount,UnderlyingCode,BsType"; req.sord = "asc"; } var retListResult = query.ToSearchList(req); var underlyingCodes = retListResult.rows.Select(r => r.UnderlyingCode).ToList(); var underlyings = DbContext.underlying_manager.Where(x => underlyingCodes.Contains(x.UnderlyingCode)).AsNoTracking().ToList(); foreach (var item in retListResult.rows) { var um = underlyings.FirstOrDefault(x => x.UnderlyingCode == item.UnderlyingCode); if (um != null && um.IsBond()) { item.TradingAmountAvg = BondPriceConverter.ToDisplay(item.TradingAmountAvg); item.TradingAmountFeeAvg = BondPriceConverter.ToDisplay(item.TradingAmountFeeAvg); item.TradingAmountNet = BondPriceConverter.ToDisplay(item.TradingAmountNet); item.TradingQty /= ConsGlobal.bondShowPriceMultiple; } } return retListResult; } /// /// 查询互换开平仓事件 /// /// /// public SearchListResult SearchEventList(SwapFlowQueryRequest req) { var predicate = PredicateBuilder.Create(n =>n.PositionType>0&&n.DataState>0); List eventTypes = new List() { (int)SwapEventTypeEnum.确认交易, (int)SwapEventTypeEnum.平仓 }; if (req.TradeDate.HasValue) { predicate = predicate.And(n=>n.EventDate==req.TradeDate); } if (req.TradeDateEnd.HasValue) { predicate = predicate.And(n => n.EventDate <= req.TradeDateEnd); } if (req.TradeDateStart.HasValue) { predicate = predicate.And(n => n.EventDate >= req.TradeDateStart); } if (!string.IsNullOrEmpty(req.TradeNumber)) { predicate = predicate.And(n => n.SwapTradeNo.Contains(req.TradeNumber.Trim())); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { predicate = predicate.And(n => n.UnderlyingCode.Contains(req.UnderlyingCode.Trim())); } if (req.ClientId.HasValue) { predicate = predicate.And(n => n.ClientId==req.ClientId); } var eventQuery =from se in DbContext.swap_flow_event.Where(predicate) join t in DbContext.trade.Where(x=>x.ValidState==ConsGlobal.Valid) on se.SwapTradeId equals t.id join s in DbContext.swap_event.Where(x => !x.Invalid && eventTypes.Contains(x.EventType)) on se.EventId equals s.id into stemp from s in stemp.DefaultIfEmpty() select se; if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "PositionId,id"; req.sord = "asc"; } var retListResult = eventQuery.ToSearchList(req); List extendList = null; Dictionary ytmMap = new Dictionary(); if (retListResult != null && retListResult.rows != null && retListResult.rows.Any()) { var tradeIds = retListResult.rows.Where(p => p.PayDate == null || p.EventType != (int)SwapEventTypeEnum.平仓).Select(p => p.SwapTradeId).Distinct().ToList(); if (tradeIds != null && tradeIds.Count > 0) { extendList = DbContext.trade_extend.AsNoTracking().Where(p => tradeIds.Contains(p.TradeId)).ToList(); // 查询成交收益率 ytmMap = DbContext.trade.AsNoTracking().Where(p => tradeIds.Contains(p.id)).ToList().ToDictionary(t => t.id, t => t.InitYtm); } } if (extendList == null) { extendList = new List(); } foreach (var item in retListResult.rows) { item.InitYtm = ytmMap.GetValueOrDefault(item.SwapTradeId); if (ConsGlobal.InstrumentType.IsBond(item.UnderlyingInstrumentType)) { item.TradingAmountAvg = BondPriceConverter.ToDisplay(item.TradingAmountAvg); item.TradingAmountFeeAvg = BondPriceConverter.ToDisplay(item.TradingAmountFeeAvg); item.TradingAmountNetFeeAvg = item.TradingAmountNetFeeAvg.HasValue ? BondPriceConverter.ToDisplay(item.TradingAmountNetFeeAvg.Value) : item.TradingAmountNetFeeAvg; item.TradingAmountNetAvg = item.TradingAmountNetAvg.HasValue ? BondPriceConverter.ToDisplay(item.TradingAmountNetAvg.Value) : item.TradingAmountNetAvg; item.Quantity /= ConsGlobal.bondShowPriceMultiple; } if (item.PayDate == null || item.EventType != (int)SwapEventTypeEnum.平仓) { var extend = extendList.FirstOrDefault(p => p.TradeId == item.SwapTradeId); if (extend != null&& item.PayDate == null) { item.PayDate = item.UnwindDate.Value.AddDays(extend.ExtendObj.SettlementRules); } } } return retListResult; } /// /// 重置流水 /// /// /// public void ResetFlows(int clientId,DateTime valueDate) { var flows= DbContext.swap_flow.Where(x=>x.ClientId==clientId&&x.OccurTime>=valueDate&&x.DataState==(int)SwapFlowDateStateEnum.完成); var flowMerge= DbContext.swap_flow_merge.Where(x => x.ClientId == clientId && x.OccurTime >= valueDate && x.DataState == (int)SwapFlowDateStateEnum.完成); flows.ForEach(x => { x.SwapTradeId = null; x.SwapTradeNo = null; x.DataState = (int)SwapFlowDateStateEnum.等待完成; }); DbContext.swap_flow_merge.RemoveRange(flowMerge); DbContext.SaveChanges(); Task.Run(() => { RealtimePnlCalc.RealtimeSwapPosition(new OptUserInfo(0, "互换实时持仓服务", OptUserFrom.Service)); }); } /// /// 开平仓事件导出 /// /// /// /// public byte[] exprotSwapFlowEventExcel(SwapFlowQueryRequest req) { //获取数据 var ret = SearchEventList(req); List list = new List(); foreach (var item in ret.rows) { SwapFlowEventExportModel exportModel = new SwapFlowEventExportModel(); exportModel.EventDate = item.EventDate.OtcFormatDate(); exportModel.UnwindDate = item.UnwindDate.OtcFormatDate(); exportModel.PayDate = item.PayDate.OtcFormatDate(); exportModel.SwapTradeNo = item.SwapTradeNo; exportModel.SwapPositionIdPadding = item.SwapPositionIdPadding; exportModel.EventType = ((SwapFlowEventTypeEnum)item.EventType).ToString(); exportModel.EventReason = item.EventReason; exportModel.PayDirection = ((SwapDirectionEnum)item.PayDirection).ToString(); exportModel.PositionType = item.PositionType==1?"多头":"空头"; exportModel.UnderlyingCode = item.UnderlyingCode; exportModel.MatuirityDate = item.MatuirityDate.OtcFormatDate(); exportModel.TradingAmountAvg = item.TradingAmountAvg.OtcFormat(OtcFormatFlag.umprice); exportModel.TradingAmountFeeAvg = item.TradingAmountFeeAvg.OtcFormat(OtcFormatFlag.umprice); exportModel.Quantity = item.Quantity.OtcFormatMoney(false, 4); exportModel.TradingAmount = item.TradingAmount.OtcFormatMoney(false, 4); exportModel.ContractSize = item.ContractSize.ToString(); exportModel.TradingFee = item.TradingFee.OtcFormatMoney(false, 4); exportModel.TradingFeePending = item.TradingFeePending.OtcFormatMoney(false, 4); exportModel.DividendPending = item.DividendPending.OtcFormatMoney(false, 4); exportModel.MarkClosePnl = item.MarkClosePnl.OtcFormatMoney(false, 4); exportModel.DividendIn = item.DividendIn.OtcFormatMoney(false, 4); exportModel.OptLog = item.OptLog; exportModel.InitYtm = item.InitYtm; list.Add(exportModel); } var tplFilePath = OtcAppContext.MapPath("/App_Docs"); var sourceFileName = Path.Combine(tplFilePath, "导出模板", "互换开平仓事件流水导出模板.xlsx"); var modelDict = new Dictionary(); var model = new { list = list }; modelDict.Add("Sheet1", model); ExcelPackage.LicenseContext = LicenseContext.NonCommercial; return new ExcelTemplateGenerator().SetTemplateFile(sourceFileName).SetTemplateData(modelDict).Output(); } /// /// 查询互换合成持仓 /// /// /// public SearchListResult SearchComposeList(SwapFlowQueryRequest req) { var predicate = PredicateBuilder.Create(n => n.PosiQuantity>0 && n.PosiStartDate == req.TradeDate && !n.Invalid&&!n.IsInitial); List eventDatas = new List() { "系统操作-自动合成持仓", "流水自动簿记确认交易" }; var eventDate =QdpCalendarHelper.GetNonHolidayDefore(req.TradeDate.Value.AddDays(-1)); var swapEventPredicate = PredicateBuilder.Create(n => eventDatas.Contains(n.EventReason)&&!n.Invalid&&n.ValueDate== eventDate); var tradePredicate = PredicateBuilder.Create(n => n.TradeType=="收益互换"&&n.ValidState!=ConsGlobal.InValid); if (!string.IsNullOrEmpty(req.TradeNumber)) { tradePredicate = tradePredicate.And(n => n.TradeNumber.Contains(req.TradeNumber.Trim())); } if (req.ClientId.HasValue) { tradePredicate = tradePredicate.And(n => n.ClientId==req.ClientId); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { predicate = predicate.And(n => n.UnderlyingCode.Contains(req.UnderlyingCode.Trim())); } var positionQuery = DbContext.swap_position.Where(predicate); var swapTradeIds = DbContext.swap_event.Where(swapEventPredicate).Select(s => s.SwapTradeId).Distinct(); tradePredicate = tradePredicate.And(x=> swapTradeIds.Contains(x.id)); var tradeQuery = DbContext.trade.Where(tradePredicate); var query = from position in positionQuery join td in tradeQuery on position.SwapTradeId equals td.id select new SwapPositionResponse { position = position, TradeDate = td.StartDate.Value, SwapTradeNo = td.TradeNumber, StructureType = td.StructureType, ClientName = td.ClientName }; if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "SwapTradeNo,position.UnderlyingCode"; req.sord = "asc"; } var retListResult = query.ToSearchList(req); foreach (var item in retListResult.rows) { if (ConsGlobal.InstrumentType.IsBond(item.position.UnderlyingInstrumentType)) { item.position.PosiNetPrice = BondPriceConverter.ToDisplay(item.position.PosiNetPrice); item.position.PosiGrossPrice = BondPriceConverter.ToDisplay(item.position.PosiGrossPrice); item.position.PosiNetNoFeePrice = item.position.PosiNetNoFeePrice.HasValue ? BondPriceConverter.ToDisplay(item.position.PosiNetNoFeePrice.Value) : item.position.PosiNetNoFeePrice; item.position.PosiNetFeePrice = item.position.PosiNetFeePrice.HasValue ? BondPriceConverter.ToDisplay(item.position.PosiNetFeePrice.Value) : item.position.PosiNetFeePrice; item.position.PosiQuantity /= ConsGlobal.bondShowPriceMultiple; } } return retListResult; } /// /// 保存流水 /// /// public void SaveSwapFlow(swap_flow req) { CheckValid(req); swap_flow swap_Flow = DbContext.swap_flow.Find(req.id); if (swap_Flow == null) { swap_Flow = new swap_flow(); } swap_Flow.OccurTime = req.OccurTime; swap_Flow.FundAccount = req.FundAccount; swap_Flow.TradingAmount = req.TradingAmount; swap_Flow.TradingFee = req.TradingFee; swap_Flow.TradingQty = req.TradingQty; swap_Flow.UnderlyingCode = req.UnderlyingCode; swap_Flow.BsType = req.BsType; swap_Flow.ContractSize = req.ContractSize; swap_Flow.TradingAmountAvg = req.TradingAmountAvg; swap_Flow.TradingAmountFeeAvg = TradeFeeHelper.CalcPriceWithFee(req.TradingFee,req.TradingAmountAvg,req.TradingQty,req.BsType); swap_Flow.ClientId = req.ClientId; swap_Flow.ytm = req.ytm; swap_Flow.TradingAmountNet = req.TradingAmountNet; swap_Flow.ClientName = req.ClientName; swap_Flow.UnderlyingName = req.UnderlyingName; swap_Flow.TradingAmountNetFee = TradeFeeHelper.CalcPriceWithFee(req.TradingFee, req.TradingAmountNet??0, req.TradingQty, req.BsType); swap_Flow.SettleDate=req.SettleDate; swap_Flow.DataState = (int)SwapFlowDateStateEnum.等待完成; UpdateDbOption(swap_Flow); if (req.id == 0) { DbContext.swap_flow.Add(swap_Flow); } Task.Run(() => { RealtimePnlCalc.RealtimeSwapPosition(new OptUserInfo(0, "互换实时持仓服务", OptUserFrom.Service)); }); DbContext.SaveChanges(); Dictionary> clientUmsDic = new Dictionary>(); clientUmsDic.Add(swap_Flow.ClientId ?? 0, new List { swap_Flow.UnderlyingCode }); new RiskCacheService().refreshRiskCache(clientUmsDic); } /// /// 回退删除手动簿记流水 /// /// /// public void DeleteSwapFlow(int tradeId,DateTime eventDate,bool skip) { var swapFlows = DbContext.swap_flow.Where(x => x.SwapTradeId == tradeId && x.OccurTime >= eventDate); if (skip) { swapFlows= swapFlows.Skip(1); } DbContext.swap_flow.RemoveRange(swapFlows); DbContext.SaveChanges(); Task.Run(() => { RealtimePnlCalc.RealtimeSwapPosition(new OptUserInfo(0, "互换实时持仓服务", OptUserFrom.Service)); }); } /// /// 保存流水 /// /// public void SaveSwapFlowMerge(swap_flow req) { CheckValid(req); swap_flow_merge swap_Flow = DbContext.swap_flow_merge.Find(req.id); if (swap_Flow == null) { swap_Flow = new swap_flow_merge(); ; } swap_Flow.OccurTime = req.OccurTime.Value; swap_Flow.ClientId = req.ClientId; swap_Flow.FundAccount = req.FundAccount; swap_Flow.TradingAmount = req.TradingAmount; swap_Flow.TradingFee = req.TradingFee; swap_Flow.TradingQty = req.TradingQty; swap_Flow.UnderlyingCode = req.UnderlyingCode; swap_Flow.BsType = req.BsType; swap_Flow.DataState = (int)SwapFlowDateStateEnum.等待完成; swap_Flow.ContractSize = req.ContractSize; swap_Flow.TradingAmountAvg = req.TradingAmountAvg; swap_Flow.TradingAmountFeeAvg = req.TradingAmountFeeAvg; UpdateDbOption(swap_Flow); if (req.id == 0) { DbContext.swap_flow_merge.Add(swap_Flow); } DbContext.SaveChanges(); } /// /// 删除流水 /// /// /// public void DeleteSwapFlow(long id) { var capitalAccount = DbContext.swap_flow.Find(id); if (capitalAccount == null) { throw new ServiceException("未找到该互换流水"); } DbContext.swap_flow.Remove(capitalAccount); DbContext.SaveChanges(); Task.Run(() => { RealtimePnlCalc.RealtimeSwapPosition(new OptUserInfo(0, "互换实时持仓服务", OptUserFrom.Service)); }); Dictionary> clientUmsDic = new Dictionary>(); clientUmsDic.Add(capitalAccount.ClientId ?? 0, new List { capitalAccount.UnderlyingCode }); new RiskCacheService().refreshRiskCache(clientUmsDic); } /// /// 删除流水 /// /// /// public void DeleteSwapFlowMerge(long id) { var swap_Flow = DbContext.swap_flow_merge.Find(id); if (swap_Flow == null) { throw new ServiceException("未找到该互换流水汇总"); } DbContext.swap_flow_merge.Remove(swap_Flow); DbContext.SaveChanges(); } /// /// 查看流水 /// /// /// public swap_flow GetSwapFlow(long id) { var swapFlow = DbContext.swap_flow.Find(id); if (swapFlow == null) { throw new ServiceException("未找到该互换流水"); } var um = DataCacheProvider.GetUnderlyingDataSource().GetData(swapFlow.UnderlyingCode); if (um != null && um.IsBond()) { swapFlow.TradingAmountAvg = BondPriceConverter.ToDisplay(swapFlow.TradingAmountAvg); swapFlow.TradingAmountFeeAvg = BondPriceConverter.ToDisplay(swapFlow.TradingAmountFeeAvg); swapFlow.TradingAmountNet = swapFlow.TradingAmountNet.HasValue ? BondPriceConverter.ToDisplay(swapFlow.TradingAmountNet.Value) : swapFlow.TradingAmountNet; swapFlow.TradingAmountNetFee = swapFlow.TradingAmountNetFee.HasValue ? BondPriceConverter.ToDisplay(swapFlow.TradingAmountNetFee.Value) : swapFlow.TradingAmountNetFee; swapFlow.TradingQty /= ConsGlobal.bondShowPriceMultiple; } return swapFlow; } public swap_flow_merge GetSwapFlowMerge(long id) { var swapFlow = DbContext.swap_flow_merge.Find(id); if (swapFlow == null) { throw new ServiceException("未找到该互换流水"); } var um = DataCacheProvider.GetUnderlyingDataSource().GetData(swapFlow.UnderlyingCode); if (um != null && um.IsBond()) { swapFlow.TradingAmountAvg = BondPriceConverter.ToDisplay(swapFlow.TradingAmountAvg); swapFlow.TradingAmountFeeAvg = BondPriceConverter.ToDisplay(swapFlow.TradingAmountFeeAvg); swapFlow.TradingAmountNetAvg = swapFlow.TradingAmountNetAvg.HasValue ? BondPriceConverter.ToDisplay(swapFlow.TradingAmountNetAvg.Value) : swapFlow.TradingAmountNetAvg; swapFlow.TradingAmountNetFeeAvg = swapFlow.TradingAmountNetFeeAvg.HasValue ? BondPriceConverter.ToDisplay(swapFlow.TradingAmountNetFeeAvg.Value) : swapFlow.TradingAmountNetFeeAvg; swapFlow.TradingQty /= ConsGlobal.bondShowPriceMultiple; } return swapFlow; } /// /// 流水汇总 /// public void SwapFlowMerge(DateTime tradeDate) { new SysJobService(UserInfo).UpdateJob("互换流水合成持仓", 21, "互换流水汇总进行中"); var predicate = PredicateBuilder.Create(n => n.DataState == (int)SwapFlowDateStateEnum.等待完成 && n.OccurTime == tradeDate && n.BsType != (int)EnumDirection.UnKnown); var capitalQuery = DbContext.swap_fund_account.Where(x => x.Status == (int)SwapFoundAccountStatusEnum.正常); var flowquery = DbContext.swap_flow.Where(predicate); var tradeQuery = DbContext.trade.Where(t => t.TradeStatus == ConsTrade.确认成交 && t.StructureType == ClientMarginTypeEnum.多空组合.ToString() && t.ValidState != "InValid" && t.StartDate <= tradeDate && t.ExerciseDate >= tradeDate); List swapFlowSummaries = new List(); var query = from flow in flowquery join capital in capitalQuery on flow.FundAccount equals capital.FundAccount join td in tradeQuery on capital.SwapTradeId equals td.id select new SwapFlowQueryResponse { id = flow.id, FundAccount = flow.FundAccount, OccurTime = flow.OccurTime, SwapTradeId = capital.SwapTradeId, SwapTradeNo = capital.SwapTradeNo, BsType = flow.BsType, UnderlyingCode = flow.UnderlyingCode, TradingQty = flow.TradingQty, TradingAmount = flow.TradingAmount, TradingFee = flow.TradingFee, TradingAmountAvg = flow.TradingAmountAvg, TradingAmountFeeAvg = flow.TradingAmountFeeAvg, ContractSize = flow.ContractSize }; foreach (var item in query) { if (GetUnderlyingCode(item.UnderlyingCode)) { swapFlowSummaries.Add(item); } } if (swapFlowSummaries.Count == 0) { return; } foreach (var item in swapFlowSummaries) { var flow = flowquery.First(x => x.id == item.id); flow.DataState = (int)SwapFlowDateStateEnum.完成; } var swapFlowGroup = swapFlowSummaries.GroupBy(g => new { g.SwapTradeId, g.OccurTime, g.UnderlyingCode, g.BsType }); foreach (var gourpItem in swapFlowGroup) { var swapflow = gourpItem.First(); swap_flow_merge swap_flow_summary = new swap_flow_merge() { OccurTime = swapflow.OccurTime.Value, FundAccount = swapflow.FundAccount, SwapTradeId = swapflow.SwapTradeId, SwapTradeNo = swapflow.SwapTradeNo, UnderlyingCode = swapflow.UnderlyingCode, BsType = swapflow.BsType, TradingQty = gourpItem.Sum(s => s.TradingQty), TradingAmount = gourpItem.Sum(s => s.TradingAmount), TradingFee = gourpItem.Sum(s => s.TradingFee), DataState = (int)SwapFlowDateStateEnum.等待完成, TradingAmountFeeAvg = gourpItem.Average(s => s.TradingAmountFeeAvg), TradingAmountAvg = Math.Round(gourpItem.Average(s => s.TradingAmountAvg), ConsGlobal.PriceRound, MidpointRounding.AwayFromZero), ContractSize = swapflow.ContractSize }; UpdateDbOption(swap_flow_summary); DbContext.swap_flow_merge.Add(swap_flow_summary); } DbContext.SaveChanges(); new SysJobService(UserInfo).UpdateJob("互换流水合成持仓", 22, "互换流水汇总完成"); } public void UpdatePayDate(UpdatePayDateDto dto) { var id = long.Parse(DataProtect.Decrypt(dto.Id)); var model = DbContext.swap_flow_event.FirstOrDefault(p => p.id == id); if(model!=null) { model.PayDate=dto.PayDate; model.OptId = UserInfo.UserId; model.OptName = UserInfo.UserName; model.OptTime = DateTime.Now; DbContext.SaveChanges(); } } #region 私有方法 /// /// 必填项校验 /// /// /// private void CheckRequired(swap_flow req) { if (string.IsNullOrEmpty(req.UnderlyingCode) && string.IsNullOrEmpty(req.UnderlyingCode.Trim())) { throw new ServiceException("标的代码不能为空"); } req.UnderlyingCode = req.UnderlyingCode.Trim(); } /// /// 数据有效性校验 /// /// private void CheckValid(swap_flow req) { CheckRequired(req); var roundedPrice = Math.Round(req.TradingAmountAvg, ConsGlobal.SwapDeliveryPriceRound, MidpointRounding.AwayFromZero); if (req.TradingAmountAvg != roundedPrice) { throw new ServiceException($"成交全价最多保留{ConsGlobal.SwapDeliveryPriceRound}位小数"); } var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(req.UnderlyingCode); if (underlying == null) { throw new ServiceException("没有找到标的信息:" + req.UnderlyingCode); } var isBond = underlying.IsBond(); if (isBond) { // 债券报价(×100)转入库小数(×0.01),价格字段统一走 BondPriceConverter req.TradingAmountAvg = BondPriceConverter.ToStorage(req.TradingAmountAvg); req.TradingAmountFeeAvg = BondPriceConverter.ToStorage(req.TradingAmountFeeAvg); if (req.TradingAmountNet.HasValue) req.TradingAmountNet = BondPriceConverter.ToStorage(req.TradingAmountNet.Value); if (req.TradingAmountNetFee.HasValue) req.TradingAmountNetFee = BondPriceConverter.ToStorage(req.TradingAmountNetFee.Value); // 数量×100(万手→手),与价格维度无关,保留常量 req.TradingQty *= ConsGlobal.bondShowPriceMultiple; } req.TradingAmountAvg = Math.Round( req.TradingAmountAvg, isBond ? ConsGlobal.PriceRound : ConsGlobal.SwapDeliveryPriceRound, MidpointRounding.AwayFromZero); } #endregion } }