From 4e6d887b684e60625a1ea6c943abb65b9cadca52 Mon Sep 17 00:00:00 2001 From: ruisu Date: Thu, 9 Jul 2026 16:18:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E4=BF=AE=E6=94=B9=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YLErpDAL/Modules/RiskEngine/RiskEngineService.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs index fea278d0..a6949a2a 100644 --- a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs +++ b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs @@ -497,7 +497,7 @@ namespace YLErp.Modules.RiskEngine // Id = 1000001, // RuleName = "挂钩标的集中度校验(本地)", // RuleText = "取值字段:分子取 QuotaMonitorService 已注入 DataMap[same_underlying_total_notional],该值按存续交易口径汇总同一标的 StockEqvNotional;分母取 DataMap[underlying_manager].IssueSize,债券标的场景下该值由 underlying_manager.ExJson 反序列化回填,含义按当前业务测试口径使用发行量(亿)。为什么这么取:当前上下文已经稳定注入了这两个值,且与集中度规则最接近正式口径。计算逻辑:同一标的总名义本金 ÷ 发行量 × 100%,发行量需先乘 100000000 还原为元,结果大于 30% 时触发审批。", - // RuleExpr = "DataMap.ContainsKey(\"same_underlying_total_notional\") && DataMap[\"same_underlying_total_notional\"] != null && DataMap.ContainsKey(\"underlying_manager\") && DataMap[\"underlying_manager\"] != null && ((YLErp.DBModels.underlying_manager)DataMap[\"underlying_manager\"]).IssueSize.HasValue && ((YLErp.DBModels.underlying_manager)DataMap[\"underlying_manager\"]).IssueSize.Value > 0 && Convert.ToDecimal(DataMap[\"same_underlying_total_notional\"]) / (((YLErp.DBModels.underlying_manager)DataMap[\"underlying_manager\"]).IssueSize.Value * 100000000m) * 100m > 30m", + // RuleExpr = "DataMap.ContainsKey("same_underlying_total_notional") && DataMap["same_underlying_total_notional"] != null && DataMap.ContainsKey("underlying_manager") && DataMap["underlying_manager"] != null && ((YLErp.DBModels.underlying_manager)DataMap["underlying_manager"]).IssueSize.HasValue && ((YLErp.DBModels.underlying_manager)DataMap["underlying_manager"]).IssueSize.Value > 0 && Convert.ToDecimal(DataMap["same_underlying_total_notional"]) / (((YLErp.DBModels.underlying_manager)DataMap["underlying_manager"]).IssueSize.Value * 100000000m) * 100m > 30m", // Version = 1, // Status = RiskRuleStatus.Active, // OptId = 0, @@ -513,7 +513,7 @@ namespace YLErp.Modules.RiskEngine // Id = 1000004, // RuleName = "保证金支付比例超阈值(本地)", // RuleText = "取值字段:直接取 DataMap[trade].MarginRate,对应 trade 表保证金率字段。为什么这么取:该字段已经在当前上下文稳定注入,且 seed 规则 4 的判断核心也是保证金比例。计算逻辑:本地测试按数值型比例直接比较,MarginRate 大于 0.5 视为超过 50%,触发审批。", - // RuleExpr = "DataMap.ContainsKey(\"trade\") && DataMap[\"trade\"] != null && ((YLErp.DBModels.trade)DataMap[\"trade\"]).MarginRate > 0.5", + // RuleExpr = "DataMap.ContainsKey("trade") && DataMap["trade"] != null && ((YLErp.DBModels.trade)DataMap["trade"]).MarginRate > 0.5", // Version = 1, // Status = RiskRuleStatus.Active, // OptId = 0, @@ -529,7 +529,7 @@ namespace YLErp.Modules.RiskEngine // Id = 1000005, // RuleName = "保证金利率偏离(本地)", // RuleText = "取值字段:正式口径应取收益互换扩展数据中的保证金利率字段,但当前 RiskContext 未注入 trade_swap,因此本地测试先取 DataMap[trade].MarginRate 近似代替。为什么这么取:当前上下文只有 trade 可直接取值,先保证规则链路可验证。计算逻辑:若近似保证金利率不在 2% 到 5% 区间内,即小于 0.02 或大于 0.05,则触发审批。", - // RuleExpr = "DataMap.ContainsKey(\"trade\") && DataMap[\"trade\"] != null && ((((YLErp.DBModels.trade)DataMap[\"trade\"]).MarginRate < 0.02) || (((YLErp.DBModels.trade)DataMap[\"trade\"]).MarginRate > 0.05))", + // RuleExpr = "DataMap.ContainsKey("trade") && DataMap["trade"] != null && ((((YLErp.DBModels.trade)DataMap["trade"]).MarginRate < 0.02) || (((YLErp.DBModels.trade)DataMap["trade"]).MarginRate > 0.05))", // Version = 1, // Status = RiskRuleStatus.Active, // OptId = 0, @@ -545,7 +545,7 @@ namespace YLErp.Modules.RiskEngine // Id = 1000006, // RuleName = "保证金收取比例低于最低标准(本地)", // RuleText = "取值字段:正式口径应取配置项 MinMarginRate 或客户/品种最低保证金率,当前上下文未注入配置对象,因此本地测试仍取 DataMap[trade].MarginRate 做比较。为什么这么取:trade.MarginRate 是当前唯一稳定可得且能反映保证金比例的字段。计算逻辑:先以 20% 作为本地测试最低标准,MarginRate 小于 0.2 时触发审批,后续接入正式配置后再替换阈值来源。", - // RuleExpr = "DataMap.ContainsKey(\"trade\") && DataMap[\"trade\"] != null && ((YLErp.DBModels.trade)DataMap[\"trade\"]).MarginRate < 0.2", + // RuleExpr = "DataMap.ContainsKey("trade") && DataMap["trade"] != null && ((YLErp.DBModels.trade)DataMap["trade"]).MarginRate < 0.2", // Version = 1, // Status = RiskRuleStatus.Active, // OptId = 0, @@ -561,7 +561,7 @@ namespace YLErp.Modules.RiskEngine // Id = 1000007, // RuleName = "起息日早于当前日期(本地)", // RuleText = "取值字段:取 DataMap[trade].StartDate,对应 trade 表开始日。为什么这么取:seed 规则 7 直接使用 StartDate 与当前日期比较,当前上下文也已注入 trade。计算逻辑:StartDate 有值且日期早于系统当天 DateTime.Today 时触发审批。", - // RuleExpr = "DataMap.ContainsKey(\"trade\") && DataMap[\"trade\"] != null && ((YLErp.DBModels.trade)DataMap[\"trade\"]).StartDate.HasValue && ((YLErp.DBModels.trade)DataMap[\"trade\"]).StartDate.Value.Date < DateTime.Today", + // RuleExpr = "DataMap.ContainsKey("trade") && DataMap["trade"] != null && ((YLErp.DBModels.trade)DataMap["trade"]).StartDate.HasValue && ((YLErp.DBModels.trade)DataMap["trade"]).StartDate.Value.Date < DateTime.Today", // Version = 1, // Status = RiskRuleStatus.Active, // OptId = 0, @@ -577,7 +577,7 @@ namespace YLErp.Modules.RiskEngine // Id = 1000008, // RuleName = "支付日为银行间交易日(本地)", // RuleText = "取值字段:取 DataMap[trade].SettlementDate,对应 trade 表结算日期。为什么这么取:当前代码中支付相关日期可直接从 trade 取得,且项目已有 QdpCalendarHelper.GetNonHolidayDefore 可用于交易日校验。计算逻辑:若 SettlementDate 有值,且向前修正到最近交易日后的结果不等于原日期,则说明原日期不是银行间交易日,触发审批。", - // RuleExpr = "DataMap.ContainsKey(\"trade\") && DataMap[\"trade\"] != null && ((YLErp.DBModels.trade)DataMap[\"trade\"]).SettlementDate.HasValue && QdpCalendarHelper.GetNonHolidayDefore(((YLErp.DBModels.trade)DataMap[\"trade\"]).SettlementDate.Value.Date) != ((YLErp.DBModels.trade)DataMap[\"trade\"]).SettlementDate.Value.Date", + // RuleExpr = "DataMap.ContainsKey("trade") && DataMap["trade"] != null && ((YLErp.DBModels.trade)DataMap["trade"]).SettlementDate.HasValue && QdpCalendarHelper.GetNonHolidayDefore(((YLErp.DBModels.trade)DataMap["trade"]).SettlementDate.Value.Date) != ((YLErp.DBModels.trade)DataMap["trade"]).SettlementDate.Value.Date", // Version = 1, // Status = RiskRuleStatus.Active, // OptId = 0, @@ -593,7 +593,7 @@ namespace YLErp.Modules.RiskEngine // Id = 1000009, // RuleName = "到期日为银行间交易日(本地)", // RuleText = "取值字段:取 DataMap[trade].ExerciseDate,对应当前交易里更接近业务到期/行权日的字段。为什么这么取:TradeBase 中 MaturityDate 注释已提示容易与 ExerciseDate 混淆,当前测试按交易实际到期处理字段 ExerciseDate 落地,避免先取错口径。计算逻辑:ExerciseDate 有值且向前修正到最近交易日后的结果不等于原日期时,视为不是银行间交易日,触发审批。", - // RuleExpr = "DataMap.ContainsKey(\"trade\") && DataMap[\"trade\"] != null && ((YLErp.DBModels.trade)DataMap[\"trade\"]).ExerciseDate.HasValue && QdpCalendarHelper.GetNonHolidayDefore(((YLErp.DBModels.trade)DataMap[\"trade\"]).ExerciseDate.Value.Date) != ((YLErp.DBModels.trade)DataMap[\"trade\"]).ExerciseDate.Value.Date", + // RuleExpr = "DataMap.ContainsKey("trade") && DataMap["trade"] != null && ((YLErp.DBModels.trade)DataMap["trade"]).ExerciseDate.HasValue && QdpCalendarHelper.GetNonHolidayDefore(((YLErp.DBModels.trade)DataMap["trade"]).ExerciseDate.Value.Date) != ((YLErp.DBModels.trade)DataMap["trade"]).ExerciseDate.Value.Date", // Version = 1, // Status = RiskRuleStatus.Active, // OptId = 0, @@ -609,7 +609,7 @@ namespace YLErp.Modules.RiskEngine // Id = 1000010, // RuleName = "平仓日为银行间交易日(本地)", // RuleText = "取值字段:取 DataMap[trade].UnWindDate,对应 trade 表平仓日。为什么这么取:当前上下文已注入该字段,且 seed 规则中的平仓日判断在本地最接近该口径。计算逻辑:UnWindDate 有值且向前修正到最近交易日后的结果不等于原日期时,视为不是银行间交易日,触发审批。", - // RuleExpr = "DataMap.ContainsKey(\"trade\") && DataMap[\"trade\"] != null && ((YLErp.DBModels.trade)DataMap[\"trade\"]).UnWindDate.HasValue && QdpCalendarHelper.GetNonHolidayDefore(((YLErp.DBModels.trade)DataMap[\"trade\"]).UnWindDate.Value.Date) != ((YLErp.DBModels.trade)DataMap[\"trade\"]).UnWindDate.Value.Date", + // RuleExpr = "DataMap.ContainsKey("trade") && DataMap["trade"] != null && ((YLErp.DBModels.trade)DataMap["trade"]).UnWindDate.HasValue && QdpCalendarHelper.GetNonHolidayDefore(((YLErp.DBModels.trade)DataMap["trade"]).UnWindDate.Value.Date) != ((YLErp.DBModels.trade)DataMap["trade"]).UnWindDate.Value.Date", // Version = 1, // Status = RiskRuleStatus.Active, // OptId = 0,