using BaseOUDAL; using YLErp.BLL; using YLErp.Commons; using YLErp.Model; using YLErp.Modules.EodModule; using YLErp.Modules.RiskExposure; using YLErp.Modules.RiskModule; using YLErp.Modules.TradeModule; using YLErp.QdpModule; namespace YLErp.Modules.RiskHedgingModule { public class HedgeRiskMonitoringService : YLBaseService { private readonly ClientDBContext clientDB; public HedgeRiskMonitoringService(OptUserInfo userInfo) : base(userInfo) { clientDB = DbContextFactory.GetClientDbContext(userInfo); } public HedgeRiskMonitoringService(YLBaseService baseService) : base(baseService) { } public HedgeRiskMonitoringService(OptUserInfo optUser, YLContext dbContext) : base(optUser, dbContext) { } /// /// 读取配置 /// /// public HedgeRiskMonitoringReq ReadHedgeRiskMonitoringReportConfig() { HedgeRiskMonitoringReq result = null; try { var cfg = DbContext.AppConfig.Where(O => O.PName == "HedgeRiskMonitoringConfig").FirstOrDefault(); if (cfg == null) { result = new HedgeRiskMonitoringReq(); cfg = new AppConfig() { PGroup = "Custom", PName = "HedgeRiskMonitoringConfig", PType = "string", Remark = "风险对冲检测表配置", CreateTime = DateTime.Now, }; DbContext.AppConfig.Add(cfg); cfg.PValue = result.ToJson(); DbContext.SaveChanges(); } else { result = JsonHelper.ToObject(cfg.PValue); } } catch { } return result ?? new HedgeRiskMonitoringReq(); } /// /// 保存配置 /// /// public void SaveHedgeRiskMonitoringReportConfig(HedgeRiskMonitoringReq req) { try { var cfg = DbContext.AppConfig.Where(O => O.PName == "HedgeRiskMonitoringConfig").FirstOrDefault(); if (cfg == null) { cfg = new AppConfig() { PGroup = "System", PName = "HedgeRiskMonitoringConfig", PType = "string", Remark = "风险对冲检测表配置", CreateTime = DateTime.Now, }; DbContext.AppConfig.Add(cfg); } cfg.PValue = req.ToJson(); cfg.OptDate = DateTime.Now; DbContext.SaveChanges(); } catch { } } public HedgeRiskMonitoringReportModel GetHedgeRiskMonitoringReportModel(DateTime endDate, HedgeRiskMonitoringReq req, RiskRequestModel reqRisk, EodPositionRisksReq eodPositionRisksReq, TradeMultiCloseQueryModel reqTradeMultiClose) { var hedgeRiskMonitoringReportModel = new HedgeRiskMonitoringReportModel(); //汇总 hedgeRiskMonitoringReportModel.QuotaTargetReport = new QuotaTargetReport() { QuotaStopLoss = req.quotaStopLoss, QuotaCostRisk = req.quotaCostRisk, QuotaPressureTest = req.quotaPressureTest, QuotaCashDelta = req.quotaCashDelta, QuotaContractTerm = req.quotaContractTerm, QuotaUnderlyingConcentration = req.quotaUnderlyingConcentration, QuotaStockEqvNotional = req.quotaStockEqvNotional, QuotaMarginHold = req.quotaMarginHold, }; if (PS.Config.ErpElement.UseOldEodPnLExplainer) { if (reqRisk?.EodSettlePriceMode == "结算价") { new Modules.RiskExposure.RiskExposureReportService(UserInfo).GetPortfolioList(reqRisk, out var riskCollectReport); GetQuotaTargetReportByRiskCollect(endDate, hedgeRiskMonitoringReportModel.QuotaTargetReport, riskCollectReport, eodPositionRisksReq); hedgeRiskMonitoringReportModel.RiskCollectReport = riskCollectReport; } else { new Modules.RiskExposure.RiskExposureReportService(UserInfo).GetPortfolioList(reqRisk, out var riskCollectReport); GetQuotaTargetReportByRiskCollect(endDate, hedgeRiskMonitoringReportModel.QuotaTargetReport, riskCollectReport, eodPositionRisksReq); hedgeRiskMonitoringReportModel.RiskCollectReport = riskCollectReport; } } else { if (reqRisk?.EodSettlePriceMode == "结算价") { new Modules.RiskExposure.RiskExposureReportService(UserInfo).GetPortfolioList(reqRisk, out var riskCollectReport); GetQuotaTargetReportByRiskCollect(endDate, hedgeRiskMonitoringReportModel.QuotaTargetReport, riskCollectReport, eodPositionRisksReq); hedgeRiskMonitoringReportModel.RiskCollectReport = riskCollectReport; } else { new Modules.RiskExposure.RiskExposureReportService(UserInfo).GetPortfolioList(reqRisk, out var riskCollectReport); GetQuotaTargetReportByRiskCollect(endDate, hedgeRiskMonitoringReportModel.QuotaTargetReport, riskCollectReport, eodPositionRisksReq); hedgeRiskMonitoringReportModel.RiskCollectReport = riskCollectReport; } } //预付金监控报表 hedgeRiskMonitoringReportModel.BondMonitorReport = GetClientLatestBalance(endDate); if (hedgeRiskMonitoringReportModel.BondMonitorReport.BondMonitorDetails.Count == 0) { hedgeRiskMonitoringReportModel.BondMonitorReport.BondMonitorDetails.Add(new BondMonitorDetail() { IsRiskEventToDay = "", IsAppened = "" }); } var PositionRisklist = new EodPositionRisksQueryService(UserInfo).GetEodPositionRisksDataHandle(eodPositionRisksReq); var PositionRisklist2 = PositionRisklist.Select(n => new ExpandoDictionary(n)).ToArray(); //日终报表 hedgeRiskMonitoringReportModel.PositionRiskReport = PositionRisklist2; var OptionSettlelist = new Modules.TradeModule.QueryModule.OtcOptionMultiCloseService(UserInfo).HandleExportDataToList(reqTradeMultiClose); var OptionSettlelist2 = OptionSettlelist.Select(n => new ExpandoDictionary(n.MetaDic)).ToArray(); //了结报表 hedgeRiskMonitoringReportModel.OptionSettleReport = OptionSettlelist2; //预付金占用 var currMargin = DbContext.exchange_account.Any() ? DbContext.exchange_account.Sum(O => O.CurrMargin) : 0; hedgeRiskMonitoringReportModel.QuotaTargetReport.MarginHold = currMargin == 0 ? 0 : currMargin / 10000;//万元 return hedgeRiskMonitoringReportModel; } public BondMonitorReport GetClientLatestBalance(DateTime? ValueDateTo, bool IsClientBalanceGap = false, bool IsGetOuterMarginGap = false, bool ParentFlag = false) { var ValueDateFrom = ValueDateTo; var context = new Modules.EodModule.QueryModule.EodSettleInfoQueryContext(UserInfo); var clientIds = context.GetClientIds(); var cb = BLL.EodSettlement.ClientBalanceUtility.GetClientBanlances(clientIds, ValueDateFrom.Value, ValueDateTo.Value, IsClientBalanceGap, IsGetOuterMarginGap, ParentFlag).ToList(); var bondMonitorReport = new BondMonitorReport { BondMonitorDetails = new List() }; var MarginOccupationPositiveNumber = cb.Where(x => x.MarginOccupation > 0).ToList(); foreach (var item in MarginOccupationPositiveNumber) { var c = new YLContext(); var bondMonitorDetail = new BondMonitorDetail(); var name = clientDB.client.FirstOrDefault(l => l.id == item.ClientId).Name; bondMonitorDetail.ClientName = name; bondMonitorDetail.DepositReceivable = item.MarginOccupation; bondMonitorDetail.CreditAndClosingBalance = item.AmountFund + item.TotalCredit; bondMonitorReport.BondMonitorDetails.Add(bondMonitorDetail); } bondMonitorReport.SumBondMonitor = MarginOccupationPositiveNumber.Sum(x => x.MarginOccupation); return bondMonitorReport; } public void ReqDefaultHandle(DateTime endDate, out RiskRequestModel reqRisk, out EodPositionRisksReq eodPositionRisksReq, out TradeMultiCloseQueryModel reqTradeMultiClose) { //方顿-风险监测表-汇总数据开始日期需要为每年的第一个交易日 var startDate = new DateTime(valuedateBLL.ValueDate.Year, 1, 1); for (var i = 1; i < 30; i++) { if (!QdpCalendarHelper.IsHoliday(startDate)) { break; } startDate = startDate.AddDays(1); } reqRisk = new RiskRequestModel { EodSettlePriceMode = "收盘价", ValueDateStart = startDate, ValueDateEnd = endDate }; eodPositionRisksReq = new EodPositionRisksReq { EodSettlePriceMode = "收盘价", IsOnlyExport = false, IsParentTrade = false, VolType = "持仓", needSettleData = false, page = 0, rows = 0, ValueDate = endDate }; reqTradeMultiClose = new TradeMultiCloseQueryModel { GetTotal = true }; ; //reqTradeMultiClose.PageIndex = 1; //reqTradeMultiClose.PageSize = 25; //reqTradeMultiClose.TradeStatus = "确认成交,新增待确认,修改待确认,审批中,已拒绝,已执行,已平仓,已到期,平仓待复核,行权待复核,互换待复核,提前终止拒绝"; reqTradeMultiClose.UnWindType = "全部"; reqTradeMultiClose.UseForwardASwap = true; reqTradeMultiClose.UnwindDateStart = startDate; reqTradeMultiClose.UnwindDateEnd = endDate; } public void GetQuotaTargetReportByRiskCollect(DateTime endDate, QuotaTargetReport quotaTargetReport, RiskCollectReport riskCollectReport, EodPositionRisksReq eodPositionRisksReq) { quotaTargetReport.StopLoss = riskCollectReport.PortfolioSum.Pnl / 10000;//单位为万元 quotaTargetReport.CashDelta = riskCollectReport.PortfolioSum.DeltaCash / 10000;//单位为万元 quotaTargetReport.StockEqvNotional = riskCollectReport.PortfolioSum.OtcStockEqvNotionalReal / 10000;//单位为万元 var req = new Modules.EodModule.eod_varReq { ValueDate = endDate, PvPercent = 0.95, IsNeedExport = false }; var results = new Modules.EodModule.EodVaRService(UserInfo).GetEodVaR(req); //风险价值 quotaTargetReport.CostRisk = results.Any() ? ((double?)Math.Abs(results.First().WinLoss) / 10000) : null;//单位为万元 //压力测试 var req2 = new Modules.ScenarioModule.ScenarioRequest { //req2.ConfigId = 13; UseTradeDivendRate = true, ValueDate = endDate, VolType = "对冲", RiskFreeRate = valuedateBLL.SysRiskFreeRate(), SearchModel = new Modules.ScenarioModule.TradeScenarioSearchModel { UserAssets = eodPositionRisksReq.UserAssets, UserClients = eodPositionRisksReq.UserClients, PositionDate = endDate, IsSelAll = true, page = 1, rows = 20, sord = "asc" } }; var config = DbContext.ScenarioConfig.Where(O => O.ConfigName == "对冲风险压力测试").FirstOrDefault(); if (config == null) { throw new ServiceException("没有找到名为\"对冲风险压力测试\"情景分析配置"); } var result = new Modules.ScenarioModule.ScenarioCalcService(UserInfo).Calculate(req2, config); quotaTargetReport.PressureTest = result.ResultItems.Any() ? ((double?)Math.Abs(result.ResultItems.GroupBy(o => $"{o.xIndex}_{o.yIndex}").ToList().Select(o => o.Sum(O => O.PnL)).Min()) / 10000)/*单位为万元*/ : null; } } }