Merge branch 'glms/feature/1.4.2' of http://git.yiliantech.com/gitlab/otc-dev/zszq-trs into glms/feature/1.4.2
This commit is contained in:
@@ -160,17 +160,3 @@ csharp_preserve_single_line_statements = true
|
||||
|
||||
# CA1819: Properties should not return arrays
|
||||
dotnet_diagnostic.CA1819.severity = silent
|
||||
|
||||
# JavaScript 和 TypeScript 文件
|
||||
[*.{js,jsx,ts,tsx}]
|
||||
# 缩进和间距
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
tab_width = 4
|
||||
|
||||
# 新行首选项
|
||||
end_of_line = crlf
|
||||
insert_final_newline = false
|
||||
|
||||
# 拖尾逗号不添加
|
||||
trailing_comma = none
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
public enum RiskControlStrategy
|
||||
{
|
||||
Block = 1,
|
||||
Approval = 2,
|
||||
ShowTip = 3
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
public enum RiskRuleStatus
|
||||
{
|
||||
Active = 1,
|
||||
Disabled = 2,
|
||||
Deleted = 3
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
public enum RiskVariableCategory
|
||||
{
|
||||
BookingElement = 1,
|
||||
MarketData = 2,
|
||||
SystemCalc = 3,
|
||||
BooleanCheck = 4
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
public enum RiskVariableDataType
|
||||
{
|
||||
Numeric = 1,
|
||||
Date = 2,
|
||||
Boolean = 3
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
[Table("glms_risk_rule")]
|
||||
public class glms_risk_rule : DBModelWithOperator
|
||||
{
|
||||
public string RuleName { get; set; }
|
||||
public string RuleText { get; set; }
|
||||
public string ConditionJson { get; set; }
|
||||
public string RuleExpr { get; set; }
|
||||
public RiskRuleStatus Status { get; set; } = RiskRuleStatus.Active;
|
||||
public int Version { get; set; } = 1;
|
||||
public int? UpdateOptId { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime? UpdateDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
[Table("glms_risk_rule_application")]
|
||||
public class glms_risk_rule_application : DBModelWithOperator
|
||||
{
|
||||
public string RuleIds { get; set; }
|
||||
public RiskRuleStatus Status { get; set; } = RiskRuleStatus.Active;
|
||||
public RiskControlStrategy ControlStrategy { get; set; }
|
||||
public string TriggerPoints { get; set; }
|
||||
public string ScopeAssetBookIds { get; set; }
|
||||
public string ScopeClientIds { get; set; }
|
||||
public string ScopeUnderlyingTypes { get; set; }
|
||||
public string ScopeTradeTypes { get; set; }
|
||||
public int ScopeIsGlobal { get; set; }
|
||||
public int Version { get; set; } = 1;
|
||||
public int? UpdateOptId { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime? UpdateDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
[Table("glms_risk_rule_audit_log")]
|
||||
public class glms_risk_rule_audit_log : DBModelBase
|
||||
{
|
||||
public string OperationType { get; set; }
|
||||
public string TargetType { get; set; }
|
||||
public long TargetId { get; set; }
|
||||
public string TargetName { get; set; }
|
||||
public string OperationDetail { get; set; }
|
||||
public string Result { get; set; }
|
||||
public string SnapshotData { get; set; }
|
||||
public long OptId { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace YLErp.DBModels
|
||||
{
|
||||
[Table("glms_risk_variable")]
|
||||
public class glms_risk_variable : DBModelWithOperator
|
||||
{
|
||||
public string VariableName { get; set; }
|
||||
public RiskVariableCategory Category { get; set; }
|
||||
public RiskVariableDataType DataType { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string ValueDomain { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string VariableExpr { get; set; }
|
||||
public int Version { get; set; } = 1;
|
||||
public int SortOrder { get; set; }
|
||||
public int? UpdateOptId { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime? UpdateDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
CREATE TABLE `glms_risk_rule` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||
`RuleName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '规则名称',
|
||||
`RuleText` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规则文本',
|
||||
`ConditionJson` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '条件JSON(结构化模式, RuleCondition数组)',
|
||||
`RuleExpr` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '规则表达式(自由文本模式, 类C#表达式)',
|
||||
`Status` tinyint NOT NULL DEFAULT 1 COMMENT '状态: 1=Active, 2=Disabled, 3=Deleted',
|
||||
`Version` int NOT NULL DEFAULT 1 COMMENT '版本号(乐观锁)',
|
||||
`OptId` int NULL DEFAULT NULL COMMENT '创建人Id',
|
||||
`OptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人名称',
|
||||
`OptDate` datetime NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`UpdateOptId` int NULL DEFAULT NULL COMMENT '最后修改人Id',
|
||||
`UpdateOptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '最后修改人名称',
|
||||
`UpdateDate` datetime NULL DEFAULT NULL COMMENT '最后修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_status`(`Status` ASC) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '风控规则定义表' ROW_FORMAT = Dynamic;
|
||||
|
||||
CREATE TABLE `glms_risk_rule_application` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||
`RuleIds` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '关联规则Id列表(逗号分隔)',
|
||||
`Status` tinyint NOT NULL DEFAULT 1 COMMENT '状态: 1=Active, 2=Disabled, 3=Deleted',
|
||||
`ControlStrategy` tinyint NOT NULL COMMENT '控制策略: 1=Block, 2=Approval, 3=Warning',
|
||||
`TriggerPoints` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '触发时点(逗号分隔)',
|
||||
`ScopeAssetBookIds` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '适用账户Id列表',
|
||||
`ScopeClientIds` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '适用对手方Id列表',
|
||||
`ScopeUnderlyingTypes` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '适用标的类型',
|
||||
`ScopeTradeTypes` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '适用合约类型',
|
||||
`ScopeIsGlobal` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否全局适用: 0=否, 1=是',
|
||||
`Version` int NOT NULL DEFAULT 1 COMMENT '版本号(乐观锁)',
|
||||
`OptId` int NULL DEFAULT NULL COMMENT '创建人Id',
|
||||
`OptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人名称',
|
||||
`OptDate` datetime NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`UpdateOptId` int NULL DEFAULT NULL COMMENT '最后修改人Id',
|
||||
`UpdateOptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '最后修改人名称',
|
||||
`UpdateDate` datetime NULL DEFAULT NULL COMMENT '最后修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_status`(`Status` ASC) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '风控规则应用配置表' ROW_FORMAT = Dynamic;
|
||||
|
||||
CREATE TABLE `glms_risk_rule_audit_log` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||
`OperationType` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '操作类型(RULE_CREATE/RULE_UPDATE等)',
|
||||
`TargetType` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '目标类型(RULE/APPLICATION/VARIABLE)',
|
||||
`TargetId` bigint NOT NULL COMMENT '目标记录Id',
|
||||
`TargetName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '目标名称',
|
||||
`OperationDetail` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '操作详情',
|
||||
`Result` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作结果',
|
||||
`SnapshotData` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '快照数据(JSON)',
|
||||
`OptId` bigint NOT NULL COMMENT '操作人Id',
|
||||
`OptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作人名称',
|
||||
`OptDate` datetime NOT NULL COMMENT '操作时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `idx_opt_date`(`OptDate` ASC) USING BTREE,
|
||||
INDEX `idx_operation_type`(`OperationType` ASC) USING BTREE,
|
||||
INDEX `idx_target_type`(`TargetType` ASC) USING BTREE,
|
||||
INDEX `idx_target_id`(`TargetId` ASC) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '风控规则操作审计日志表' ROW_FORMAT = Dynamic;
|
||||
|
||||
CREATE TABLE `glms_risk_variable` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||
`VariableName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '变量名称',
|
||||
`Category` tinyint NOT NULL COMMENT '分类: 1=BookingElement, 2=MarketData, 3=SystemCalc, 4=BooleanCheck',
|
||||
`DataType` tinyint NOT NULL COMMENT '数据类型: 1=Numeric, 2=Date, 3=Boolean',
|
||||
`Unit` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '单位',
|
||||
`ValueDomain` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '值域描述',
|
||||
`Description` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
|
||||
`VariableExpr` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '变量表达式(C#表达式)',
|
||||
`Version` int NOT NULL DEFAULT 1 COMMENT '版本号(乐观锁)',
|
||||
`SortOrder` int NOT NULL DEFAULT 0 COMMENT '排序',
|
||||
`OptId` int NULL DEFAULT NULL COMMENT '创建人Id',
|
||||
`OptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人名称',
|
||||
`OptDate` datetime NULL DEFAULT NULL COMMENT '创建时间',
|
||||
`UpdateOptId` int NULL DEFAULT NULL COMMENT '最后修改人Id',
|
||||
`UpdateOptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '最后修改人名称',
|
||||
`UpdateDate` datetime NULL DEFAULT NULL COMMENT '最后修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '风控变量池定义表' ROW_FORMAT = Dynamic;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=1;
|
||||
@@ -1,135 +0,0 @@
|
||||
-- ============================================================
|
||||
-- 规则应用初始数据(对应设计文档 §4.9.1 通用规则预置参考)
|
||||
-- 依赖:seed_rules.sql(规则数据需先插入)
|
||||
--
|
||||
-- 每条规则对应一条应用配置(1:1),定义"何时、对谁、怎么处理"
|
||||
-- ControlStrategy: 1=Block(禁止), 2=Approval(审批), 3=Warning(提示)
|
||||
-- TriggerPoints: BOOK_CONFIRM=簿记交易确认
|
||||
-- ScopeIsGlobal: 1=全局适用, 0=按维度配置(Scope字段为NULL表示"全部")
|
||||
-- ============================================================
|
||||
|
||||
-- 规则1:挂钩标的集中度超阈值(审批,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '挂钩标的集中度超阈值';
|
||||
|
||||
-- 规则2:挂钩标的到期日小于合约到期日(禁止,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 1, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '挂钩标的到期日小于合约到期日';
|
||||
|
||||
-- 规则3:名义本金超阈值(审批,账户/合约类型)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '名义本金超阈值';
|
||||
|
||||
-- 规则4:保证金支付比例超阈值(审批,账户/标的类型)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '保证金支付比例超阈值';
|
||||
|
||||
-- 规则5:保证金利率偏离(审批,账户)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '保证金利率偏离';
|
||||
|
||||
-- 规则6:保证金收取比例低于最低标准(审批,账户/标的类型)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '保证金收取比例低于最低标准';
|
||||
|
||||
-- 规则7:起息日早于当前日期(审批,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '起息日早于当前日期';
|
||||
|
||||
-- 规则8:支付日为银行间交易日(审批,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '支付日为银行间交易日';
|
||||
|
||||
-- 规则9:到期日为银行间交易日(审批,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '到期日为银行间交易日';
|
||||
|
||||
-- 规则10:平仓日为银行间交易日(审批,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '平仓日为银行间交易日';
|
||||
|
||||
-- 规则11:合约期限超阈值(审批,账户)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '合约期限超阈值';
|
||||
|
||||
-- 规则12:债券类净价偏离(审批,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '债券类净价偏离';
|
||||
|
||||
-- 规则13:债券类收益率偏离(审批,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '债券类收益率偏离';
|
||||
|
||||
-- 规则14:非债券类价格偏离(审批,全局)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '非债券类价格偏离';
|
||||
|
||||
-- 规则15:单一交易对手累计标的数量超阈值(审批,对手方)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '单一交易对手累计标的数量超阈值';
|
||||
|
||||
-- 规则16:多头支付固定端利率偏离(审批,账户)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '多头支付固定端利率偏离';
|
||||
|
||||
-- 规则17:空头利率减点借贷加权偏离(审批,账户)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '空头利率减点借贷加权偏离';
|
||||
|
||||
-- 规则18:账户授权收支方向不匹配(禁止,账户)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 1, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '账户授权收支方向不匹配';
|
||||
|
||||
-- 规则19:执行价偏离超阈值(审批,账户)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '执行价偏离超阈值';
|
||||
|
||||
-- 规则20:希腊字母限额超阈值(提示,账户/标的,预留接口)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 3, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '希腊字母限额超阈值';
|
||||
|
||||
-- 规则21:接近/触发敲入敲出价(提示,全局,预留接口)
|
||||
INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
|
||||
SELECT
|
||||
CAST(r.id AS CHAR), 1, 3, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
|
||||
FROM `glms_risk_rule` r WHERE r.RuleName = '接近/触发敲入敲出价';
|
||||
@@ -1,50 +0,0 @@
|
||||
-- ============================================================
|
||||
-- 异常交易监控页面 - 操作权限(按钮)数据
|
||||
-- 依赖:异常交易监控菜单 id=1077 (type=1) 需先插入
|
||||
-- 对应 FunctionRight.xml 风险控制下风控相关操作权限(共16个按钮)
|
||||
-- type: 0=目录 1=菜单 2=按钮
|
||||
-- ============================================================
|
||||
|
||||
-- ----------------------------
|
||||
-- 1. sys_menu 页面+按钮(type=1,2)
|
||||
-- ----------------------------
|
||||
INSERT INTO `yltrs_admin`.`sys_menu` (`id`, `pid`, `pids`, `name`, `code`, `type`, `icon`, `router`, `component`, `permission`, `application`, `open_type`, `visible`, `link`, `redirect`, `weight`, `sort`, `remark`, `status`, `create_time`, `create_user`, `update_time`, `update_user`) VALUES
|
||||
(1077, 99, NULL, '异常交易监控', NULL, 1, NULL, NULL, NULL, '异常交易监控', NULL, NULL, NULL, NULL, NULL, NULL, 0, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1078, 1077, NULL, '风控规则查看', NULL, 2, NULL, NULL, NULL, '风控规则查看', NULL, NULL, NULL, NULL, NULL, NULL, 1, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1079, 1077, NULL, '风控规则新增', NULL, 2, NULL, NULL, NULL, '风控规则新增', NULL, NULL, NULL, NULL, NULL, NULL, 2, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1080, 1077, NULL, '风控规则编辑', NULL, 2, NULL, NULL, NULL, '风控规则编辑', NULL, NULL, NULL, NULL, NULL, NULL, 3, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1081, 1077, NULL, '风控规则删除', NULL, 2, NULL, NULL, NULL, '风控规则删除', NULL, NULL, NULL, NULL, NULL, NULL, 4, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1082, 1077, NULL, '风控规则启停', NULL, 2, NULL, NULL, NULL, '风控规则启停', NULL, NULL, NULL, NULL, NULL, NULL, 5, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1083, 1077, NULL, '风控应用查看', NULL, 2, NULL, NULL, NULL, '风控应用查看', NULL, NULL, NULL, NULL, NULL, NULL, 6, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1084, 1077, NULL, '风控应用新增', NULL, 2, NULL, NULL, NULL, '风控应用新增', NULL, NULL, NULL, NULL, NULL, NULL, 7, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1085, 1077, NULL, '风控应用编辑', NULL, 2, NULL, NULL, NULL, '风控应用编辑', NULL, NULL, NULL, NULL, NULL, NULL, 8, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1086, 1077, NULL, '风控应用删除', NULL, 2, NULL, NULL, NULL, '风控应用删除', NULL, NULL, NULL, NULL, NULL, NULL, 9, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1087, 1077, NULL, '风控应用启停', NULL, 2, NULL, NULL, NULL, '风控应用启停', NULL, NULL, NULL, NULL, NULL, NULL, 10, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1088, 1077, NULL, '风控变量查看', NULL, 2, NULL, NULL, NULL, '风控变量查看', NULL, NULL, NULL, NULL, NULL, NULL, 11, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1089, 1077, NULL, '风控变量新增', NULL, 2, NULL, NULL, NULL, '风控变量新增', NULL, NULL, NULL, NULL, NULL, NULL, 12, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1090, 1077, NULL, '风控变量编辑', NULL, 2, NULL, NULL, NULL, '风控变量编辑', NULL, NULL, NULL, NULL, NULL, NULL, 13, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1091, 1077, NULL, '风控变量删除', NULL, 2, NULL, NULL, NULL, '风控变量删除', NULL, NULL, NULL, NULL, NULL, NULL, 14, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1092, 1077, NULL, '风控日志查看', NULL, 2, NULL, NULL, NULL, '风控日志查看', NULL, NULL, NULL, NULL, NULL, NULL, 15, '', 0, NULL, NULL, NULL, NULL),
|
||||
(1093, 1077, NULL, '风控日志导出', NULL, 2, NULL, NULL, NULL, '风控日志导出', NULL, NULL, NULL, NULL, NULL, NULL, 16, '', 0, NULL, NULL, NULL, NULL);
|
||||
|
||||
-- ----------------------------
|
||||
-- 2. sys_role_menu 角色1的按钮权限
|
||||
-- ----------------------------
|
||||
INSERT INTO `yltrs_admin`.`sys_role_menu` (`id`, `role_id`, `menu_id`) VALUES
|
||||
(1097, 1, 1077),
|
||||
(1098, 1, 1078),
|
||||
(1099, 1, 1079),
|
||||
(1100, 1, 1080),
|
||||
(1101, 1, 1081),
|
||||
(1102, 1, 1082),
|
||||
(1103, 1, 1083),
|
||||
(1104, 1, 1084),
|
||||
(1105, 1, 1085),
|
||||
(1106, 1, 1086),
|
||||
(1107, 1, 1087),
|
||||
(1108, 1, 1088),
|
||||
(1109, 1, 1089),
|
||||
(1110, 1, 1090),
|
||||
(1111, 1, 1091),
|
||||
(1112, 1, 1092),
|
||||
(1113, 1, 1093);
|
||||
@@ -1,292 +0,0 @@
|
||||
-- ============================================================
|
||||
-- 规则初始数据(对应设计文档 §4.9.1 通用规则预置参考)
|
||||
-- 依赖:seed_variables.sql(变量池数据需先插入,ID 1~44)
|
||||
--
|
||||
-- 变量 ID 映射(seed_variables.sql 自增):
|
||||
-- 1=合约名义本金 2=合约起息日 3=合约到期日 4=合约平仓日
|
||||
-- 5=合约支付日 6=期初净价 7=期初全价 8=期初收益率
|
||||
-- 9=期初价格 10=期末全价 11=期末价格 12=保证金利率
|
||||
-- 13=保证金比例 14=客户授信额度
|
||||
-- 15=上一收盘日中债估值净价 16=上一收盘日中债估值全价 17=上一收盘日中债估值收益率
|
||||
-- 18=上一日收盘价 19=借贷加权费率 20=FR007 21=当前日期
|
||||
-- 22=挂钩标的到期日 23=标的发行余额
|
||||
-- 24=挂钩标的集中度 25=授信占用率 26=合约期限 27=Delta
|
||||
-- 28=Gamma 29=Vega 30=Theta 31=利息端利率
|
||||
-- 32=对手方累计标的数量 33=同一标的累计名义本金 34=同一客户累计名义本金
|
||||
-- 35=总持仓名义本金
|
||||
-- 36=到期日是否银行间交易日 37=平仓日是否银行间交易日 38=支付日是否银行间交易日
|
||||
-- 39=利息端/浮动端方向是否同向 40=关键业务要素是否一致
|
||||
-- 41=多空方向为多头 42=多空方向为空头
|
||||
-- 43=保证金收支方向为支付 44=保证金收支方向为收取
|
||||
-- 45=期初净价偏离度 46=期初收益率偏离度 47=期初价格偏离度
|
||||
-- 48=利息端利率与FR007偏离度 49=利息端利率与借贷加权费率偏离度
|
||||
-- 50=执行价偏离度 51=执行价 52=客户品种最低保证金率 53=参考价格
|
||||
--
|
||||
-- ConditionJson 精简设计:只存 VariableId/Operator/ThresholdType/Value/ThresholdVariableId
|
||||
-- 展示字段(VariableName/VariableType/Unit/ThresholdVariableName)从变量接口关联获取
|
||||
-- ============================================================
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 插入 21 条通用规则
|
||||
-- ============================================================
|
||||
|
||||
-- 规则1:挂钩标的集中度超阈值(审批,全局)
|
||||
-- 条件:挂钩标的集中度(ID=24) > 30%
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('挂钩标的集中度超阈值',
|
||||
'挂钩标的集中度超过阈值(默认30%)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 24,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 30
|
||||
)),
|
||||
'calc.UnderlyingConcentration > 30',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则2:挂钩标的到期日小于合约到期日(禁止,全局)
|
||||
-- 条件:挂钩标的到期日(ID=22) < 合约到期日(ID=3)
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('挂钩标的到期日小于合约到期日',
|
||||
'挂钩标的到期日早于合约到期日时禁止交易',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 22,
|
||||
'Operator', '早于', 'ThresholdType', 'Variable',
|
||||
'ThresholdVariableId', 3
|
||||
)),
|
||||
'market.UnderlyingMaturityDate < trade.ExerciseDate',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则3:名义本金超阈值(审批,账户/合约类型)
|
||||
-- 条件:合约名义本金(ID=1) > 100000000(1亿元)
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('名义本金超阈值',
|
||||
'合约名义本金超过阈值(默认1亿元)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 1,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 100000000
|
||||
)),
|
||||
'trade.StockEqvNotional > 100000000',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则4:保证金支付比例超阈值(审批,账户/标的类型)
|
||||
-- 条件:保证金比例(ID=13) > 50%
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('保证金支付比例超阈值',
|
||||
'保证金比例超过阈值(默认50%)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 13,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 50
|
||||
)),
|
||||
'trade.MarginRate > 50',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则5:保证金利率偏离(审批,账户)
|
||||
-- 条件:保证金利率(ID=12) 不介于 [2%, 5%]
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('保证金利率偏离',
|
||||
'保证金利率不在配置区间内(默认2%~5%)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 12,
|
||||
'Operator', '不介于', 'ThresholdType', 'Fixed', 'Value', JSON_ARRAY(2, 5),
|
||||
'IncludeLowerBound', true, 'IncludeUpperBound', true
|
||||
)),
|
||||
'!(client_marginrate.InitMarginRebateRate >= 2 && client_marginrate.InitMarginRebateRate <= 5)',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则6:保证金收取比例低于最低标准(审批,账户/标的类型)
|
||||
-- 条件:保证金比例(ID=13) < 客户品种最低保证金率(ID=52)
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('保证金收取比例低于最低标准',
|
||||
'保证金比例低于客户品种最低保证金率时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 13,
|
||||
'Operator', '<', 'ThresholdType', 'Variable',
|
||||
'ThresholdVariableId', 52
|
||||
)),
|
||||
'trade.MarginRate < config.MinMarginRate',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则7:起息日早于当前日期(审批,全局)
|
||||
-- 条件:合约起息日(ID=2) < 当前日期(ID=21)
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('起息日早于当前日期',
|
||||
'合约起息日早于当前日期时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 2,
|
||||
'Operator', '早于', 'ThresholdType', 'Variable',
|
||||
'ThresholdVariableId', 21
|
||||
)),
|
||||
'trade.StartDate < sys.CurrentDate',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则8:支付日为银行间交易日(审批,全局)
|
||||
-- 条件:支付日是否银行间交易日(ID=38) = 是
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('支付日为银行间交易日',
|
||||
'支付日为银行间交易日时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 38,
|
||||
'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
|
||||
)),
|
||||
'calc.IsSettlementDateTradingDay == true',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则9:到期日为银行间交易日(审批,全局)
|
||||
-- 条件:到期日是否银行间交易日(ID=36) = 是
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('到期日为银行间交易日',
|
||||
'到期日为银行间交易日时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 36,
|
||||
'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
|
||||
)),
|
||||
'calc.IsExerciseDateTradingDay == true',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则10:平仓日为银行间交易日(审批,全局)
|
||||
-- 条件:平仓日是否银行间交易日(ID=37) = 是
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('平仓日为银行间交易日',
|
||||
'平仓日为银行间交易日时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 37,
|
||||
'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
|
||||
)),
|
||||
'calc.IsUnwindDateTradingDay == true',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则11:合约期限超阈值(审批,账户)
|
||||
-- 条件:合约期限(ID=26) > 365天
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('合约期限超阈值',
|
||||
'合约期限超过阈值(默认365天)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 26,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 365
|
||||
)),
|
||||
'calc.MaturityDays > 365',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则12:债券类净价偏离(审批,全局)
|
||||
-- 条件:期初净价偏离度(ID=45) > 5%
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('债券类净价偏离',
|
||||
'期初净价与上一收盘日中债估值净价偏离度超阈值(默认5%)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 45,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 5
|
||||
)),
|
||||
'Math.Abs(swap_position.PosiNetNoFeePrice - market.CBValuationNetPrice) / market.CBValuationNetPrice * 100 > 5',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则13:债券类收益率偏离(审批,全局)
|
||||
-- 条件:期初收益率偏离度(ID=46) > 5%
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('债券类收益率偏离',
|
||||
'期初收益率与上一收盘日中债估值收益率偏离度超阈值(默认5%)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 46,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 5
|
||||
)),
|
||||
'Math.Abs(trade.InitYtm - market.CBValuationYtm) / market.CBValuationYtm * 100 > 5',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则14:非债券类价格偏离(审批,全局)
|
||||
-- 条件:期初价格偏离度(ID=47) > 5%
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('非债券类价格偏离',
|
||||
'期初价格与上一日收盘价偏离度超阈值(默认5%)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 47,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 5
|
||||
)),
|
||||
'Math.Abs(trade.SpotPrice - market.LastClosePrice) / market.LastClosePrice * 100 > 5',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则15:单一交易对手累计标的数量超阈值(审批,对手方)
|
||||
-- 条件:对手方累计标的数量(ID=32) > 10个
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('单一交易对手累计标的数量超阈值',
|
||||
'对手方累计标的数量超过阈值(默认10个)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 32,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 10
|
||||
)),
|
||||
'calc.CounterpartyUnderlyingCount > 10',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则16:多头支付固定端利率偏离(审批,账户)
|
||||
-- 条件:多空方向为多头(ID=41) AND 利息端利率与FR007偏离度(ID=48) > 3%
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('多头支付固定端利率偏离',
|
||||
'多头方向支付固定端场景下,利息端利率与FR007偏离度超阈值(默认3%)时触发审批',
|
||||
JSON_ARRAY(
|
||||
JSON_OBJECT(
|
||||
'VariableId', 41,
|
||||
'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
|
||||
),
|
||||
JSON_OBJECT(
|
||||
'VariableId', 48,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 3
|
||||
)
|
||||
),
|
||||
'calc.IsLongDirection == true && Math.Abs(calc.InterestRate - market.FR007) / market.FR007 * 100 > 3',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则17:空头利率减点借贷加权偏离(审批,账户)
|
||||
-- 条件:多空方向为空头(ID=42) AND 利息端利率与借贷加权费率偏离度(ID=49) > 2%
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('空头利率减点借贷加权偏离',
|
||||
'空头方向场景下,利息端利率与借贷加权费率偏离度超阈值(默认2%)时触发审批',
|
||||
JSON_ARRAY(
|
||||
JSON_OBJECT(
|
||||
'VariableId', 42,
|
||||
'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
|
||||
),
|
||||
JSON_OBJECT(
|
||||
'VariableId', 49,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 2
|
||||
)
|
||||
),
|
||||
'calc.IsShortDirection == true && Math.Abs(calc.InterestRate - market.BondLendingRate) / market.BondLendingRate * 100 > 2',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则18:账户授权收支方向不匹配(禁止,账户)
|
||||
-- 条件:保证金收支方向为支付(ID=43)(实际需结合账户授权方向判断,此处简化)
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('账户授权收支方向不匹配',
|
||||
'保证金收支方向与账户授权方向不匹配时禁止交易',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 43,
|
||||
'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
|
||||
)),
|
||||
'calc.IsMarginPay == true',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则19:执行价偏离超阈值(审批,账户)
|
||||
-- 条件:执行价偏离度(ID=50) > 5%
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('执行价偏离超阈值',
|
||||
'执行价与参考价格偏离度超阈值(默认5%)时触发审批',
|
||||
JSON_ARRAY(JSON_OBJECT(
|
||||
'VariableId', 50,
|
||||
'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 5
|
||||
)),
|
||||
'Math.Abs(trade.StrikePrice - market.ReferencePrice) / market.ReferencePrice * 100 > 5',
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则20:希腊字母限额超阈值(提示,预留接口,一期不纳入)
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('希腊字母限额超阈值',
|
||||
'Delta/Gamma/Vega/Theta任一超阈值时提示(预留接口,一期不纳入)',
|
||||
NULL,
|
||||
NULL,
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 规则21:接近/触发敲入敲出价(提示,预留接口,需确认具体判断逻辑)
|
||||
INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('接近/触发敲入敲出价',
|
||||
'标的价格接近敲入/敲出价时提示(预留接口,需确认具体判断逻辑)',
|
||||
NULL,
|
||||
NULL,
|
||||
1, 1, 0, 'SYSTEM', NOW());
|
||||
@@ -1,73 +0,0 @@
|
||||
-- ============================================================
|
||||
-- 变量池初始数据(对应设计文档 §4.4 变量池完整清单)
|
||||
-- ============================================================
|
||||
|
||||
-- 4.4.1 簿记要素类(Category=1)
|
||||
INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('合约名义本金', 1, 1, '元', '≥ 0', 'trade.StockEqvNotional 或 swap_position.PosiNotionalValue', 'trade.StockEqvNotional', 101, 0, 'SYSTEM', NOW()),
|
||||
('合约起息日', 1, 2, NULL, NULL, 'trade.StartDate 或 swap_position.PosiStartDate', 'trade.StartDate', 102, 0, 'SYSTEM', NOW()),
|
||||
('合约到期日', 1, 2, NULL, NULL, 'trade.ExerciseDate 或 swap_position.PosiMatuirityDate', 'trade.ExerciseDate', 103, 0, 'SYSTEM', NOW()),
|
||||
('合约平仓日', 1, 2, NULL, NULL, 'trade.UnWindDate', 'trade.UnWindDate', 104, 0, 'SYSTEM', NOW()),
|
||||
('合约支付日', 1, 2, NULL, NULL, 'trade.SettlementDate', 'trade.SettlementDate', 105, 0, 'SYSTEM', NOW()),
|
||||
('期初净价', 1, 1, '元', '≥ 0', 'swap_position.PosiNetNoFeePrice(债券 TRS)', 'swap_position.PosiNetNoFeePrice', 106, 0, 'SYSTEM', NOW()),
|
||||
('期初全价', 1, 1, '元', '≥ 0', 'swap_position.PosiNetFeePrice(债券 TRS)/ trade.SpotPrice(其他)', 'swap_position.PosiNetFeePrice', 107, 0, 'SYSTEM', NOW()),
|
||||
('期初收益率', 1, 1, '%', NULL, 'trade.InitYtm 或 swap_position.InitYtm', 'trade.InitYtm', 108, 0, 'SYSTEM', NOW()),
|
||||
('期初价格', 1, 1, '元', '≥ 0', 'trade.SpotPrice(非债券类)', 'trade.SpotPrice', 109, 0, 'SYSTEM', NOW()),
|
||||
('期末全价', 1, 1, '元', '≥ 0', 'eod_swap_position.UnderlyingPrice(债券 TRS)', 'eod_swap_position.UnderlyingPrice', 110, 0, 'SYSTEM', NOW()),
|
||||
('期末价格', 1, 1, '元', '≥ 0', 'trade.FinalPrice', 'trade.FinalPrice', 111, 0, 'SYSTEM', NOW()),
|
||||
('保证金利率', 1, 1, '%', NULL, 'client_marginrate.InitMarginRebateRate', 'client_marginrate.InitMarginRebateRate', 112, 0, 'SYSTEM', NOW()),
|
||||
('保证金比例', 1, 1, '%', '0~100', 'trade.MarginRate', 'trade.MarginRate', 113, 0, 'SYSTEM', NOW()),
|
||||
('客户授信额度', 1, 1, '元', '≥ 0', 'credit.Credit', 'credit.Credit', 114, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 4.4.2 行情类(Category=2,统一取上一交易日收盘价)
|
||||
INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('上一收盘日中债估值净价', 2, 1, '元', '≥ 0', '资讯数据', 'market.CBValuationNetPrice', 201, 0, 'SYSTEM', NOW()),
|
||||
('上一收盘日中债估值全价', 2, 1, '元', '≥ 0', '资讯数据', 'market.CBValuationFullPrice', 202, 0, 'SYSTEM', NOW()),
|
||||
('上一收盘日中债估值收益率', 2, 1, '%', NULL, '资讯数据', 'market.CBValuationYtm', 203, 0, 'SYSTEM', NOW()),
|
||||
('上一日收盘价', 2, 1, '元', '≥ 0', '行情数据,按标的区分', 'market.LastClosePrice', 204, 0, 'SYSTEM', NOW()),
|
||||
('借贷加权费率', 2, 1, '%', NULL, 'CMDM 标的债券借贷费率行情表', 'market.BondLendingRate', 205, 0, 'SYSTEM', NOW()),
|
||||
('FR007', 2, 1, '%', NULL, '上一交易日收盘价', 'market.FR007', 206, 0, 'SYSTEM', NOW()),
|
||||
('当前日期', 2, 2, NULL, NULL, 'DateTime.Today', 'sys.CurrentDate', 207, 0, 'SYSTEM', NOW()),
|
||||
('挂钩标的到期日', 2, 2, NULL, NULL, '资讯数据', 'market.UnderlyingMaturityDate', 208, 0, 'SYSTEM', NOW()),
|
||||
('标的发行余额', 2, 1, '元', '≥ 0', '资讯数据', 'market.UnderlyingIssueBalance', 209, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 4.4.3 系统计算值类(Category=3)
|
||||
INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('挂钩标的集中度', 3, 1, '%', '0~100', '同一标的存续交易总名义本金 ÷ 标的发行余额 × 100', 'calc.UnderlyingConcentration', 301, 0, 'SYSTEM', NOW()),
|
||||
('授信占用率', 3, 1, '%', '0~100', '(已占用授信 + 本笔授信占用) ÷ 授信总额 × 100', 'calc.CreditUsageRate', 302, 0, 'SYSTEM', NOW()),
|
||||
('合约期限', 3, 1, '天', '≥ 0', '(ExerciseDate - StartDate).Days', 'calc.MaturityDays', 303, 0, 'SYSTEM', NOW()),
|
||||
('Delta', 3, 1, NULL, NULL, 'realtime_trade_risk.Delta(预留接口,一期不纳入)', 'realtime_trade_risk.Delta', 304, 0, 'SYSTEM', NOW()),
|
||||
('Gamma', 3, 1, NULL, NULL, 'realtime_trade_risk.Gamma(预留接口,一期不纳入)', 'realtime_trade_risk.Gamma', 305, 0, 'SYSTEM', NOW()),
|
||||
('Vega', 3, 1, NULL, NULL, 'realtime_trade_risk.Vega(预留接口,一期不纳入)', 'realtime_trade_risk.Vega', 306, 0, 'SYSTEM', NOW()),
|
||||
('Theta', 3, 1, NULL, NULL, 'realtime_trade_risk.Theta(预留接口,一期不纳入)', 'realtime_trade_risk.Theta', 307, 0, 'SYSTEM', NOW()),
|
||||
('利息端利率', 3, 1, '%', NULL, '固定利率 或 FR007 ± 加点', 'calc.InterestRate', 308, 0, 'SYSTEM', NOW()),
|
||||
('对手方累计标的数量', 3, 1, '个', '≥ 0', 'COUNT(DISTINCT UnderlyingId) 该对手方所有存续交易,含本笔', 'calc.CounterpartyUnderlyingCount', 309, 0, 'SYSTEM', NOW()),
|
||||
('同一标的累计名义本金', 3, 1, '元', '≥ 0', 'SUM(该标的所有存续交易的 StockEqvNotional),含本笔', 'calc.SameUnderlyingTotalNotional', 310, 0, 'SYSTEM', NOW()),
|
||||
('同一客户累计名义本金', 3, 1, '元', '≥ 0', 'SUM(该客户所有存续交易的 StockEqvNotional),含本笔', 'calc.SameClientTotalNotional', 311, 0, 'SYSTEM', NOW()),
|
||||
('总持仓名义本金', 3, 1, '元', '≥ 0', 'SUM(所有存续交易的 StockEqvNotional)', 'calc.TotalPositionNotional', 312, 0, 'SYSTEM', NOW());
|
||||
-- 新增变量(ID 45~53):
|
||||
-- 45=期初净价偏离度 46=期初收益率偏离度 47=期初价格偏离度
|
||||
-- 48=利息端利率与FR007偏离度 49=利息端利率与借贷加权费率偏离度
|
||||
-- 50=执行价偏离度 51=执行价 52=客户品种最低保证金率 53=参考价格
|
||||
INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('期初净价偏离度', 3, 1, '%', '≥ 0', 'ABS(期初净价-中债估值净价)/中债估值净价*100', 'Math.Abs(swap_position.PosiNetNoFeePrice - market.CBValuationNetPrice) / market.CBValuationNetPrice * 100', 313, 0, 'SYSTEM', NOW()),
|
||||
('期初收益率偏离度', 3, 1, '%', '≥ 0', 'ABS(期初收益率-中债估值收益率)/中债估值收益率*100', 'Math.Abs(trade.InitYtm - market.CBValuationYtm) / market.CBValuationYtm * 100', 314, 0, 'SYSTEM', NOW()),
|
||||
('期初价格偏离度', 3, 1, '%', '≥ 0', 'ABS(期初价格-上一日收盘价)/上一日收盘价*100', 'Math.Abs(trade.SpotPrice - market.LastClosePrice) / market.LastClosePrice * 100', 315, 0, 'SYSTEM', NOW()),
|
||||
('利息端利率与FR007偏离度', 3, 1, '%', '≥ 0', 'ABS(利息端利率-FR007)/FR007*100', 'Math.Abs(calc.InterestRate - market.FR007) / market.FR007 * 100', 316, 0, 'SYSTEM', NOW()),
|
||||
('利息端利率与借贷加权费率偏离度', 3, 1, '%', '≥ 0', 'ABS(利息端利率-借贷加权费率)/借贷加权费率*100', 'Math.Abs(calc.InterestRate - market.BondLendingRate) / market.BondLendingRate * 100', 317, 0, 'SYSTEM', NOW()),
|
||||
('执行价偏离度', 3, 1, '%', '≥ 0', 'ABS(执行价-参考价格)/参考价格*100', 'Math.Abs(trade.StrikePrice - market.ReferencePrice) / market.ReferencePrice * 100', 318, 0, 'SYSTEM', NOW()),
|
||||
('执行价', 1, 1, '元', '≥ 0', 'trade.StrikePrice', 'trade.StrikePrice', 115, 0, 'SYSTEM', NOW()),
|
||||
('客户品种最低保证金率', 1, 1, '%', '0~100', '客户品种最低保证金率(由账户/标的配置决定)', 'config.MinMarginRate', 116, 0, 'SYSTEM', NOW()),
|
||||
('参考价格', 2, 1, '元', '≥ 0', '执行价参考价格(行情数据)', 'market.ReferencePrice', 210, 0, 'SYSTEM', NOW());
|
||||
|
||||
-- 4.4.4 布尔判断类(Category=4)
|
||||
INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
|
||||
('到期日是否银行间交易日', 4, 3, NULL, NULL, '查询银行间交易日历', 'calc.IsExerciseDateTradingDay', 401, 0, 'SYSTEM', NOW()),
|
||||
('平仓日是否银行间交易日', 4, 3, NULL, NULL, '查询银行间交易日历', 'calc.IsUnwindDateTradingDay', 402, 0, 'SYSTEM', NOW()),
|
||||
('支付日是否银行间交易日', 4, 3, NULL, NULL, '查询银行间交易日历', 'calc.IsSettlementDateTradingDay', 403, 0, 'SYSTEM', NOW()),
|
||||
('利息端/浮动端方向是否同向', 4, 3, NULL, NULL, '利息端"收取"↔浮动端"多头",利息端"支付"↔浮动端"空头"', 'calc.IsInterestFloatSameDirection', 404, 0, 'SYSTEM', NOW()),
|
||||
('关键业务要素是否一致', 4, 3, NULL, NULL, '交易确认书 vs 簿记要素(大模型方案)', 'calc.IsKeyElementsConsistent', 405, 0, 'SYSTEM', NOW()),
|
||||
('多空方向为多头', 4, 3, NULL, NULL, 'trade.BuySell == "买入" 或浮动端为多头', 'calc.IsLongDirection', 406, 0, 'SYSTEM', NOW()),
|
||||
('多空方向为空头', 4, 3, NULL, NULL, '与多头互斥', 'calc.IsShortDirection', 407, 0, 'SYSTEM', NOW()),
|
||||
('保证金收支方向为支付', 4, 3, NULL, NULL, '保证金方向为支付', 'calc.IsMarginPay', 408, 0, 'SYSTEM', NOW()),
|
||||
('保证金收支方向为收取', 4, 3, NULL, NULL, '与支付互斥', 'calc.IsMarginReceive', 409, 0, 'SYSTEM', NOW());
|
||||
@@ -1,4 +1,4 @@
|
||||
using BaseOUDAL;
|
||||
using BaseOUDAL;
|
||||
using YLErp.Core.DBModels;
|
||||
using YLErp.Model;
|
||||
|
||||
@@ -408,10 +408,5 @@ namespace YLErp.BLL
|
||||
public DbSet<trade_contract_oa_result> tradeContractOaResult { get; set; }
|
||||
public DbSet<BondPayment> bondPayment { get; set; }
|
||||
|
||||
public DbSet<glms_risk_rule> glms_risk_rule { get; set; }
|
||||
public DbSet<glms_risk_rule_application> glms_risk_rule_application { get; set; }
|
||||
public DbSet<glms_risk_rule_audit_log> glms_risk_rule_audit_log { get; set; }
|
||||
public DbSet<glms_risk_variable> glms_risk_variable { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -199,8 +199,14 @@ namespace YLErp.DBModels
|
||||
}
|
||||
public bool SwapCanEdit()
|
||||
{
|
||||
var hasSwapDealEvent = swap_Events.Any(x =>
|
||||
!x.Invalid
|
||||
&& (x.EventType == (int)SwapEventTypeEnum.平仓
|
||||
|| x.EventType == (int)SwapEventTypeEnum.互换
|
||||
|| x.EventType == (int)SwapEventTypeEnum.自动互换));
|
||||
|
||||
//确认成交
|
||||
return !(ConsTrade.TradeStatusAfterAndWithOutConfirmed.Contains(TradeStatus) || ConsTrade.审批中.Equals(TradeStatus) || UnWindDate.HasValue || (!PS.Config.TradeElement.IsAmendableAfterConfirm && TradeDate < valuedateBLL.ValueDate && ConsTrade.确认成交.Equals(TradeStatus)));
|
||||
return !(ConsTrade.TradeStatusAfterAndWithOutConfirmed.Contains(TradeStatus) || ConsTrade.审批中.Equals(TradeStatus) || UnWindDate.HasValue || hasSwapDealEvent || (!PS.Config.TradeElement.IsAmendableAfterConfirm && TradeDate < valuedateBLL.ValueDate && ConsTrade.确认成交.Equals(TradeStatus)));
|
||||
}
|
||||
public bool CanDelete()
|
||||
{
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 规则编译结果。
|
||||
/// 用于承载公式校验、Roslyn 编译结果和错误信息。
|
||||
/// </summary>
|
||||
public class RuleCompileResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否编译成功。
|
||||
/// </summary>
|
||||
public bool Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编译失败时的错误信息。
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 编译成功后的可执行委托。
|
||||
/// </summary>
|
||||
public Func<RiskContext, bool> CompiledScript { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建成功结果。
|
||||
/// </summary>
|
||||
public static RuleCompileResult Ok(Func<RiskContext, bool> compiledScript)
|
||||
{
|
||||
return new RuleCompileResult
|
||||
{
|
||||
Success = true,
|
||||
CompiledScript = compiledScript
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建失败结果。
|
||||
/// </summary>
|
||||
public static RuleCompileResult Fail(string errorMessage)
|
||||
{
|
||||
return new RuleCompileResult
|
||||
{
|
||||
Success = false,
|
||||
ErrorMessage = errorMessage
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 规则编译结果的进程内缓存。
|
||||
/// 当前第一版按规则 Id 缓存 Roslyn 编译后的可执行委托。
|
||||
/// </summary>
|
||||
public static class RuleCompiledCache
|
||||
{
|
||||
/// <summary>
|
||||
/// 规则编译结果的进程内缓存。ConcurrentDictionary为线程安全的字典,用于缓存编译后的规则委托,性能略低。
|
||||
/// </summary>
|
||||
private static readonly ConcurrentDictionary<string, Func<RiskContext, bool>> Cache
|
||||
= new ConcurrentDictionary<string, Func<RiskContext, bool>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// 写入或更新规则编译结果。
|
||||
/// </summary>
|
||||
public static void Set(string ruleCode, Func<RiskContext, bool> compiledScript)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ruleCode) || compiledScript == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Cache[ruleCode] = compiledScript;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试获取规则编译结果。
|
||||
/// </summary>
|
||||
public static bool TryGet(string ruleCode, out Func<RiskContext, bool> compiledScript)
|
||||
{
|
||||
compiledScript = null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ruleCode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Cache.TryGetValue(ruleCode, out compiledScript);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定规则的编译结果。
|
||||
/// </summary>
|
||||
public static void Remove(string ruleCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ruleCode))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Cache.TryRemove(ruleCode, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空全部规则编译结果。
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
Cache.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,324 +0,0 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// Roslyn 脚本全局变量容器
|
||||
/// CSharpScript 执行时通过此对象传递 DataMap
|
||||
/// </summary>
|
||||
public class ScriptGlobals
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据字典:key=表名/前缀,value=对应数据对象
|
||||
/// </summary>
|
||||
public Dictionary<string, object> DataMap { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 规则编译器(Roslyn 版)
|
||||
///
|
||||
/// 编译时机:规则定义时(零运行时解析开销)
|
||||
/// 执行方式:判风控时直接调用 rule.CompiledScript(context) → bool
|
||||
///
|
||||
/// 相比表达式树方案的优势:
|
||||
/// - 代码简洁:生成 C# 字符串即可,无需手动拼接 Expression 节点
|
||||
/// - 灵活性高:天然支持多条件 AND/OR、复杂运算、未来可扩展任意 C# 语法
|
||||
/// - 可调试:生成的脚本代码可直接阅读和理解
|
||||
///
|
||||
/// 示例:
|
||||
/// RuleExpr: Convert.ToDecimal(((YLErp.DBModels.trade)DataMap["trade"]).StockEqvNotional) > 100000000m
|
||||
/// 编译结果:Func<RiskContext, bool>(内部通过 Roslyn 编译缓存)
|
||||
/// </summary>
|
||||
public static class RuleCompiler
|
||||
{
|
||||
/// <summary>
|
||||
/// 变量编码 → 类型全名的映射
|
||||
/// 用于 Roslyn 脚本中的类型强转,如 ((YLErp.DBModels.trade)DataMap["trade"])
|
||||
/// </summary>
|
||||
static IYcLogger _logger =LogFactory.GetLogger("RuleCompiler");
|
||||
private static readonly Dictionary<string, string> VariableTypeMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["trade"] = "YLErp.DBModels.trade",
|
||||
["swap_position"] = "YLErp.DBModels.swap_position",
|
||||
["client"] = "YLErp.DBModels.client",
|
||||
["credit"] = "YLErp.DBModels.credit",
|
||||
["client_marginrate"] = "YLErp.DBModels.client_marginrate",
|
||||
["market"] = "YLErp.DBModels.market",
|
||||
["calc"] = "YLErp.DBModels.calc",
|
||||
["sys"] = "YLErp.DBModels.sys",
|
||||
["eod_swap_position"] = "YLErp.DBModels.eod_swap_position",
|
||||
["realtime_trade_risk"] = "YLErp.DBModels.realtime_trade_risk",
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 将规则编译为可执行委托,并写入 rule.CompiledScript
|
||||
/// 调用时机:规则创建时 / 规则加载时 / 缓存刷新时
|
||||
/// </summary>
|
||||
public static void Compile(this RiskRule rule)
|
||||
{
|
||||
var result = ValidateAndCompileRule(rule);
|
||||
if (!result.Success)
|
||||
{
|
||||
throw new InvalidOperationException(result.ErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验并编译规则表达式。
|
||||
/// 当前 RuleExpr 要求是 Roslyn 可直接执行的 bool 表达式。
|
||||
/// </summary>
|
||||
public static RuleCompileResult ValidateAndCompileFormula(string formulaExp)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(formulaExp))
|
||||
{
|
||||
return RuleCompileResult.Fail("规则 RuleExpr 不能为空");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var compiled = CompileScript(formulaExp);
|
||||
return RuleCompileResult.Ok(compiled);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return RuleCompileResult.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 校验并编译规则,编译成功后同时写入规则对象和内存缓存。
|
||||
/// </summary>
|
||||
public static RuleCompileResult ValidateAndCompileRule(RiskRule rule)
|
||||
{
|
||||
if (rule == null)
|
||||
{
|
||||
return RuleCompileResult.Fail("规则不能为空");
|
||||
}
|
||||
|
||||
if (rule.Id <= 0)
|
||||
{
|
||||
return RuleCompileResult.Fail("规则 Id 不能为空");
|
||||
}
|
||||
|
||||
var result = ValidateAndCompileFormula(rule.RuleExpr);
|
||||
if (!result.Success)
|
||||
{
|
||||
return RuleCompileResult.Fail($"规则[{rule.Id}]编译失败:{result.ErrorMessage}");
|
||||
}
|
||||
|
||||
rule.CompiledScript = result.CompiledScript;
|
||||
RuleCompiledCache.Set(rule.Id.ToString(), result.CompiledScript);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析 ConditionJson,提取条件列表。
|
||||
/// 要求 expression 明确描述实际取值路径。
|
||||
/// 当前主执行链不再使用该方法,仅作为早期方案保留。
|
||||
/// </summary>
|
||||
// private static List<(string variableCode, string expression, string op, object value, string variableType)> ParseConditionJson(string conditionJson)
|
||||
// {
|
||||
// var result = new List<(string, string, string, object, string)>();
|
||||
// var jObj = JObject.Parse(formulaJson);
|
||||
// var conditions = jObj["conditions"] as JArray;
|
||||
|
||||
// if (conditions == null || !conditions.Any())
|
||||
// {
|
||||
// throw new ArgumentException("ConditionJson 中缺少 conditions");
|
||||
// }
|
||||
|
||||
// foreach (var cond in conditions)
|
||||
// {
|
||||
// string variableCode = cond["variableCode"]?.Value<string>();
|
||||
// string expression = cond["expression"]?.Value<string>();
|
||||
// string op = cond["operator"]?.Value<string>();
|
||||
// object value = cond["value"]?.Value<object>();
|
||||
// string variableType = cond["variableType"]?.Value<string>() ?? "numeric";
|
||||
|
||||
// if (string.IsNullOrWhiteSpace(expression) || string.IsNullOrWhiteSpace(op))
|
||||
// {
|
||||
// throw new ArgumentException("条件中缺少 expression 或 operator");
|
||||
// }
|
||||
|
||||
// result.Add((variableCode, expression, op, value, variableType));
|
||||
// }
|
||||
|
||||
// return result;
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// 根据条件列表生成 Roslyn C# 脚本代码。
|
||||
/// 多条件自动用 &&(AND)连接。
|
||||
/// 左值表达式统一基于 expression 构建。
|
||||
/// </summary>
|
||||
private static string BuildScriptCode(List<(string variableCode, string expression, string op, object value, string variableType)> conditions)
|
||||
{
|
||||
var exprParts = new List<string>();
|
||||
|
||||
foreach (var (_, expression, op, value, variableType) in conditions)
|
||||
{
|
||||
// 先根据 expression 构建左值访问表达式,再拼接比较符和右值字面量
|
||||
string leftExpr = BuildMemberAccessExpression(expression, variableType);
|
||||
|
||||
// 格式化阈值
|
||||
string valueLiteral = FormatValueLiteral(value, variableType);
|
||||
|
||||
// 格式化操作符
|
||||
string csharpOp = FormatOperator(op);
|
||||
|
||||
// 生成单条件表达式
|
||||
string expr = $"{leftExpr} {csharpOp} {valueLiteral}";
|
||||
exprParts.Add(expr);
|
||||
}
|
||||
|
||||
// 多条件用 && 连接
|
||||
return string.Join(" && ", exprParts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将前端传入的 expression 转成 Roslyn 可执行的成员访问表达式。
|
||||
/// 例如 trade.StockEqvNotional 会转成 ((YLErp.DBModels.trade)DataMap["trade"]).StockEqvNotional。
|
||||
/// 数值类型会自动包一层 Convert.ToDecimal,便于与 decimal 阈值比较。
|
||||
/// </summary>
|
||||
private static string BuildMemberAccessExpression(string expression, string variableType)
|
||||
{
|
||||
var parts = expression.Split('.');
|
||||
if (parts.Length < 2)
|
||||
{
|
||||
throw new ArgumentException($"expression 格式不正确:{expression}");
|
||||
}
|
||||
|
||||
string prefix = parts[0].Trim().ToLower();
|
||||
if (!VariableTypeMap.TryGetValue(prefix, out string typeFullName))
|
||||
{
|
||||
throw new ArgumentException($"未知前缀:{prefix}");
|
||||
}
|
||||
|
||||
// 除前缀外,其余部分都视为成员访问路径,便于后续扩展多级属性访问
|
||||
string memberAccess = string.Join(".", parts.Skip(1).Select(p => p.Trim()));
|
||||
string objectExpr = $"(({typeFullName})DataMap[\"{prefix}\"]).{memberAccess}";
|
||||
|
||||
if (variableType == "numeric" || variableType == "number")
|
||||
{
|
||||
return $"Convert.ToDecimal({objectExpr})";
|
||||
}
|
||||
|
||||
return objectExpr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用 Roslyn 编译 C# 脚本代码为可执行委托
|
||||
/// </summary>
|
||||
private static Func<RiskContext, bool> CompileScript(string scriptCode)
|
||||
{
|
||||
// 配置编译选项:引用必要的程序集
|
||||
var options = ScriptOptions.Default
|
||||
.WithReferences(
|
||||
typeof(RiskContext).Assembly, // YLErpDAL
|
||||
typeof(YLErp.DBModels.trade).Assembly // Model 所在程序集
|
||||
)
|
||||
.WithImports("System");
|
||||
|
||||
// 创建脚本(尚未执行,仅编译)
|
||||
var script = CSharpScript.Create<bool>(scriptCode, options, globalsType: typeof(ScriptGlobals));
|
||||
|
||||
// 编译(提前发现语法错误)
|
||||
//后续编译需提供接口,返回前端编译信息,包含编译错误列表
|
||||
var compilation = script.GetCompilation();
|
||||
var diagnostics = compilation.GetDiagnostics();
|
||||
var errors = diagnostics.Where(d => d.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error).ToList();
|
||||
if (errors.Any())
|
||||
{
|
||||
string errorMsg = string.Join("; ", errors.Select(e => e.GetMessage()));
|
||||
_logger.Error($"规则编译失败:{errorMsg}\n脚本代码:{scriptCode}");
|
||||
throw new InvalidOperationException($"脚本编译失败:{errorMsg}");
|
||||
}
|
||||
|
||||
// 生成可调用委托
|
||||
var runner = script.CreateDelegate();
|
||||
|
||||
// 包装为同步的 Func<RiskContext, bool>
|
||||
return ctx =>
|
||||
{
|
||||
var globals = new ScriptGlobals { DataMap = ctx.DataMap };
|
||||
try
|
||||
{
|
||||
return runner(globals).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// 脚本执行异常(如空引用、类型转换失败)视为规则不触发
|
||||
_logger.Error($"规则执行异常:{ex.Message}\n脚本代码:{scriptCode}");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 格式化阈值为 C# 字面量
|
||||
/// </summary>
|
||||
private static string FormatValueLiteral(object value, string variableType)
|
||||
{
|
||||
if (value == null) return "null";
|
||||
|
||||
string strValue = value.ToString();
|
||||
|
||||
// 数值类型统一加 m 后缀(decimal)
|
||||
if (variableType == "numeric" || variableType == "number")
|
||||
{
|
||||
if (decimal.TryParse(strValue, NumberStyles.Any, CultureInfo.InvariantCulture, out decimal d))
|
||||
{
|
||||
return d.ToString(CultureInfo.InvariantCulture) + "m";
|
||||
}
|
||||
}
|
||||
|
||||
// 布尔
|
||||
if (variableType == "boolean" || variableType == "bool")
|
||||
{
|
||||
if (bool.TryParse(strValue, out bool b))
|
||||
{
|
||||
return b ? "true" : "false";
|
||||
}
|
||||
}
|
||||
|
||||
// 日期
|
||||
if (variableType == "date" && DateTime.TryParse(strValue, out DateTime dt))
|
||||
{
|
||||
return $"DateTime.Parse(\"{dt:yyyy-MM-dd}\")";
|
||||
}
|
||||
|
||||
// 字符串(兜底)
|
||||
return $"\"{strValue.Replace("\\", "\\\\").Replace("\"", "\\\"")}\"";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将操作符统一为 C# 操作符
|
||||
/// </summary>
|
||||
private static string FormatOperator(string op)
|
||||
{
|
||||
return op?.Trim() switch
|
||||
{
|
||||
// 数值型 C# 符号
|
||||
"=" or "==" => "==",
|
||||
"!=" or "≠" => "!=",
|
||||
">" => ">",
|
||||
"<" => "<",
|
||||
">=" => ">=",
|
||||
"<=" => "<=",
|
||||
// 日期型中文语义 → C# 符号
|
||||
"早于" => "<",
|
||||
"晚于" => ">",
|
||||
"等于" => "==",
|
||||
"不早于" => ">=",
|
||||
"不晚于" => "<=",
|
||||
_ => throw new ArgumentException($"不支持的操作符:{op}")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class BatchOperationResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public int TotalCount { get; set; }
|
||||
public int SuccessCount { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class CreateRiskApplicationReq
|
||||
{
|
||||
public string RuleIds { get; set; }
|
||||
public RiskControlStrategy ControlStrategy { get; set; }
|
||||
public string TriggerPoints { get; set; }
|
||||
public string ScopeAssetBookIds { get; set; }
|
||||
public string ScopeClientIds { get; set; }
|
||||
public string ScopeUnderlyingTypes { get; set; }
|
||||
public string ScopeTradeTypes { get; set; }
|
||||
public int ScopeIsGlobal { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class CreateRiskRuleReq
|
||||
{
|
||||
public string RuleName { get; set; }
|
||||
public string RuleText { get; set; }
|
||||
public string ConditionJson { get; set; }
|
||||
public string RuleExpr { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class CreateRiskVariableReq
|
||||
{
|
||||
public string VariableName { get; set; }
|
||||
public RiskVariableCategory Category { get; set; }
|
||||
public RiskVariableDataType DataType { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string ValueDomain { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string VariableExpr { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using BaseOUDAL;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class QueryRiskApplicationReq : BaseSearchReq
|
||||
{
|
||||
public string RuleName { get; set; }
|
||||
public RiskRuleStatus? Status { get; set; }
|
||||
public RiskControlStrategy? Strategy { get; set; }
|
||||
public string TriggerPoint { get; set; }
|
||||
public string ScopeClientIds { get; set; }
|
||||
public string ScopeUnderlyingTypes { get; set; }
|
||||
public string ScopeTradeTypes { get; set; }
|
||||
public string ScopeAssetBookIds { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using BaseOUDAL;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class QueryRiskAuditLogReq : BaseSearchReq
|
||||
{
|
||||
public string OperationType { get; set; }
|
||||
public string TargetType { get; set; }
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
public string Keyword { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using BaseOUDAL;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class QueryRiskRuleReq : BaseSearchReq
|
||||
{
|
||||
public string Keyword { get; set; }
|
||||
public RiskRuleStatus? Status { get; set; }
|
||||
public long? VariableId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using BaseOUDAL;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class QueryRiskVariableReq : BaseSearchReq
|
||||
{
|
||||
public RiskVariableCategory? Category { get; set; }
|
||||
public RiskVariableDataType? DataType { get; set; }
|
||||
public string VariableName { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskApplicationDetail
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string RuleIds { get; set; }
|
||||
public RiskRuleStatus Status { get; set; }
|
||||
public RiskControlStrategy ControlStrategy { get; set; }
|
||||
public string TriggerPoints { get; set; }
|
||||
public string ScopeAssetBookIds { get; set; }
|
||||
public string ScopeClientIds { get; set; }
|
||||
public string ScopeUnderlyingTypes { get; set; }
|
||||
public string ScopeTradeTypes { get; set; }
|
||||
public int ScopeIsGlobal { get; set; }
|
||||
public int Version { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskApplicationListItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string RuleIds { get; set; }
|
||||
public int Status { get; set; }
|
||||
public RiskControlStrategy ControlStrategy { get; set; }
|
||||
public string TriggerPoints { get; set; }
|
||||
public string ScopeAssetBookIds { get; set; }
|
||||
public string ScopeClientIds { get; set; }
|
||||
public string ScopeUnderlyingTypes { get; set; }
|
||||
public string ScopeTradeTypes { get; set; }
|
||||
public int ScopeIsGlobal { get; set; }
|
||||
public int Version { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskAuditLogDetail
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string OperationType { get; set; }
|
||||
public string TargetType { get; set; }
|
||||
public long TargetId { get; set; }
|
||||
public string TargetName { get; set; }
|
||||
public string OperationDetail { get; set; }
|
||||
public string Result { get; set; }
|
||||
public string SnapshotData { get; set; }
|
||||
public long OptId { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskAuditLogListItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string OperationType { get; set; }
|
||||
public string TargetType { get; set; }
|
||||
public long TargetId { get; set; }
|
||||
public string TargetName { get; set; }
|
||||
public string OperationDetail { get; set; }
|
||||
public string Result { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskRuleApplicationSummary
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public RiskRuleStatus Status { get; set; }
|
||||
public RiskControlStrategy ControlStrategy { get; set; }
|
||||
public string TriggerPoints { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskRuleDetail
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string RuleName { get; set; }
|
||||
public string RuleText { get; set; }
|
||||
public string ConditionJson { get; set; }
|
||||
public string RuleExpr { get; set; }
|
||||
public RiskRuleStatus Status { get; set; }
|
||||
public int Version { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public List<RiskRuleApplicationSummary> Applications { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskRuleListItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string RuleName { get; set; }
|
||||
public string RuleText { get; set; }
|
||||
public string ConditionJson { get; set; }
|
||||
public string RuleExpr { get; set; }
|
||||
public RiskRuleStatus Status { get; set; }
|
||||
public int Version { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public int ApplicationCount { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskRuleSimpleItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string RuleName { get; set; }
|
||||
public string RuleText { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskRuleVersionItem
|
||||
{
|
||||
public int Version { get; set; }
|
||||
public string OperationType { get; set; }
|
||||
public string OperationDetail { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
using System;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskVariableDetail
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string VariableName { get; set; }
|
||||
public RiskVariableCategory Category { get; set; }
|
||||
public RiskVariableDataType DataType { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string ValueDomain { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string VariableExpr { get; set; }
|
||||
public int Version { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public int ReferenceCount { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskVariableListItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string VariableName { get; set; }
|
||||
public RiskVariableCategory Category { get; set; }
|
||||
public RiskVariableDataType DataType { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string ValueDomain { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string VariableExpr { get; set; }
|
||||
public int Version { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RiskVariableSimpleItem
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public string VariableName { get; set; }
|
||||
public RiskVariableCategory Category { get; set; }
|
||||
public RiskVariableDataType DataType { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string VariableExpr { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class RuleCondition
|
||||
{
|
||||
public long VariableId { get; set; }
|
||||
public string Operator { get; set; }
|
||||
public string ThresholdType { get; set; }
|
||||
public object Value { get; set; }
|
||||
public long? ThresholdVariableId { get; set; }
|
||||
// 介于/不介于 的边界包含控制,默认 true
|
||||
public bool IncludeLowerBound { get; set; } = true;
|
||||
public bool IncludeUpperBound { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class UpdateRiskApplicationReq
|
||||
{
|
||||
public string RuleIds { get; set; }
|
||||
public RiskControlStrategy ControlStrategy { get; set; }
|
||||
public string TriggerPoints { get; set; }
|
||||
public string ScopeAssetBookIds { get; set; }
|
||||
public string ScopeClientIds { get; set; }
|
||||
public string ScopeUnderlyingTypes { get; set; }
|
||||
public string ScopeTradeTypes { get; set; }
|
||||
public int ScopeIsGlobal { get; set; }
|
||||
public int Version { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class UpdateRiskRuleReq
|
||||
{
|
||||
public string RuleName { get; set; }
|
||||
public string RuleText { get; set; }
|
||||
public string ConditionJson { get; set; }
|
||||
public string RuleExpr { get; set; }
|
||||
public int Version { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine.Dto
|
||||
{
|
||||
public class UpdateRiskVariableReq
|
||||
{
|
||||
public string VariableName { get; set; }
|
||||
public RiskVariableCategory Category { get; set; }
|
||||
public RiskVariableDataType DataType { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public string ValueDomain { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string VariableExpr { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
public int Version { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 风控上下文:封装一次风控检查所需的全部数据上下文
|
||||
/// </summary>
|
||||
public class RiskContext
|
||||
{
|
||||
/// <summary>
|
||||
/// 当前交易ID
|
||||
/// </summary>
|
||||
public int TradeId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前触发时点
|
||||
/// </summary>
|
||||
public string TriggerPoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据字典:key=表名/前缀,value=对应数据对象
|
||||
/// </summary>
|
||||
public Dictionary<string, object> DataMap { get; set; } = new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
@@ -1,638 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using Qdp.Foundation.Utilities;
|
||||
using System.Reflection;
|
||||
using YLErp.BLL;
|
||||
using YLErp.Model;
|
||||
|
||||
/*
|
||||
================================================================================
|
||||
风控引擎服务 — RiskEngineService 技术方案与当前实现说明
|
||||
================================================================================
|
||||
|
||||
【项目背景】
|
||||
当前 TRS 系统已在 QuotaMonitorService 中接入第一版风控引擎,用于在交易关键
|
||||
时点执行可配置规则判断。当前目标不是一次性做成最终版,而是在最小可运行链路
|
||||
跑通后,逐步演进为可由前端配置、后端预编译、执行期直接命中的正式版本。
|
||||
|
||||
【当前实现口径】(以本注释和实际代码为准)
|
||||
|
||||
核心概念:
|
||||
- RiskRule(风控规则):规则定义本体,当前重点字段包括 Id、RuleName、
|
||||
RuleText、RuleExpr、Version、CompiledScript。
|
||||
- RiskRuleApplication(规则应用):与规则分离,承载启用状态、控制策略、触发时点、
|
||||
适用范围(全局 / 账户 / 客户 / 标的类型 / 合约类型)。
|
||||
- RuleExpr:当前唯一主编译入口。要求内容是 Roslyn 可直接执行的 C# bool 表达式,
|
||||
例如直接访问 DataMap["trade"] 后做数值或日期比较。
|
||||
- ConditionJson:当前已在规则定义中保留,但不参与主执行链路。
|
||||
- RiskContext:一次风控检查的数据上下文,包含 TradeId、TriggerPoint 和 DataMap。
|
||||
- RuleCompiledCache:进程内编译结果缓存,按规则 Id 缓存 Func<RiskContext, bool>。
|
||||
|
||||
当前编译流程:
|
||||
1. 外部准备好规则对象,在 RuleExpr 中直接写最终可执行表达式
|
||||
2. 调用 RuleCompiler.ValidateAndCompileRule(rule)
|
||||
3. 内部使用 Roslyn 编译 RuleExpr,生成 Func<RiskContext, bool>
|
||||
4. 编译成功后写入 rule.CompiledScript,并同步写入 RuleCompiledCache
|
||||
5. 执行阶段优先从 RuleCompiledCache 取委托执行
|
||||
|
||||
当前执行流程(EvaluateRisk):
|
||||
1. 从数据库加载规则列表和应用列表
|
||||
2. 按应用状态、TriggerPoints 过滤有效应用
|
||||
3. 按应用范围过滤交易是否命中(全局 / 账户 / 客户 / 标的类型 / 合约类型)
|
||||
4. 根据应用配置中的 RuleIds 找到对应规则 Id 并关联规则
|
||||
5. 优先从 RuleCompiledCache 读取已编译委托,未命中时兜底编译一次
|
||||
6. 执行规则委托,按 ControlStrategy 聚合为 Blocked / NeedApproval / Warnings
|
||||
7. 返回 RiskResult
|
||||
|
||||
当前维度匹配规则:
|
||||
- 全局:ScopeIsGlobal=true 时直接命中
|
||||
- 同一维度内多选:并集(OR)
|
||||
- 不同维度之间:交集(AND)
|
||||
- 某维度留空:视为该维度不限制
|
||||
|
||||
【与早期方案的主要差异】
|
||||
- 当前不是 Content 解析或表达式树主导,而是 RuleExpr 直编译主导
|
||||
- RiskRule 与 RiskRuleApplication 当前仍是分离模型,没有合并
|
||||
- 编译器文件已放入 RiskEngine/Compile 目录下
|
||||
- 当前已引入 RuleCompileResult、RuleCompiledCache,用于校验结果与进程内缓存
|
||||
- Rule2 这类“左值与右值都来自对象字段”的规则,当前通过 RuleExpr 直接表达
|
||||
|
||||
【当前代码结构】
|
||||
风控引擎层:YLErpDAL/Modules/RiskEngine/
|
||||
- RiskEngineService.cs:执行入口,负责规则筛选、应用过滤、委托执行、结果聚合
|
||||
- RiskRule.cs:规则定义模型,含 CompiledScript 运行时字段
|
||||
- RiskRuleApplication.cs:规则应用模型,承载策略、触发点和适用范围
|
||||
- RiskContext.cs / RiskResult.cs:执行上下文与结果模型
|
||||
|
||||
编译相关:YLErpDAL/Modules/RiskEngine/Compile/
|
||||
- RuleCompiler.cs:Roslyn 编译入口,提供 ValidateAndCompileFormula / ValidateAndCompileRule
|
||||
- RuleCompileResult.cs:编译结果模型
|
||||
- RuleCompiledCache.cs:编译结果缓存
|
||||
|
||||
当前集成点:
|
||||
- QuotaMonitorService.cs:构造 RiskContext,并将 trade 对象放入 DataMap["trade"]
|
||||
|
||||
【当前进度】(截至 2026-06-24)
|
||||
✅ 已完成:
|
||||
1. RiskEngine 第一版执行链路已跑通:QuotaMonitorService -> RiskEngineService -> RuleCompiler
|
||||
2. 风控上下文通过 DataMap 传入 trade 对象,支持规则脚本直接访问交易字段
|
||||
3. RuleExpr 直编译方案已接入,支持数值比较和日期比较
|
||||
4. Application 通用维度匹配已支持:全局 / 账户 / 客户 / 标的类型 / 合约类型
|
||||
5. 维度组合逻辑已按文档确认:同维度 OR,不同维度 AND
|
||||
6. RuleCompiler 已支持校验 + 编译 + 写缓存
|
||||
7. RuleCompiledCache / RuleCompileResult 已落地到 Compile 目录
|
||||
8. RiskEngineService 已改为执行时优先从 RuleCompiledCache 读取委托
|
||||
|
||||
【待办事项 / TODO】
|
||||
⬜ 1. 接入真实规则来源
|
||||
- 由数据库或前端提交替换当前 LoadRules / LoadApplications 的规则来源
|
||||
⬜ 2. 增加接口层
|
||||
- 提供前端提交 RuleExpr 后的校验接口
|
||||
- 提供规则保存 / 发布后预编译并写缓存的入口
|
||||
⬜ 3. 启动预热与缓存刷新
|
||||
- 服务启动时批量加载有效规则并预编译
|
||||
- 支持规则更新后的缓存刷新 / 删除
|
||||
⬜ 4. 完善执行期策略
|
||||
- 当前保留“缓存未命中时兜底编译”逻辑
|
||||
- 后续可收紧为“执行期只读缓存,未命中按发布失败处理”
|
||||
⬜ 5. 补测试样例
|
||||
- 数值比较、日期比较、维度过滤、非法公式、边界值
|
||||
⬜ 6. 完善 RuleExpr 配套能力
|
||||
- 提供前端可用的表达式编辑、校验与错误提示
|
||||
- 约束可用变量、类型转换和脚本安全边界
|
||||
|
||||
【注意事项】
|
||||
1. 当前 RuleExpr 必须是 Roslyn 最终可执行的 C# bool 表达式,不是业务语义短句
|
||||
2. DataMap 中的值由宿主业务代码准备,编译器与执行器本身不负责查库补数
|
||||
3. 当前缓存的是 Func<RiskContext, bool>,这是规则判断函数,不是事件处理器
|
||||
4. 业务可预期失败优先走结果返回,不要把高频校验失败都设计成异常
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 风控引擎服务(第一版 — 骨架版,先跑通)
|
||||
/// </summary>
|
||||
public class RiskEngineService : YLBaseService
|
||||
{
|
||||
IYcLogger _logger = LogFactory.GetLogger("RiskEngineService");
|
||||
|
||||
private static readonly Lazy<RiskEngineService> _instance =
|
||||
new Lazy<RiskEngineService>(() => new RiskEngineService());
|
||||
|
||||
public static RiskEngineService GetInstance() => _instance.Value;
|
||||
|
||||
private RiskEngineService() : base(OptUserInfo.SystemUser)
|
||||
{
|
||||
}
|
||||
|
||||
public RiskEngineService(OptUserInfo userInfo) : base(userInfo)
|
||||
{
|
||||
}
|
||||
|
||||
public RiskEngineService(YLBaseService baseService) : base(baseService)
|
||||
{
|
||||
}
|
||||
|
||||
public RiskEngineService(OptUserInfo optUser, YLContext dbContext) : base(optUser, dbContext)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 规则内存缓存(启动预热写入,EvaluateRisk 读取)
|
||||
/// </summary>
|
||||
private static volatile List<RiskRule> _cachedRules;
|
||||
private static volatile List<RiskRuleApplication> _cachedApplications;
|
||||
private static readonly object _cacheLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// 预热:加载规则与应用到内存,并预编译所有规则到 RuleCompiledCache。
|
||||
/// 项目启动时调用一次;规则/应用更新后调用 RefreshCache 刷新。
|
||||
/// </summary>
|
||||
public void Preload()
|
||||
{
|
||||
lock (_cacheLock)
|
||||
{
|
||||
_logger.Info("[风控引擎] Preload 开始 - 加载规则与应用并预编译");
|
||||
|
||||
var rules = LoadRulesFromDb();
|
||||
var applications = LoadApplicationsFromDb();
|
||||
List<long> res = new List<long>();
|
||||
foreach(var i in applications)
|
||||
{
|
||||
if(i.Status!= RiskRuleStatus.Active)
|
||||
{
|
||||
res.Add(i.Id);
|
||||
}
|
||||
}
|
||||
// 预编译所有规则到 RuleCompiledCache
|
||||
foreach (var rule in rules)
|
||||
{
|
||||
var ruleId = rule.Id.ToString();
|
||||
if (RuleCompiledCache.TryGet(ruleId, out _))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var compileResult = RuleCompiler.ValidateAndCompileRule(rule);
|
||||
if (!compileResult.Success)
|
||||
{
|
||||
_logger.Info($"[风控引擎] 规则预编译失败 - RuleId: {rule.Id}, Error: {compileResult.ErrorMessage}");
|
||||
}
|
||||
}
|
||||
|
||||
_cachedRules = rules;
|
||||
_cachedApplications = applications;
|
||||
|
||||
_logger.Info($"[风控引擎] Preload 完成 - 规则数: {rules.Count}, 应用数: {applications.Count}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新缓存:清空已编译委托与内存缓存后重新预加载。
|
||||
/// 规则/应用配置更新后调用。
|
||||
/// </summary>
|
||||
public void RefreshCache()
|
||||
{
|
||||
_logger.Info("[风控引擎] RefreshCache 被调用 - 清空缓存并重新预加载");
|
||||
lock (_cacheLock)
|
||||
{
|
||||
_cachedRules = null;
|
||||
_cachedApplications = null;
|
||||
RuleCompiledCache.Clear();
|
||||
}
|
||||
|
||||
Preload();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从内存缓存获取规则列表;缓存为空时兜底加载并填充缓存。
|
||||
/// </summary>
|
||||
private List<RiskRule> GetRules()
|
||||
{
|
||||
var rules = _cachedRules;
|
||||
if (rules != null)
|
||||
{
|
||||
return rules;
|
||||
}
|
||||
|
||||
lock (_cacheLock)
|
||||
{
|
||||
if (_cachedRules != null)
|
||||
{
|
||||
return _cachedRules;
|
||||
}
|
||||
|
||||
var loaded = LoadRulesFromDb();
|
||||
_cachedRules = loaded;
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从内存缓存获取应用列表;缓存为空时兜底加载并填充缓存。
|
||||
/// </summary>
|
||||
private List<RiskRuleApplication> GetApplications()
|
||||
{
|
||||
var applications = _cachedApplications;
|
||||
if (applications != null)
|
||||
{
|
||||
return applications;
|
||||
}
|
||||
|
||||
lock (_cacheLock)
|
||||
{
|
||||
if (_cachedApplications != null)
|
||||
{
|
||||
return _cachedApplications;
|
||||
}
|
||||
|
||||
var loaded = LoadApplicationsFromDb();
|
||||
_cachedApplications = loaded;
|
||||
return loaded;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行风控检查(最终设计版:预编译委托 + 规则筛选 + 策略判定)
|
||||
/// </summary>
|
||||
/// <param name="context">风控上下文</param>
|
||||
/// <param name="triggerPoint">触发时点,如 BOOK_CONFIRM</param>
|
||||
/// <returns>风控结果</returns>
|
||||
public RiskResult EvaluateRisk(RiskContext context, string triggerPoint)
|
||||
{
|
||||
var result = new RiskResult();
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Info($"[风控引擎] EvaluateRisk 开始 - TradeId: {context?.TradeId}, TriggerPoint: {triggerPoint}");
|
||||
|
||||
// ============================================================
|
||||
// Step 1: 从内存缓存读取规则定义和规则应用(启动时已预热)
|
||||
// ============================================================
|
||||
var rules = GetRules();
|
||||
var applications = GetApplications();
|
||||
_logger.Info($"[风控引擎] 加载规则数: {rules.Count}, 应用数: {applications.Count}");
|
||||
|
||||
// ============================================================
|
||||
// Step 2: 先按 Application 过滤 Active 状态和 TriggerPoint 匹配的应用
|
||||
// ============================================================
|
||||
var activeApps = applications
|
||||
.Where(a => a.Status == RiskRuleStatus.Active)
|
||||
.ToList();
|
||||
var apps = activeApps
|
||||
.Where(a => !string.IsNullOrEmpty(a.TriggerPoints))
|
||||
.ToList();
|
||||
var triggerMatchedApps = apps
|
||||
.Where(a => a.TriggerPoints.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(s => s.Trim())
|
||||
.Contains(triggerPoint))
|
||||
.ToList();
|
||||
|
||||
// 再按应用范围过滤。
|
||||
// 统一走通用维度匹配:
|
||||
// 1. 全局命中时直接通过;
|
||||
// 2. 同一维度内多选按并集处理;
|
||||
// 3. 不同维度之间按交集处理;
|
||||
// 4. 某维度留空表示该维度不限制。
|
||||
var trade = context?.DataMap != null && context.DataMap.ContainsKey("trade")
|
||||
? context.DataMap["trade"] as YLErp.DBModels.trade
|
||||
: null;
|
||||
|
||||
var matchedApplications = triggerMatchedApps
|
||||
.Where(a => IsApplicationMatched(a, trade))
|
||||
.ToList();
|
||||
|
||||
_logger.Info($"[风控引擎] 匹配 TriggerPoint 的应用数: {matchedApplications.Count}");
|
||||
|
||||
// ============================================================
|
||||
// Step 3: 遍历匹配的应用,通过 RuleIds 关联规则并执行预编译委托
|
||||
// ============================================================
|
||||
foreach (var application in matchedApplications)
|
||||
{
|
||||
// ------------------------------------------------------------
|
||||
// 3.1 通过 RuleIds 关联规则定义
|
||||
// ------------------------------------------------------------
|
||||
var applicationRuleIds = ParseRuleIds(application.RuleIds);
|
||||
if (!applicationRuleIds.Any())
|
||||
{
|
||||
_logger.Info($"[风控引擎] 应用未配置有效规则 - RuleIds: {application.RuleIds}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var applicationRules = rules
|
||||
.Where(r => applicationRuleIds.Contains(r.Id) && r.Id == 3)
|
||||
.ToList();
|
||||
|
||||
var missingRuleIds = applicationRuleIds
|
||||
.Where(ruleId => applicationRules.All(r => r.Id != ruleId))
|
||||
.ToList();
|
||||
|
||||
foreach (var missingRuleId in missingRuleIds)
|
||||
{
|
||||
_logger.Info($"[风控引擎] 未找到对应规则定义 - RuleId: {missingRuleId}, ApplicationRuleIds: {application.RuleIds}");
|
||||
}
|
||||
|
||||
foreach (var rule in applicationRules)
|
||||
{
|
||||
var ruleId = rule.Id.ToString();
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 3.2 优先从编译缓存读取规则委托
|
||||
// ------------------------------------------------------------
|
||||
if (!RuleCompiledCache.TryGet(ruleId, out var compiledScript))
|
||||
{
|
||||
_logger.Info($"[风控引擎] 缓存中未命中已编译规则,执行兜底编译 - RuleId: {rule.Id}");
|
||||
|
||||
var compileResult = RuleCompiler.ValidateAndCompileRule(rule);
|
||||
if (!compileResult.Success)
|
||||
{
|
||||
_logger.Info($"[风控引擎] 规则编译失败 - RuleId: {rule.Id}, Error: {compileResult.ErrorMessage}");
|
||||
continue;
|
||||
}
|
||||
|
||||
compiledScript = compileResult.CompiledScript;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 3.3 执行预编译委托
|
||||
// ------------------------------------------------------------
|
||||
bool triggered = false;
|
||||
try
|
||||
{
|
||||
triggered = compiledScript(context);
|
||||
_logger.Info($"[风控引擎] 规则执行 - RuleId: {rule.Id}, Triggered: {triggered}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Info($"[风控引擎] 规则执行异常 - RuleId: {rule.Id}, Error: {ex.Message}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// 3.4 命中后按 Application 的控制策略聚合结果
|
||||
// ------------------------------------------------------------
|
||||
if (triggered)
|
||||
{
|
||||
_logger.Info($"[风控引擎] 规则触发 - RuleId: {rule.Id}, Strategy: {application.ControlStrategy}");
|
||||
|
||||
switch (application.ControlStrategy)
|
||||
{
|
||||
case RiskControlStrategy.Block:
|
||||
break;
|
||||
result.Blocked = true;
|
||||
result.Passed = false;
|
||||
result.TriggeredRules.Add(new TriggeredRuleInfo
|
||||
{
|
||||
RuleId = rule.Id.ToString(),
|
||||
RuleName = rule.RuleName,
|
||||
ControlStrategy = RiskControlStrategy.Block,
|
||||
RuleText = rule.RuleText,
|
||||
Message = $"规则[{rule.RuleName}]触发:禁止"
|
||||
});
|
||||
break;
|
||||
|
||||
case RiskControlStrategy.Approval:
|
||||
result.NeedApproval = true;
|
||||
result.Passed = false;
|
||||
result.TriggeredRules.Add(new TriggeredRuleInfo
|
||||
{
|
||||
RuleId = ruleId,
|
||||
RuleName = rule.RuleName,
|
||||
ControlStrategy = RiskControlStrategy.Approval,
|
||||
RuleText = rule.RuleText,
|
||||
Message = $"规则[{rule.RuleName}]触发:需审批"
|
||||
});
|
||||
break;
|
||||
|
||||
case RiskControlStrategy.ShowTip:
|
||||
result.ShowTip = true;
|
||||
result.TriggeredRules.Add(new TriggeredRuleInfo
|
||||
{
|
||||
RuleId = ruleId,
|
||||
RuleName = rule.RuleName,
|
||||
ControlStrategy = RiskControlStrategy.ShowTip,
|
||||
RuleText = rule.RuleText,
|
||||
Message = $"规则[{rule.RuleName}]触发:提示"
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
_logger.Info($"[风控引擎] 未知策略类型 - ControlStrategy: {application.ControlStrategy}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info($"[风控引擎] 规则未触发 - RuleId: {rule.Id}, TriggerPoint: {triggerPoint}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Step 4: 聚合最终结果
|
||||
// ============================================================
|
||||
if (!result.Blocked && !result.NeedApproval)
|
||||
{
|
||||
result.Passed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Passed = false;
|
||||
}
|
||||
|
||||
_logger.Info($"[风控引擎] EvaluateRisk 完成 - TradeId: {context?.TradeId}, Passed: {result.Passed}, Blocked: {result.Blocked}, NeedApproval: {result.NeedApproval}, TriggeredRules: {result.TriggeredRules.Count}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.NeedApproval = true;
|
||||
result.Passed = false;
|
||||
result.TriggeredRules.Add(new TriggeredRuleInfo
|
||||
{
|
||||
RuleId = "ENGINE_ERROR",
|
||||
RuleName = "风控引擎执行异常",
|
||||
RuleText = ex.Message,
|
||||
Message = $"风控引擎异常:{ex.Message}"
|
||||
});
|
||||
_logger.Error($"[风控引擎] EvaluateRisk 异常 - TradeId: {context?.TradeId}, Error: {ex.Message}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从数据库加载规则列表
|
||||
/// </summary>
|
||||
private List<RiskRule> LoadRulesFromDb()
|
||||
{
|
||||
return DbContext.glms_risk_rule
|
||||
.AsNoTracking()
|
||||
.Where(r => r.Status != RiskRuleStatus.Deleted)
|
||||
.OrderByDescending(r => r.UpdateDate ?? r.OptDate)
|
||||
.Select(r => new RiskRule
|
||||
{
|
||||
Id = r.id,
|
||||
RuleName = r.RuleName,
|
||||
RuleText = r.RuleText,
|
||||
ConditionJson = r.ConditionJson,
|
||||
RuleExpr = r.RuleExpr,
|
||||
Version = r.Version,
|
||||
IsDeleted = r.Status == RiskRuleStatus.Deleted,
|
||||
OptId = r.OptId ?? 0,
|
||||
OptName = r.OptName,
|
||||
OptDate = r.OptDate ?? DateTime.MinValue,
|
||||
UpdateOptId = r.UpdateOptId ?? 0,
|
||||
UpdateOptName = r.UpdateOptName,
|
||||
UpdateDate = r.UpdateDate ?? r.OptDate ?? DateTime.MinValue
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
/// <summary>
|
||||
/// 从数据库加载应用配置
|
||||
/// </summary>
|
||||
private List<RiskRuleApplication> LoadApplicationsFromDb()
|
||||
{
|
||||
return DbContext.glms_risk_rule_application
|
||||
.AsNoTracking()
|
||||
.Where(a => a.Status != RiskRuleStatus.Deleted)
|
||||
.OrderByDescending(a => a.UpdateDate ?? a.OptDate)
|
||||
.Select(a => new RiskRuleApplication
|
||||
{
|
||||
Id = a.id,
|
||||
RuleIds = a.RuleIds,
|
||||
Status = a.Status,
|
||||
ControlStrategy = a.ControlStrategy,
|
||||
TriggerPoints = a.TriggerPoints,
|
||||
ScopeIsGlobal = a.ScopeIsGlobal,
|
||||
ScopeAssetBookIds = a.ScopeAssetBookIds,
|
||||
ScopeClientIds = a.ScopeClientIds,
|
||||
ScopeUnderlyingTypes = a.ScopeUnderlyingTypes,
|
||||
ScopeTradeTypes = a.ScopeTradeTypes,
|
||||
Version = a.Version,
|
||||
OptId = a.OptId ?? 0,
|
||||
OptName = a.OptName,
|
||||
OptDate = a.OptDate ?? DateTime.MinValue,
|
||||
UpdateOptId = a.UpdateOptId ?? 0,
|
||||
UpdateOptName = a.UpdateOptName,
|
||||
UpdateDate = a.UpdateDate ?? a.OptDate ?? DateTime.MinValue
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断应用配置是否命中当前交易。
|
||||
/// 匹配规则遵循设计文档:
|
||||
/// 1. 全局命中时直接返回 true;
|
||||
/// 2. 同一维度内多选按并集处理;
|
||||
/// 3. 不同维度之间按交集处理;
|
||||
/// 4. 某维度留空表示该维度不限制。
|
||||
/// </summary>
|
||||
private bool IsApplicationMatched(RiskRuleApplication application, YLErp.DBModels.trade trade)
|
||||
{
|
||||
if (application == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (application.ScopeIsGlobal == 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (trade == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var accountMatched = IsScopeEmpty(application.ScopeAssetBookIds) || IsValueMatched(application.ScopeAssetBookIds, GetTradeAssetBookId(trade));
|
||||
var clientMatched = IsScopeEmpty(application.ScopeClientIds) || IsValueMatched(application.ScopeClientIds, trade.ClientId);
|
||||
var underlyingTypeMatched = IsScopeEmpty(application.ScopeUnderlyingTypes) || IsValueMatched(application.ScopeUnderlyingTypes, GetTradeUnderlyingType(trade));
|
||||
var tradeTypeMatched = IsScopeEmpty(application.ScopeTradeTypes) || IsValueMatched(application.ScopeTradeTypes, trade.TradeType);
|
||||
|
||||
return accountMatched
|
||||
&& clientMatched
|
||||
&& underlyingTypeMatched
|
||||
&& tradeTypeMatched;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析应用配置中的规则ID列表。
|
||||
/// 多个规则ID使用逗号分隔,返回去空格后的 long 集合。
|
||||
/// </summary>
|
||||
private List<long> ParseRuleIds(string ruleIds)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ruleIds))
|
||||
{
|
||||
return new List<long>();
|
||||
}
|
||||
|
||||
var ids = new List<long>();
|
||||
foreach (var part in ruleIds.Split(',', StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (long.TryParse(part.Trim(), out long id))
|
||||
{
|
||||
ids.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断某个范围字段是否为空。
|
||||
/// 为空表示该维度不限制。
|
||||
/// </summary>
|
||||
private bool IsScopeEmpty(string scopeValue)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(scopeValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断单个值是否命中逗号分隔的范围配置。
|
||||
/// 同一维度内多选按并集处理,只要命中任一值即返回 true。
|
||||
/// </summary>
|
||||
private bool IsValueMatched(string scopeValue, object currentValue)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(scopeValue))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (currentValue == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentText = currentValue.ToString()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(currentText))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return scopeValue
|
||||
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(s => s.Trim())
|
||||
.Any(s => string.Equals(s, currentText, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取交易的资产簿账户ID。
|
||||
/// 当前先按 BookId 取值;如果后续真实字段不是 BookId,再统一调整这里即可。
|
||||
/// </summary>
|
||||
private object GetTradeAssetBookId(YLErp.DBModels.trade trade)
|
||||
{
|
||||
var property = trade.GetType().GetProperty("BookId");
|
||||
return property?.GetValue(trade);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取交易的标的类型。
|
||||
/// 当前先按 UnderlyingInstrumentType 取值;如果后续真实字段名不同,再统一调整这里即可。
|
||||
/// </summary>
|
||||
private object GetTradeUnderlyingType(YLErp.DBModels.trade trade)
|
||||
{
|
||||
var property = trade.GetType().GetProperty("UnderlyingInstrumentType");
|
||||
return property?.GetValue(trade);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 风控结果
|
||||
/// </summary>
|
||||
public class RiskResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否全部通过
|
||||
/// </summary>
|
||||
public bool Passed { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 是否被禁止
|
||||
/// </summary>
|
||||
public bool Blocked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否需要审批
|
||||
/// </summary>
|
||||
public bool NeedApproval { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否存在提示
|
||||
/// </summary>
|
||||
public bool ShowTip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发的规则列表
|
||||
/// </summary>
|
||||
public List<TriggeredRuleInfo> TriggeredRules { get; set; } = new List<TriggeredRuleInfo>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发规则详情
|
||||
/// </summary>
|
||||
public class TriggeredRuleInfo
|
||||
{
|
||||
public string RuleId { get; set; }
|
||||
public string RuleName { get; set; }
|
||||
public RiskControlStrategy ControlStrategy { get; set; }
|
||||
public string RuleText { get; set; }
|
||||
public string Message { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 风控规则定义。
|
||||
/// 只描述“规则是什么”,不包含状态、策略、触发时点、适用范围等应用配置。
|
||||
/// 这些执行维度由 RiskRuleApplication 承载。
|
||||
/// </summary>
|
||||
public class RiskRule
|
||||
{
|
||||
// === 基础信息 ===
|
||||
public long Id { get; set; }
|
||||
public string RuleName { get; set; }
|
||||
public string RuleText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 【核心】条件JSON(结构化模式的条件列表存储),如
|
||||
/// {"conditions":[{"variableId":1,"operator":">","value":100000000}]}
|
||||
/// 由 RuleCompiler 解析并编译为 CompiledScript
|
||||
/// </summary>
|
||||
public string ConditionJson { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 【核心】规则表达式(自由文本模式,类C#表达式)
|
||||
/// 由 RuleCompiler 编译为 CompiledScript
|
||||
/// </summary>
|
||||
public string RuleExpr { get; set; }
|
||||
|
||||
// === 生命周期 ===
|
||||
public int Version { get; set; }
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
// === 审计字段 ===
|
||||
public int OptId { get; set; }
|
||||
public string OptName { get; set; }
|
||||
public DateTime OptDate { get; set; }
|
||||
public int UpdateOptId { get; set; }
|
||||
public string UpdateOptName { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
|
||||
// === 运行时内存字段(不持久化到数据库)===
|
||||
/// <summary>
|
||||
/// 【核心】预编译的可执行委托
|
||||
/// 在规则创建/加载时由 RuleCompiler.Compile(this) 生成
|
||||
/// 判风控时直接调用:rule.CompiledScript(context) → bool
|
||||
/// </summary>
|
||||
public Func<RiskContext, bool> CompiledScript { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
using System;
|
||||
using YLErp.DBModels;
|
||||
|
||||
namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// 风控规则应用配置。
|
||||
///
|
||||
/// 设计原因:
|
||||
/// 依据设计文档,风控规则需要区分“规则定义”和“规则应用”两个层面。
|
||||
/// RiskRule 负责定义“规则是什么”,例如规则名称、规则编码、公式表达式、描述、版本等;
|
||||
/// RiskRuleApplication 负责定义“规则在什么场景下如何执行”,例如启用状态、校验策略、触发时点、适用范围。
|
||||
///
|
||||
/// 拆分后的好处是:
|
||||
/// 1. 同一条规则可以被多个应用配置复用,避免重复维护相同的公式定义。
|
||||
/// 2. 不同业务场景可以对同一条规则配置不同的执行策略,例如在簿记确认时禁止,在平仓审核时提示。
|
||||
/// 3. 调整触发时点、适用范围、控制策略时,不需要修改规则本身,降低配置耦合。
|
||||
/// 4. 后续如果要做规则管理页面、规则启停、按场景灰度投放,也更容易扩展。
|
||||
///
|
||||
/// 当前文件先定义第一版最小模型,用于支撑基础流程跑通和示例数据加载。
|
||||
/// </summary>
|
||||
public class RiskRuleApplication
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用配置主键ID。
|
||||
/// 用于唯一标识一条规则应用记录。
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 关联的规则ID列表。
|
||||
/// 通过该字段与 RiskRule.Id 关联,多个规则ID使用逗号分隔。
|
||||
/// </summary>
|
||||
|
||||
public string RuleIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 应用状态。
|
||||
/// 约定:
|
||||
/// 1 = Active(已生效)
|
||||
/// 2 = Disabled(已停用)
|
||||
/// 3 = Deleted(已删除)
|
||||
/// 在实际执行时,通常只加载 Active 状态的应用配置。
|
||||
/// </summary>
|
||||
public RiskRuleStatus Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 校验策略。
|
||||
/// 约定:
|
||||
/// 1 = 禁止
|
||||
/// 2 = 审批
|
||||
/// 3 = 提示
|
||||
/// 当规则命中时,由该字段决定最终处理方式。
|
||||
/// </summary>
|
||||
public RiskControlStrategy ControlStrategy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 触发时点。
|
||||
/// 多个时点使用逗号分隔,例如:
|
||||
/// BOOK_CONFIRM,CLOSE_REVIEW
|
||||
/// 表示该应用配置会在这些业务时点参与风控判断。
|
||||
/// </summary>
|
||||
public string TriggerPoints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否全局适用。
|
||||
/// true 表示对所有交易都适用,此时通常忽略其他 Scope 字段;
|
||||
/// false 表示只在指定范围内适用,需要结合下方各 Scope 字段进行过滤。
|
||||
/// </summary>
|
||||
public int ScopeIsGlobal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 适用的资产簿记账户范围。
|
||||
/// 第一版使用逗号分隔的字符串保存,例如:
|
||||
/// 123,456,789
|
||||
/// 后续执行时可按约定解析为账户ID集合。
|
||||
/// </summary>
|
||||
public string ScopeAssetBookIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 适用的客户范围。
|
||||
/// 第一版使用逗号分隔的字符串保存客户ID,例如:
|
||||
/// 10001,10002
|
||||
/// 用于在执行前筛选该规则是否适用于当前客户。
|
||||
/// </summary>
|
||||
public string ScopeClientIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 适用的标的类型范围。
|
||||
/// 例如:
|
||||
/// 股票,ETF,债券
|
||||
/// 用于控制规则仅对特定标的类型生效。
|
||||
/// </summary>
|
||||
public string ScopeUnderlyingTypes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 适用的交易类型范围。
|
||||
/// 例如:
|
||||
/// 簿记交易,平仓交易
|
||||
/// 用于控制规则仅在指定交易类型下生效。
|
||||
/// </summary>
|
||||
public string ScopeTradeTypes { get; set; }
|
||||
|
||||
public int Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建人ID。
|
||||
/// 记录是谁创建了这条应用配置。
|
||||
/// </summary>
|
||||
public int OptId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建人名称。
|
||||
/// 便于界面展示和审计追踪。
|
||||
/// </summary>
|
||||
public string OptName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 创建时间。
|
||||
/// 记录应用配置的创建时刻。
|
||||
/// </summary>
|
||||
public DateTime OptDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后更新人ID。
|
||||
/// 记录最近一次修改该应用配置的操作人。
|
||||
/// </summary>
|
||||
public int UpdateOptId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后更新人名称。
|
||||
/// 便于界面展示和审计追踪。
|
||||
/// </summary>
|
||||
public string UpdateOptName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后更新时间。
|
||||
/// 记录最近一次修改该应用配置的时间。
|
||||
/// </summary>
|
||||
public DateTime UpdateDate { get; set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -50,7 +50,6 @@ using YLErp.Modules.TradeDalModule;
|
||||
using YLErp.Modules.TradeModule;
|
||||
using YLErp.Modules.TradeModule.DealModule;
|
||||
using YLErp.QdpModule;
|
||||
using YLErp.Modules.RiskEngine;
|
||||
using static YLErp.ConsGlobal;
|
||||
|
||||
namespace YLErp.Modules.RiskModule
|
||||
@@ -5140,64 +5139,6 @@ namespace YLErp.Modules.RiskModule
|
||||
result.QuotaWarningDetails = quotaWarningMsg ?? "";
|
||||
result.AvailableForClient = availableMsg ?? "";
|
||||
result.TrialSource = trialSource;
|
||||
|
||||
// ===== 新风控引擎接入点(设计文档 4.6.1) =====
|
||||
try
|
||||
{
|
||||
var riskEngine = new RiskEngineService(this);
|
||||
var riskContext = new RiskContext
|
||||
{
|
||||
TradeId = tradeId,
|
||||
TriggerPoint = "BOOK_CONFIRM"
|
||||
};
|
||||
// 构造 DataMap(第一版只塞 trade 对象,后续按需扩展)
|
||||
riskContext.DataMap["trade"] = tradeObj;
|
||||
var riskResult = riskEngine.EvaluateRisk(riskContext, "BOOK_CONFIRM");
|
||||
|
||||
_logger.Info($"[风控引擎] 簿记交易确认 - TradeId: {tradeId}, Passed: {riskResult.Passed}, Blocked: {riskResult.Blocked}, NeedApproval: {riskResult.NeedApproval}, ShowTip: {riskResult.ShowTip}");
|
||||
|
||||
// 按策略映射回 QuotaTrialStatusEnum
|
||||
if (riskResult.Blocked)
|
||||
{
|
||||
result.TrialStatus = QuotaTrialStatusEnum.Error;
|
||||
result.RiskWarningDetails += "[风控引擎] 规则触发:禁止\n";
|
||||
foreach (var triggeredRule in riskResult.TriggeredRules.Where(r => r.ControlStrategy == RiskControlStrategy.Block))
|
||||
{
|
||||
result.RiskWarningDetails += $"规则ID:{triggeredRule.RuleId};规则名称:{triggeredRule.RuleName};规则说明:{triggeredRule.RuleText}\n";
|
||||
}
|
||||
}
|
||||
if (riskResult.NeedApproval)
|
||||
{
|
||||
if (result.TrialStatus != QuotaTrialStatusEnum.Error)
|
||||
{
|
||||
result.TrialStatus = QuotaTrialStatusEnum.Warning;
|
||||
}
|
||||
result.RiskWarningDetails += "[风控引擎] 规则触发:需审批\n";
|
||||
foreach (var triggeredRule in riskResult.TriggeredRules.Where(r => r.ControlStrategy == RiskControlStrategy.Approval))
|
||||
{
|
||||
result.RiskWarningDetails += $"规则ID:{triggeredRule.RuleId};规则名称:{triggeredRule.RuleName};规则说明:{triggeredRule.RuleText}\n";
|
||||
}
|
||||
}
|
||||
if (riskResult.ShowTip)
|
||||
{
|
||||
var warningMessages = riskResult.TriggeredRules
|
||||
.Where(r => r.ControlStrategy == RiskControlStrategy.ShowTip)
|
||||
.Select(r => r.Message)
|
||||
.Where(r => !string.IsNullOrWhiteSpace(r))
|
||||
.ToList();
|
||||
if (warningMessages.Count > 0)
|
||||
{
|
||||
result.RiskWarningDetails += "[风控引擎] 提示:" + string.Join(";", warningMessages) + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"[风控引擎] 执行异常 - TradeId: {tradeId}, Error: {ex.Message}");
|
||||
// 第一版:异常不阻断原有流程,只记录日志
|
||||
}
|
||||
// ===== 新风控引擎接入结束 =====
|
||||
|
||||
_logger.Info($"[限额试算] 试算完成 - tradeId: {tradeId}, TrialStatus: {result.TrialStatus}, FundCheck: {fundStatus}, QuotaCheck: {quotaStatus}");
|
||||
SaveQuotaTrial(result);
|
||||
return result;
|
||||
|
||||
@@ -254,6 +254,9 @@ namespace YLErp.Modules.SwapModule
|
||||
unwindData.PayDate = QdpCalendarHelper.GetNonHoliday(unwindData.UnwindDate.Value.AddDays(td.trade_extend.ExtendObj.SettlementRules));
|
||||
floatEvent.PayDate = unwindData.PayDate;
|
||||
floatEvent.SwapTradeId = tradeId;
|
||||
floatEvent.SwapTradeNo = td.TradeNumber;
|
||||
floatEvent.EventType = (int)SwapFlowEventTypeEnum.互换;
|
||||
floatEvent.EventReason = "交易";
|
||||
unwindData.SwapTradeId = tradeId;
|
||||
unwindData.StructureType = td.StructureType;
|
||||
unwindData.NotionalValue = Convert.ToDecimal(td.OriginalStockEqvNotional ?? 0);
|
||||
@@ -265,8 +268,6 @@ namespace YLErp.Modules.SwapModule
|
||||
unwindData.CloseNotionalValue = unwindData.PosiNotionalValue;
|
||||
if (position != null)
|
||||
{
|
||||
floatEvent.EventType = (int)SwapEventTypeEnum.互换;
|
||||
floatEvent.EventReason = "交易";
|
||||
floatEvent.PositionId = position.PositionId;
|
||||
floatEvent.DividendIn = 0;
|
||||
floatEvent.UnderlyingCode = position.UnderlyingCode;
|
||||
@@ -1619,6 +1620,11 @@ namespace YLErp.Modules.SwapModule
|
||||
/// <param name="eventType"></param>
|
||||
private long SaveSwapDeal(UnwindData unwindData, int eventType, int clientCashId, string eventResason = "", bool approve = false)
|
||||
{
|
||||
var td = DbContext.trade.Find(unwindData.SwapTradeId);
|
||||
if (td == null)
|
||||
{
|
||||
throw new ServiceException("未找到交易信息");
|
||||
}
|
||||
var flowList = new List<swap_flow_event>(unwindData.FlowEvents);
|
||||
unwindData.FlowEvents.Clear();
|
||||
string data = JsonConvert.SerializeObject(unwindData);
|
||||
@@ -1633,7 +1639,7 @@ namespace YLErp.Modules.SwapModule
|
||||
item.PayDate = unwindData.PayDate;
|
||||
item.UnwindDate = unwindData.UnwindDate;
|
||||
item.EventDate = unwindData.ValueDate;
|
||||
item.EventId = swapEvent.id;
|
||||
FillSwapFlowEvent(item, unwindData, td, eventType, swapEvent.id);
|
||||
DbContext.swap_flow_event.Add(item);
|
||||
}
|
||||
if (!approve)
|
||||
@@ -1641,8 +1647,25 @@ namespace YLErp.Modules.SwapModule
|
||||
UpdateInitalPosition(flowList, unwindData, eventType);
|
||||
}
|
||||
DbContext.SaveChanges();
|
||||
var savedFlowEvents = DbContext.swap_flow_event.Where(x => x.EventId == swapEvent.id).ToList();
|
||||
foreach (var item in savedFlowEvents)
|
||||
{
|
||||
FillSwapFlowEvent(item, unwindData, td, eventType, swapEvent.id);
|
||||
}
|
||||
DbContext.SaveChanges();
|
||||
return swapEvent.id;
|
||||
}
|
||||
|
||||
private void FillSwapFlowEvent(swap_flow_event item, UnwindData unwindData, trade td, int eventType, long eventId)
|
||||
{
|
||||
item.EventId = eventId;
|
||||
item.SwapTradeId = unwindData.SwapTradeId;
|
||||
item.SwapTradeNo = td.TradeNumber;
|
||||
item.EventType = eventType;
|
||||
item.EventReason = string.IsNullOrWhiteSpace(item.EventReason) ? "交易" : item.EventReason;
|
||||
UpdateDbOption(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算平仓数据
|
||||
/// </summary>
|
||||
|
||||
@@ -8,9 +8,9 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule
|
||||
/// <summary>
|
||||
/// 国贸交易确认书编号生成器
|
||||
/// 规则:
|
||||
/// - 对客交易(OpponentRole为"乙方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-{当日第N笔对客交易(数字递增)}-{标的代码},从01开始
|
||||
/// - 对客交易(OpponentRole为"甲方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-FICC-{当日第N笔对客交易(数字递增)}-{标的代码},从01开始
|
||||
/// 例:GLMS-IS-20260424-01-250210IB
|
||||
/// - 非对客交易(OpponentRole为"甲方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-{当日第N笔非对客交易使用字母递增}-{标的代码},从A开始
|
||||
/// - 非对客交易(OpponentRole为"乙方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-FICC-{当日第N笔非对客交易使用字母递增}-{标的代码},从A开始
|
||||
/// 例:GLMS-IS-20260424-A-250210IB
|
||||
/// </summary>
|
||||
public class GuolianContractNoGenerator
|
||||
@@ -29,8 +29,8 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule
|
||||
trade trade,
|
||||
string clientCode)
|
||||
{
|
||||
// 根据trade的OpponentRole判断是否为对客交易(乙方=对客)
|
||||
var isClientTrade = trade.OpponentRole == "乙方";
|
||||
// 根据trade的OpponentRole判断是否为对客交易(甲方=对客)。glms客户规定甲方=对客
|
||||
var isClientTrade = trade.OpponentRole == "甲方";
|
||||
var underlyingCode = (trade.UnderlyingCode ?? "").Replace(".", ""); // 去掉标的代码中的点号
|
||||
var tradeDate = trade.TradeDate ?? DateTime.MinValue;
|
||||
var tradeDateStr = tradeDate.ToString("yyyyMMdd");
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="FluentFTP" Version="45.2.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.12.0" />
|
||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.10.0" />
|
||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
||||
<PackageReference Include="Oracle.EntityFrameworkCore" Version="6.21.90" />
|
||||
@@ -42,7 +40,7 @@
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.10.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.6.0" />
|
||||
<PackageReference Include="Qdp.Pricing.Library.Options" Version="1.0.5" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
|
||||
<PackageReference Include="YLErp.Office" Version="1.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Hosting.Server.Features;
|
||||
using YLErp.DBModels.Consts;
|
||||
using YLErp.Modules.AppModule;
|
||||
using YLErp.Modules.EodModule.SettlementModule;
|
||||
using YLErp.Modules.RiskEngine;
|
||||
using YLErp.Modules.RiskModule;
|
||||
using YLErp.Modules.SuperviseReportModule.SAC.Service;
|
||||
using YLErp.Modules.TradeRiskCalcModule;
|
||||
@@ -125,18 +124,6 @@ namespace YLErp.Web.App
|
||||
PS.SetConfig(ConsAppConfig.YLErpWebUrlConfig, address);
|
||||
}
|
||||
|
||||
// 预热风控引擎:加载规则与应用到内存,并预编译所有规则
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
RiskEngineService.GetInstance().Preload();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogFactory.GetLogger("HostedTaskService").Error("[风控引擎] 启动预热失败", ex);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
|
||||
@@ -1,125 +1,2 @@
|
||||
var main = main || {};
|
||||
main.formatOptions={
|
||||
"trading": {
|
||||
"umprice": {
|
||||
"precision": 9,
|
||||
"grouping": true,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 9,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"umpriceP": {
|
||||
"percent": true,
|
||||
"precision": 2,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"umpricePR": {
|
||||
"precision": 4,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 4,
|
||||
"maxDecimals": 2
|
||||
},
|
||||
"tradeSinglePrice": {
|
||||
"precision": 2,
|
||||
"grouping": true,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"premiumRateP": {
|
||||
"percent": true,
|
||||
"precision": 2,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"premiumRate": {
|
||||
"precision": 4,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 4,
|
||||
"maxDecimals": 2
|
||||
},
|
||||
"tradePrice": {
|
||||
"precision": 2,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"StockEqvNotional": {
|
||||
"precision": 2,
|
||||
"grouping": true,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"notional": {
|
||||
"precision": 2,
|
||||
"grouping": true,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"notionalP": {
|
||||
"percent": true,
|
||||
"precision": 2,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"volatility": {
|
||||
"precision": 4,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 4,
|
||||
"maxDecimals": 2
|
||||
},
|
||||
"volatilityP": {
|
||||
"percent": true,
|
||||
"precision": 2,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"greek": {
|
||||
"precision": 2,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"marginRateP": {
|
||||
"percent": true,
|
||||
"precision": 2,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"minDecimals": 2,
|
||||
"maxDecimals": 0
|
||||
},
|
||||
"marginRate": {
|
||||
"precision": 4,
|
||||
"grouping": false,
|
||||
"rounded": true,
|
||||
"percent": false,
|
||||
"minDecimals": 4,
|
||||
"maxDecimals": 2
|
||||
}
|
||||
}
|
||||
};
|
||||
main.formatOptions = { "trading": { "umprice": { "trimTailZeros": true, "precision": 9, "grouping": true, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "umpriceP": { "trimTailZeros": true, "percent": true, "precision": 9, "grouping": false, "rounded": true, "minDecimals": 2, "maxDecimals": 9 }, "umpricePR": { "trimTailZeros": true, "precision": 9, "grouping": false, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "tradeSinglePrice": { "trimTailZeros": true, "precision": 9, "grouping": true, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "premiumRateP": { "trimTailZeros": true, "percent": true, "precision": 9, "grouping": false, "rounded": true, "minDecimals": 2, "maxDecimals": 9 }, "premiumRate": { "trimTailZeros": true, "precision": 9, "grouping": false, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "tradePrice": { "trimTailZeros": true, "precision": 9, "grouping": false, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "StockEqvNotional": { "trimTailZeros": true, "precision": 9, "grouping": true, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "notional": { "trimTailZeros": true, "precision": 9, "grouping": true, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "notionalP": { "trimTailZeros": true, "percent": true, "precision": 9, "grouping": false, "rounded": true, "minDecimals": 2, "maxDecimals": 9 }, "volatility": { "trimTailZeros": true, "precision": 9, "grouping": false, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "volatilityP": { "trimTailZeros": true, "percent": true, "precision": 9, "grouping": false, "rounded": true, "minDecimals": 2, "maxDecimals": 9 }, "greek": { "trimTailZeros": true, "precision": 9, "grouping": false, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 }, "marginRateP": { "trimTailZeros": true, "percent": true, "precision": 9, "grouping": false, "rounded": true, "minDecimals": 2, "maxDecimals": 9 }, "marginRate": { "trimTailZeros": true, "precision": 9, "grouping": false, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 9 } } };
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Functions>
|
||||
<FunctionParent Name="报价管理" Title="报价管理">
|
||||
<FunctionSub Name="结构化交易定价" Title="期权定价"></FunctionSub>
|
||||
@@ -10,20 +10,19 @@
|
||||
</FunctionParent>
|
||||
<FunctionParent Name="交易管理" Title="交易管理">
|
||||
<FunctionSub Name="交易搜索" Title="期权交易"></FunctionSub>
|
||||
<FunctionSub Name="查看所有交易" Title="查看所有交易" Type="Operate"
|
||||
Note="是否可以查看所有交易,没有这个权限在交易列表中只能看到自己所在的簿记账户的交易"></FunctionSub>
|
||||
<FunctionSub Name="交易新增" Title="交易新增" Type="Operate" Note="是否有新增交易权限"></FunctionSub>
|
||||
<FunctionSub Name="交易编辑" Title="交易编辑" Type="Operate" Note="是否有交易编辑权限"></FunctionSub>
|
||||
<FunctionSub Name="交易删除" Title="交易删除" Type="Operate" Note="是否有交易删除权限"></FunctionSub>
|
||||
<FunctionSub Name="新增选择交易员" Title="新增交易选择交易员" Type="Operate" Note="新增交易时候是否可以选择自己以外的其他交易员"></FunctionSub>
|
||||
<FunctionSub Name="交易导入" Title="交易导入" Type="Operate" Note="是否显示交易导入按钮"></FunctionSub>
|
||||
<FunctionSub Name="交易导出" Title="交易导出" Type="Operate" Note="是否有交易导出权限"></FunctionSub>
|
||||
<FunctionSub Name="交易平仓" Title="交易平仓" Type="Operate" Note="是否有交易平仓权限"></FunctionSub>
|
||||
<FunctionSub Name="收益结算与展期" Title="收益结算与展期" Type="Operate" Note="是否有收益结算和展期的权限"></FunctionSub>
|
||||
<FunctionSub Name="互换开平仓事件流水" Title="互换开平仓事件流水"></FunctionSub>
|
||||
<FunctionSub Name="交易审批" Title="交易审批"></FunctionSub>
|
||||
<FunctionSub Name="交易平仓审核" Title="交易平仓审核" Type="Operate" Note="是否有平仓审核权限"></FunctionSub>
|
||||
<FunctionSub Name="交易行权审核" Title="交易行权审核" Type="Operate" Note="是否有行权审核权限"></FunctionSub>
|
||||
<FunctionSub Name="查看所有交易" Title="查看所有交易" Type="Operate" Note="是否可以查看所有交易,没有这个权限在交易列表中只能看到自己所在的簿记账户的交易" ></FunctionSub>
|
||||
<FunctionSub Name="交易新增" Title="交易新增" Type="Operate" Note="是否有新增交易权限" ></FunctionSub>
|
||||
<FunctionSub Name="交易编辑" Title="交易编辑" Type="Operate" Note="是否有交易编辑权限" ></FunctionSub>
|
||||
<FunctionSub Name="交易删除" Title="交易删除" Type="Operate" Note="是否有交易删除权限" ></FunctionSub>
|
||||
<FunctionSub Name="新增选择交易员" Title="新增交易选择交易员" Type="Operate" Note="新增交易时候是否可以选择自己以外的其他交易员" ></FunctionSub>
|
||||
<FunctionSub Name="交易导入" Title="交易导入" Type="Operate" Note="是否显示交易导入按钮" ></FunctionSub>
|
||||
<FunctionSub Name="交易导出" Title="交易导出" Type="Operate" Note="是否有交易导出权限" ></FunctionSub>
|
||||
<FunctionSub Name="交易平仓" Title="交易平仓" Type="Operate" Note="是否有交易平仓权限" ></FunctionSub>
|
||||
<FunctionSub Name="收益结算与展期" Title="收益结算与展期" Type="Operate" Note="是否有收益结算和展期的权限" ></FunctionSub>
|
||||
<FunctionSub Name="互换开平仓事件流水" Title="互换开平仓事件流水" ></FunctionSub>
|
||||
<FunctionSub Name="交易审批" Title="交易审批" ></FunctionSub>
|
||||
<FunctionSub Name="交易平仓审核" Title="交易平仓审核" Type="Operate" Note="是否有平仓审核权限" ></FunctionSub>
|
||||
<FunctionSub Name="交易行权审核" Title="交易行权审核" Type="Operate" Note="是否有行权审核权限" ></FunctionSub>
|
||||
<FunctionSub Name="交易回退" Title="交易回退" Type="Operate" Note="系统内任意状态的交易允许回退"></FunctionSub>
|
||||
<FunctionSub Name="特批批量确认" Title="特批批量确认" Type="Operate" Note="批量确认,跳过交易时间和资金的卡控"></FunctionSub>
|
||||
<FunctionSub Name="交易操作历史" Title="交易操作历史" Type="Operate" Note="交易操作历史"></FunctionSub>
|
||||
@@ -31,13 +30,13 @@
|
||||
<FunctionSub Name="标的交易" Title="标的交易" Note="股票期货"></FunctionSub>
|
||||
<FunctionSub Name="交易流水查看" Type="Operate" Title="交易流水查看"></FunctionSub>
|
||||
<FunctionSub Name="交易流水修改" Type="Operate" Title="交易流水修改"></FunctionSub>
|
||||
<FunctionSub Name="交易标签调整权限" Title="交易标签调整权限" Type="Operate" Note="交易上打标签、移除标签、批量打标签"></FunctionSub>
|
||||
<FunctionSub Name="交易标签查看权限" Title="交易标签查看权限" Type="Operate" Note="是否可以查看交易上的标签"></FunctionSub>
|
||||
<FunctionSub Name="标的交易新增" Title="标的交易新增" Type="Operate" Note="是否有新增标的交易权限"></FunctionSub>
|
||||
<FunctionSub Name="标的交易编辑" Title="标的交易编辑" Type="Operate" Note="是否有标的交易编辑权限"></FunctionSub>
|
||||
<FunctionSub Name="标的交易删除" Title="标的交易删除" Type="Operate" Note="是否有标的交易删除权限"></FunctionSub>
|
||||
<FunctionSub Name="标的交易持仓重置" Title="标的交易持仓重置" Type="Operate" Note="是否有标的交易持仓重置权限"></FunctionSub>
|
||||
<FunctionSub Name="偏移设置" Title="偏移设置" Type="Operate" Note="X-Bond行情报价添加偏移设置"></FunctionSub>
|
||||
<FunctionSub Name="交易标签调整权限" Title="交易标签调整权限" Type="Operate" Note="交易上打标签、移除标签、批量打标签" ></FunctionSub>
|
||||
<FunctionSub Name="交易标签查看权限" Title="交易标签查看权限" Type="Operate" Note="是否可以查看交易上的标签" ></FunctionSub>
|
||||
<FunctionSub Name="标的交易新增" Title="标的交易新增" Type="Operate" Note="是否有新增标的交易权限" ></FunctionSub>
|
||||
<FunctionSub Name="标的交易编辑" Title="标的交易编辑" Type="Operate" Note="是否有标的交易编辑权限" ></FunctionSub>
|
||||
<FunctionSub Name="标的交易删除" Title="标的交易删除" Type="Operate" Note="是否有标的交易删除权限" ></FunctionSub>
|
||||
<FunctionSub Name="标的交易持仓重置" Title="标的交易持仓重置" Type="Operate" Note="是否有标的交易持仓重置权限" ></FunctionSub>
|
||||
<FunctionSub Name="偏移设置" Title="偏移设置" Type="Operate" Note="X-Bond行情报价添加偏移设置" ></FunctionSub>
|
||||
<FunctionSub Name="变更记录" Title="变更记录" Note="变更记录 "></FunctionSub>
|
||||
<FunctionSub Name="收益凭证" Title="收益凭证"></FunctionSub>
|
||||
<FunctionSub Name="凭证审批" Title="凭证审批"></FunctionSub>
|
||||
@@ -61,23 +60,6 @@
|
||||
<FunctionSub Name="VaR计算" Title="VaR计算"></FunctionSub>
|
||||
<FunctionSub Name="观察事件" Title="观察事件"></FunctionSub>
|
||||
<FunctionSub Name="风险预警/禁止查询" Title="风险预警/禁止查询"></FunctionSub>
|
||||
<FunctionSub Name="异常交易监控" Title="异常交易监控"></FunctionSub>
|
||||
<FunctionSub Name="风控规则查看" Type="Operate" Note="是否有权限查询风控规则"></FunctionSub>
|
||||
<FunctionSub Name="风控规则新增" Type="Operate" Note="是否有权限新增风控规则"></FunctionSub>
|
||||
<FunctionSub Name="风控规则编辑" Type="Operate" Note="是否有权限编辑风控规则"></FunctionSub>
|
||||
<FunctionSub Name="风控规则删除" Type="Operate" Note="是否有权限删除/批量删除风控规则"></FunctionSub>
|
||||
<FunctionSub Name="风控规则启停" Type="Operate" Note="是否有权限启用/停用风控规则"></FunctionSub>
|
||||
<FunctionSub Name="风控应用查看" Type="Operate" Note="是否有权限查询风控应用"></FunctionSub>
|
||||
<FunctionSub Name="风控应用新增" Type="Operate" Note="是否有权限新增应用配置"></FunctionSub>
|
||||
<FunctionSub Name="风控应用编辑" Type="Operate" Note="是否有权限编辑应用配置"></FunctionSub>
|
||||
<FunctionSub Name="风控应用删除" Type="Operate" Note="是否有权限删除应用配置"></FunctionSub>
|
||||
<FunctionSub Name="风控应用启停" Type="Operate" Note="是否有权限启用/停用/批量操作应用配置"></FunctionSub>
|
||||
<FunctionSub Name="风控变量查看" Type="Operate" Note="是否有权限查询风控变量"></FunctionSub>
|
||||
<FunctionSub Name="风控变量新增" Type="Operate" Note="是否有权限新增变量"></FunctionSub>
|
||||
<FunctionSub Name="风控变量编辑" Type="Operate" Note="是否有权限编辑变量"></FunctionSub>
|
||||
<FunctionSub Name="风控变量删除" Type="Operate" Note="是否有权限删除变量"></FunctionSub>
|
||||
<FunctionSub Name="风控日志查看" Type="Operate" Note="是否有权限查询风控日志"></FunctionSub>
|
||||
<FunctionSub Name="风控日志导出" Type="Operate" Note="是否有权限导出日志Excel"></FunctionSub>
|
||||
</FunctionParent>
|
||||
<FunctionParent Name="结算管理" Title="结算财务">
|
||||
<FunctionSub Name="成交簿记" Title="成交簿记"></FunctionSub>
|
||||
@@ -89,27 +71,27 @@
|
||||
<FunctionSub Name="收盘操作" Title="收盘操作"></FunctionSub>
|
||||
<FunctionSub Name="收盘" Type="Operate" Title="收盘"></FunctionSub>
|
||||
<FunctionSub Name="每日估值报告" Title="每日估值报告"></FunctionSub>
|
||||
<FunctionSub Name="每日估值报告邮件发送" Title="每日估值报告邮件发送" Type="Operate" Note="是否有每日估值报告权限"></FunctionSub>
|
||||
<FunctionSub Name="每日估值报告邮件发送" Title="每日估值报告邮件发送" Type="Operate" Note="是否有每日估值报告权限" ></FunctionSub>
|
||||
<FunctionSub Name="日终价格查看" Type="Operate" Title="日终价格查看"></FunctionSub>
|
||||
<FunctionSub Name="日终价格修改" Type="Operate" Title="日终价格修改"></FunctionSub>
|
||||
<FunctionSub Name="债券付息数据查看" Type="Operate" Title="债券付息数据查看"></FunctionSub>
|
||||
<FunctionSub Name="债券付息数据修改" Type="Operate" Title="债券付息数据修改"></FunctionSub>
|
||||
<FunctionSub Name="交易确认书" Title="交易确认书"></FunctionSub>
|
||||
<FunctionSub Name="交易确认书生成" Title="交易确认书生成" Type="Operate" Note="是否有交易确认书生成权限"></FunctionSub>
|
||||
<FunctionSub Name="交易确认书邮件发送" Title="交易确认书邮件发送" Type="Operate" Note="是否有交易确认书邮件发送权限"></FunctionSub>
|
||||
<FunctionSub Name="交易确认书生成" Title="交易确认书生成" Type="Operate" Note="是否有交易确认书生成权限" ></FunctionSub>
|
||||
<FunctionSub Name="交易确认书邮件发送" Title="交易确认书邮件发送" Type="Operate" Note="是否有交易确认书邮件发送权限" ></FunctionSub>
|
||||
<FunctionSub Name="交易确认书-期权" Title="交易确认书-期权" Note="期权交易确认书页面访问权限"></FunctionSub>
|
||||
<FunctionSub Name="结算确认书" Title="结算确认书"></FunctionSub>
|
||||
<FunctionSub Name="结算确认书生成" Title="结算确认书生成" Type="Operate" Note="是否有结算确认书生成权限"></FunctionSub>
|
||||
<FunctionSub Name="结算确认书重置" Title="结算确认书重置" Type="Operate" Note="是否有结算确认书重置权限"></FunctionSub>
|
||||
<FunctionSub Name="结算确认书邮件发送" Title="结算确认书邮件发送" Type="Operate" Note="是否有结算确认书邮件发送权限"></FunctionSub>
|
||||
<FunctionSub Name="结算确认书生成" Title="结算确认书生成" Type="Operate" Note="是否有结算确认书生成权限" ></FunctionSub>
|
||||
<FunctionSub Name="结算确认书重置" Title="结算确认书重置" Type="Operate" Note="是否有结算确认书重置权限" ></FunctionSub>
|
||||
<FunctionSub Name="结算确认书邮件发送" Title="结算确认书邮件发送" Type="Operate" Note="是否有结算确认书邮件发送权限" ></FunctionSub>
|
||||
<FunctionSub Name="出入金维护" Title="资金记录"></FunctionSub>
|
||||
<FunctionSub Name="资金审批页面" Title="资金审批"></FunctionSub>
|
||||
<FunctionSub Name="出入金执行" Title="出入金执行" Type="Operate" Note="资金记录页面是否有出入金执行权限"></FunctionSub>
|
||||
<FunctionSub Name="出入金拒绝" Title="出入金拒绝" Type="Operate" Note="资金记录是否有出入金拒绝权限"></FunctionSub>
|
||||
<FunctionSub Name="出入金新增" Title="出入金新增" Type="Operate" Note="资金记录页面是否有出入金新增,导入权限,是否可以撤回"></FunctionSub>
|
||||
<FunctionSub Name="出入金执行" Title="出入金执行" Type="Operate" Note="资金记录页面是否有出入金执行权限" ></FunctionSub>
|
||||
<FunctionSub Name="出入金拒绝" Title="出入金拒绝" Type="Operate" Note="资金记录是否有出入金拒绝权限" ></FunctionSub>
|
||||
<FunctionSub Name="出入金新增" Title="出入金新增" Type="Operate" Note="资金记录页面是否有出入金新增,导入权限,是否可以撤回" ></FunctionSub>
|
||||
<FunctionSub Name="出入金删除" Title="出入金删除" Type="Operate" Note="资金记录页面是否有出入金删除权限"></FunctionSub>
|
||||
<FunctionSub Name="生成出金单" Title="生成出金单" Type="Operate" Note="生成出金单权限"></FunctionSub>
|
||||
<FunctionSub Name="已拒绝资金重新发起" Title="已拒绝资金重新发起" Type="Operate" Note="已拒绝资金重新发起"></FunctionSub>
|
||||
<FunctionSub Name="生成出金单" Title="生成出金单" Type="Operate" Note="生成出金单权限" ></FunctionSub>
|
||||
<FunctionSub Name="已拒绝资金重新发起" Title="已拒绝资金重新发起" Type="Operate" Note="已拒绝资金重新发起" ></FunctionSub>
|
||||
<FunctionSub Name="修改资金记录" Title="资金记录维护" Type="Operate" Note="在资金记录页面,是否可以修改待确认和修改待确认的资金记录"></FunctionSub>
|
||||
<FunctionSub Name="导入外部结算数据" Title="导入外部结算数据" Type="Operate" Note="导入外部结算数据"></FunctionSub>
|
||||
<FunctionSub Name="其他报告" Title="其他报告" Note="用于存放用户个性化的非通用报表,仅针对此功能定制开发过的用户有效"></FunctionSub>
|
||||
@@ -129,21 +111,21 @@
|
||||
<FunctionSub Name="客户审批" Title="客户审批"></FunctionSub>
|
||||
<FunctionSub Name="黑名单客户" Title="黑名单客户"></FunctionSub>
|
||||
<FunctionSub Name="审批中客户信息编辑" Title="审批中客户信息编辑" Type="Operate" Note="是否可以修改审批中的客户信息"></FunctionSub>
|
||||
<FunctionSub Name="黑名单客户管理" Type="Operate" Note="是否有权限进行客户黑名单操作"></FunctionSub>
|
||||
<FunctionSub Name="客户销户" Type="Operate" Note="是否有权限进行客户销户操作"></FunctionSub>
|
||||
<FunctionSub Name="客户休眠" Type="Operate" Note="是否有权限进行客户休眠操作"></FunctionSub>
|
||||
<FunctionSub Name="客户等级管理" Type="Operate" Note="是否有权限进行客户等级操作"></FunctionSub>
|
||||
<FunctionSub Name="黑名单客户管理" Type="Operate" Note="是否有权限进行客户黑名单操作" ></FunctionSub>
|
||||
<FunctionSub Name="客户销户" Type="Operate" Note="是否有权限进行客户销户操作" ></FunctionSub>
|
||||
<FunctionSub Name="客户休眠" Type="Operate" Note="是否有权限进行客户休眠操作" ></FunctionSub>
|
||||
<FunctionSub Name="客户等级管理" Type="Operate" Note="是否有权限进行客户等级操作" ></FunctionSub>
|
||||
<FunctionSub Name="担任适当性评估人" Type="Operate" Note="是否客户在客户信息的适当性管理页面中被选为适当性评估人"></FunctionSub>
|
||||
<FunctionSub Name="导入客户银行卡" Type="Operate" Title="导入客户银行卡" Note="能否导入客户银行卡"></FunctionSub>
|
||||
<FunctionSub Name="客户端密码设置" Type="Operate" Title="客户端密码设置" Note="能否设置客户端的密码"></FunctionSub>
|
||||
<FunctionSub Name="正常状态客户修改" Type="Operate" Note="是否有对状态为正常的客户进行信息维护的权限"></FunctionSub>
|
||||
<FunctionSub Name="销户休眠客户修改" Type="Operate" Note="是否有对已销户、已休眠的客户信息维护的权限"></FunctionSub>
|
||||
<FunctionSub Name="批量修改客户信息" Type="Operate" Note="是否有权限批量修改客户信息"></FunctionSub>
|
||||
<FunctionSub Name="客户标签调整权限" Title="客户标签调整权限" Type="Operate" Note="客户上打标签、移除标签、批量打标签"></FunctionSub>
|
||||
<FunctionSub Name="客户标签查看权限" Title="客户标签查看权限" Type="Operate" Note="是否可以查看客户上的标签"></FunctionSub>
|
||||
<FunctionSub Name="客户标签调整权限" Title="客户标签调整权限" Type="Operate" Note="客户上打标签、移除标签、批量打标签" ></FunctionSub>
|
||||
<FunctionSub Name="客户标签查看权限" Title="客户标签查看权限" Type="Operate" Note="是否可以查看客户上的标签" ></FunctionSub>
|
||||
<FunctionSub Name="机构账号设置" Title="机构账号设置"></FunctionSub>
|
||||
<FunctionSub Name="机构账号设置新增" Title="机构账号设置新增" Type="Operate" Note="是否有机构账号设置新增权限"></FunctionSub>
|
||||
<FunctionSub Name="机构账号设置编辑" Title="机构账号设置编辑" Type="Operate" Note="是否有机构账号设置编辑权限"></FunctionSub>
|
||||
<FunctionSub Name="机构账号设置新增" Title="机构账号设置新增" Type="Operate" Note="是否有机构账号设置新增权限" ></FunctionSub>
|
||||
<FunctionSub Name="机构账号设置编辑" Title="机构账号设置编辑" Type="Operate" Note="是否有机构账号设置编辑权限" ></FunctionSub>
|
||||
<FunctionSub Name="授信管理" Title="授信管理"></FunctionSub>
|
||||
<FunctionSub Name="资信评级" Title="资信评级"></FunctionSub>
|
||||
<FunctionSub Name="授信修改" Title="授信修改" Type="Operate" Note="是否可以修改授信(控制新增、修改、删除的 操作权限)"></FunctionSub>
|
||||
@@ -151,37 +133,37 @@
|
||||
</FunctionParent>
|
||||
<FunctionParent Name="互换簿记预设" Title="互换簿记预设">
|
||||
<FunctionSub Name="TRS用簿记账户设置" Title="TRS用簿记账户设置"></FunctionSub>
|
||||
<FunctionSub Name="TRS用簿记账户设置新增" Title="TRS用簿记账户设置新增" Type="Operate" Note="是否有TRS用簿记账户设置新增权限"></FunctionSub>
|
||||
<FunctionSub Name="TRS用簿记账户设置编辑" Title="TRS用簿记账户设置编辑" Type="Operate" Note="是否有TRS用簿记账户设置编辑权限"></FunctionSub>
|
||||
<FunctionSub Name="TRS用簿记账户设置删除" Title="TRS用簿记账户设置删除" Type="Operate" Note="是否有TRS用簿记账户设置删除权限"></FunctionSub>
|
||||
<FunctionSub Name="TRS用簿记账户设置新增" Title="TRS用簿记账户设置新增" Type="Operate" Note="是否有TRS用簿记账户设置新增权限" ></FunctionSub>
|
||||
<FunctionSub Name="TRS用簿记账户设置编辑" Title="TRS用簿记账户设置编辑" Type="Operate" Note="是否有TRS用簿记账户设置编辑权限" ></FunctionSub>
|
||||
<FunctionSub Name="TRS用簿记账户设置删除" Title="TRS用簿记账户设置删除" Type="Operate" Note="是否有TRS用簿记账户设置删除权限" ></FunctionSub>
|
||||
<FunctionSub Name="簿记账户与衡泰关系" Title="簿记账户与衡泰关系"></FunctionSub>
|
||||
<FunctionSub Name="簿记账户与衡泰关系新增" Title="簿记账户与衡泰关系新增" Type="Operate" Note="是否有簿记账户与衡泰关系权限"></FunctionSub>
|
||||
<FunctionSub Name="簿记账户与衡泰关系编辑" Title="簿记账户与衡泰关系编辑" Type="Operate" Note="是否有簿记账户与衡泰关系权限"></FunctionSub>
|
||||
<FunctionSub Name="簿记账户与衡泰关系删除" Title="簿记账户与衡泰关系删除" Type="Operate" Note="是否有簿记账户与衡泰关系权限"></FunctionSub>
|
||||
<FunctionSub Name="簿记账户与衡泰关系新增" Title="簿记账户与衡泰关系新增" Type="Operate" Note="是否有簿记账户与衡泰关系权限" ></FunctionSub>
|
||||
<FunctionSub Name="簿记账户与衡泰关系编辑" Title="簿记账户与衡泰关系编辑" Type="Operate" Note="是否有簿记账户与衡泰关系权限" ></FunctionSub>
|
||||
<FunctionSub Name="簿记账户与衡泰关系删除" Title="簿记账户与衡泰关系删除" Type="Operate" Note="是否有簿记账户与衡泰关系权限" ></FunctionSub>
|
||||
<FunctionSub Name="互换预付金率维护" Title="互换预付金率维护"></FunctionSub>
|
||||
<FunctionSub Name="互换预付金率修改" Type="Operate" Title="互换预付金率修改"></FunctionSub>
|
||||
<FunctionSub Name="阶梯费率" Title="阶梯费率" Note="互换阶梯费率"></FunctionSub>
|
||||
<FunctionSub Name="阶梯费率新增" Title="阶梯费率新增" Type="Operate" Note="阶梯费率新增及导入"></FunctionSub>
|
||||
<FunctionSub Name="阶梯费率编辑" Title="阶梯费率编辑" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="阶梯费率删除" Title="阶梯费率删除" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="阶梯费率新增" Title="阶梯费率新增" Type="Operate" Note="阶梯费率新增及导入" ></FunctionSub>
|
||||
<FunctionSub Name="阶梯费率编辑" Title="阶梯费率编辑" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="阶梯费率删除" Title="阶梯费率删除" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="浮动利率" Title="浮动利率" Note="互换浮动利率"></FunctionSub>
|
||||
<FunctionSub Name="浮动利率新增" Title="浮动利率新增" Type="Operate" Note="浮动利率新增及导入"></FunctionSub>
|
||||
<FunctionSub Name="浮动利率编辑" Title="浮动利率编辑" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="浮动利率删除" Title="浮动利率删除" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="浮动利率编辑" Title="浮动利率编辑" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="浮动利率删除" Title="浮动利率删除" Type="Operate" ></FunctionSub>
|
||||
</FunctionParent>
|
||||
<FunctionParent Name="基础参数管理" Title="数据管理">
|
||||
<FunctionSub Name="交易日历" Title="交易日历"></FunctionSub>
|
||||
<FunctionSub Name="交易日历管理" Title="交易日历管理" Type="Operate" Note="是否有权限修改交易日历"></FunctionSub>
|
||||
<FunctionSub Name="交易日历管理" Title="交易日历管理" Type="Operate" Note="是否有权限修改交易日历" ></FunctionSub>
|
||||
<FunctionSub Name="交易市场" Title="交易市场"></FunctionSub>
|
||||
<FunctionSub Name="交易市场修改" Type="Operate" Title="交易市场修改"></FunctionSub>
|
||||
<FunctionSub Name="标的品种" Title="标的品种"></FunctionSub>
|
||||
<FunctionSub Name="标的品种编辑" Title="标的品种编辑" Type="Operate" Note="是否有权限在标的品种页面编辑标的品种"></FunctionSub>
|
||||
<FunctionSub Name="标的品种编辑" Title="标的品种编辑" Type="Operate" Note="是否有权限在标的品种页面编辑标的品种" ></FunctionSub>
|
||||
<FunctionSub Name="标的管理" Title="标的资产"></FunctionSub>
|
||||
<FunctionSub Name="标的资产编辑" Type="Operate" Title="标的资产编辑"></FunctionSub>
|
||||
<FunctionSub Name="标的启用" Title="标的启用" Type="Operate" Note="标的资产页面是否可以启用标的资产"></FunctionSub>
|
||||
<FunctionSub Name="除权设置" Title="除权设置" Type="Operate" Note="是否可以在标的资产页面设置标的资产中的股票的除权除息信息"></FunctionSub>
|
||||
<FunctionSub Name="标的启用" Title="标的启用" Type="Operate" Note="标的资产页面是否可以启用标的资产" ></FunctionSub>
|
||||
<FunctionSub Name="除权设置" Title="除权设置" Type="Operate" Note="是否可以在标的资产页面设置标的资产中的股票的除权除息信息" ></FunctionSub>
|
||||
<FunctionSub Name="股票分红率查看" Title="股票分红率"></FunctionSub>
|
||||
<FunctionSub Name="股票分红率设置" Title="股票分红率设置" Type="Operate" Note="股票分红率页面是否有新增修改权限"></FunctionSub>
|
||||
<FunctionSub Name="股票分红率设置" Title="股票分红率设置" Type="Operate" Note="股票分红率页面是否有新增修改权限" ></FunctionSub>
|
||||
<FunctionSub Name="除权除息交易" Title="除权除息交易"></FunctionSub>
|
||||
<FunctionSub Name="设置货币" Title="设置货币"></FunctionSub>
|
||||
<FunctionSub Name="设置货币修改" Title="设置货币修改" Type="Operate" Note="修改设置货币"></FunctionSub>
|
||||
@@ -212,7 +194,7 @@
|
||||
<FunctionSub Name="系统参数" Title="系统参数配置" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="交易权限" Title="交易权限"></FunctionSub>
|
||||
<FunctionSub Name="交易权限修改" Type="Operate" Title="交易权限修改"></FunctionSub>
|
||||
<FunctionSub Name="系统日期设置" Title="系统日期设置" Type="Operate" Note="是否有权限在交易参数页面设置系统日期"></FunctionSub>
|
||||
<FunctionSub Name="系统日期设置" Title="系统日期设置" Type="Operate" Note="是否有权限在交易参数页面设置系统日期" ></FunctionSub>
|
||||
<FunctionSub Name="交易特批" Title="交易特批" Type="Operate" Note="是否有权限在系统参数页面设置交易特批开关的权限"></FunctionSub>
|
||||
<FunctionSub Name="出金特批" Title="出金特批" Type="Operate" Note="是否有权限在系统参数页面设置出金特批开关的权限"></FunctionSub>
|
||||
<FunctionSub Name="交易相关" Title="交易相关" Type="Operate" Note="是否有权限在系统参数页面设置交易修改时是否需要说明开关的权限"></FunctionSub>
|
||||
@@ -222,18 +204,18 @@
|
||||
</FunctionParent>
|
||||
<FunctionParent Name="TRS交易端" Title="TRS交易端配置">
|
||||
<FunctionSub Name="客户委托" Title="客户委托"></FunctionSub>
|
||||
<FunctionSub Name="客户委托-确认对冲委托引擎开关" Title="客户委托-确认对冲委托引擎开关" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="客户委托-合约成交" Title="客户委托-合约成交" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="客户委托-确认对冲" Title="客户委托-确认对冲" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="客户委托-批量合约成交" Title="客户委托-批量合约成交" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="客户委托-批量拒绝" Title="客户委托-批量拒绝" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="客户委托-新增客户交易" Title="客户委托-新增客户交易" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="客户委托-拒绝" Title="客户委托-拒绝" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="客户委托-确认对冲委托引擎开关" Title="客户委托-确认对冲委托引擎开关" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="客户委托-合约成交" Title="客户委托-合约成交" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="客户委托-确认对冲" Title="客户委托-确认对冲" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="客户委托-批量合约成交" Title="客户委托-批量合约成交" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="客户委托-批量拒绝" Title="客户委托-批量拒绝" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="客户委托-新增客户交易" Title="客户委托-新增客户交易" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="客户委托-拒绝" Title="客户委托-拒绝" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="对冲委托" Title="对冲委托"></FunctionSub>
|
||||
<FunctionSub Name="对冲委托-确认对冲" Title="对冲委托-确认对冲" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="对冲委托-对冲撤单" Title="对冲委托-对冲撤单" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="对冲委托-确认对冲" Title="对冲委托-确认对冲" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="对冲委托-对冲撤单" Title="对冲委托-对冲撤单" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="成交补录" Title="成交补录"></FunctionSub>
|
||||
<FunctionSub Name="成交补录-提交补录" Title="成交补录-提交补录" Type="Operate"></FunctionSub>
|
||||
<FunctionSub Name="成交补录-提交补录" Title="成交补录-提交补录" Type="Operate" ></FunctionSub>
|
||||
<FunctionSub Name="交易监控" Title="交易监控"></FunctionSub>
|
||||
<FunctionSub Name="客户行为监控" Title="客户行为监控"></FunctionSub>
|
||||
</FunctionParent>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
{Name:"资金监控",Rights:["风险控制-资金监控"],Url:"client/clientRiskMonitor"},
|
||||
{Name:"市场风险",Rights:["风险控制-市场风险"],Url:"risk/RiskExposureReport"},
|
||||
{Name:"限额监控",Rights:["风险控制-限额监控"],Url:"risk/quotaMonitor"},
|
||||
{Name:"异常交易监控",Rights:["风险控制-异常交易监控"],Url:"v3/risk/risk-engine-config"},
|
||||
{Name:"白名单券池",Rights:["风险控制-白名单券池"],Url:"v3/data/underlying-pool"},
|
||||
{Name:"日终持仓风险",Rights:["风险控制-日终持仓风险"],Url:"trade/EodPositionRisks"},
|
||||
{Name:"日终持仓风险_互换",Rights:["风险控制-日终持仓风险_互换"],Url:"swaptrade2/EodPositionRisks"},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using YLErp.DBModels.Consts;
|
||||
using YLErp.DBModels.Consts;
|
||||
using YLErp.Model.Enum;
|
||||
using YLErp.Modules.ClientModule;
|
||||
using YLErp.Modules.ClientModule.Models;
|
||||
@@ -280,7 +280,7 @@ namespace YLErp.Web
|
||||
|
||||
if (user.Roles.Any(n => n.Name == "权限管理员"))
|
||||
{
|
||||
var rightStrs = new string[] { "部门管理", "系统管理", "角色管理", "角色新增", "角色修改", "用户管理", "用户新增", "用户修改", "用户禁用", "基础缓存", "风控规则查看", "风控规则新增", "风控规则编辑", "风控规则删除", "风控规则启停", "风控应用查看", "风控应用新增", "风控应用编辑", "风控应用删除", "风控应用启停", "风控变量查看", "风控变量新增", "风控变量编辑", "风控变量删除", "风控日志查看", "风控日志导出" };
|
||||
var rightStrs = new string[] { "部门管理", "系统管理", "角色管理", "角色新增", "角色修改", "用户管理", "用户新增", "用户修改", "用户禁用", "基础缓存" };
|
||||
var query1 = db.Functions.Where(o => rightStrs.Contains(o.Name)).Select(n => n.Id);
|
||||
var query2 = from roleFunc in db.RoleFunctions
|
||||
join roleUsr in db.RoleUsers on roleFunc.RoleId equals roleUsr.RoleId
|
||||
|
||||
@@ -1,667 +0,0 @@
|
||||
using Qdp.Foundation.Utilities;
|
||||
using YLErp.DBModels;
|
||||
using YLErp.Modules.RiskEngine;
|
||||
using YLErp.Modules.RiskEngine.Dto;
|
||||
|
||||
namespace YLErp.Web.Controllers
|
||||
{
|
||||
[Route("risk-engine")]
|
||||
public class RiskRuleController : BaseController
|
||||
{
|
||||
private readonly IYcLogger _logger = LogFactory.GetLogger("RiskRuleController");
|
||||
|
||||
#region Rule Management
|
||||
|
||||
[HttpGet("risk-rules")]
|
||||
[MyAuthorize("风险控制-风控规则查看")]
|
||||
public JsonResult QueryRiskRules(QueryRiskRuleReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.QueryRuleList(req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询风控规则列表");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-rules/{id}")]
|
||||
[MyAuthorize("风险控制-风控规则查看")]
|
||||
public JsonResult GetRiskRule(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.GetRuleDetail(id);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询风控规则详情");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-rules/{id}/versions")]
|
||||
[MyAuthorize("风险控制-风控规则查看")]
|
||||
public JsonResult GetRiskRuleVersions(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.GetRuleVersions(id);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询风控规则版本历史");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-rules")]
|
||||
[MyAuthorize("风险控制-风控规则新增")]
|
||||
public JsonResult CreateRiskRule([FromBody] CreateRiskRuleReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.CreateRule(req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "创建风控规则");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("risk-rules/{id}")]
|
||||
[MyAuthorize("风险控制-风控规则编辑")]
|
||||
public JsonResult UpdateRiskRule(long id, [FromBody] UpdateRiskRuleReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.UpdateRule(id, req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "更新风控规则");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("risk-rules/{id}")]
|
||||
[MyAuthorize("风险控制-风控规则删除")]
|
||||
public JsonResult DeleteRiskRule(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
service.DeleteRule(id);
|
||||
return Json(new { success = true });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "删除风控规则");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("risk-rules/batch")]
|
||||
[MyAuthorize("风险控制-风控规则删除")]
|
||||
public JsonResult BatchDeleteRiskRules([FromBody] List<long> ids)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.BatchDeleteRules(ids);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "批量删除风控规则");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-rules/{id}/enable")]
|
||||
[MyAuthorize("风险控制-风控规则启停")]
|
||||
public JsonResult EnableRiskRule(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
service.EnableRule(id);
|
||||
return Json(new { success = true });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "启用风控规则");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-rules/{id}/disable")]
|
||||
[MyAuthorize("风险控制-风控规则启停")]
|
||||
public JsonResult DisableRiskRule(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
service.DisableRule(id);
|
||||
return Json(new { success = true });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "停用风控规则");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-rules/{id}/applications")]
|
||||
[MyAuthorize("风险控制-风控规则查看")]
|
||||
public JsonResult GetRuleApplications(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.GetRuleApplications(id);
|
||||
return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询规则关联应用列表");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-rules/list")]
|
||||
[MyAuthorize("风险控制-风控规则查看")]
|
||||
public JsonResult GetAllRiskRules()
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.GetAllRuleList();
|
||||
return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询规则下拉列表");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application Management
|
||||
|
||||
[HttpGet("risk-applications")]
|
||||
[MyAuthorize("风险控制-风控应用查看")]
|
||||
public JsonResult QueryRiskApplications(QueryRiskApplicationReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.QueryApplicationList(req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询应用配置列表");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-applications/{id}")]
|
||||
[MyAuthorize("风险控制-风控应用查看")]
|
||||
public JsonResult GetRiskApplication(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.GetApplicationDetail(id);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询应用配置详情");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-applications")]
|
||||
[MyAuthorize("风险控制-风控应用新增")]
|
||||
public JsonResult CreateRiskApplication([FromBody] CreateRiskApplicationReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.CreateApplication(req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "创建应用配置");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("risk-applications/{id}")]
|
||||
[MyAuthorize("风险控制-风控应用编辑")]
|
||||
public JsonResult UpdateRiskApplication(long id, [FromBody] UpdateRiskApplicationReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.UpdateApplication(id, req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "更新应用配置");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("risk-applications/{id}")]
|
||||
[MyAuthorize("风险控制-风控应用删除")]
|
||||
public JsonResult DeleteRiskApplication(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
service.DeleteApplication(id);
|
||||
return Json(new { success = true });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "删除应用配置");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-applications/{id}/enable")]
|
||||
[MyAuthorize("风险控制-风控应用启停")]
|
||||
public JsonResult EnableRiskApplication(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
service.EnableApplication(id);
|
||||
return Json(new { success = true });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "启用应用配置");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-applications/{id}/disable")]
|
||||
[MyAuthorize("风险控制-风控应用启停")]
|
||||
public JsonResult DisableRiskApplication(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
service.DisableApplication(id);
|
||||
return Json(new { success = true });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "停用应用配置");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-applications/batch-enable")]
|
||||
[MyAuthorize("风险控制-风控应用启停")]
|
||||
public JsonResult BatchEnableRiskApplications([FromBody] List<long> ids)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.BatchEnableApplications(ids);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "批量启用应用配置");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-applications/batch-disable")]
|
||||
[MyAuthorize("风险控制-风控应用启停")]
|
||||
public JsonResult BatchDisableRiskApplications([FromBody] List<long> ids)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.BatchDisableApplications(ids);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "批量停用应用配置");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Variable Management
|
||||
|
||||
[HttpGet("risk-variables")]
|
||||
[MyAuthorize("风险控制-风控变量查看")]
|
||||
public JsonResult QueryRiskVariables(QueryRiskVariableReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.QueryVariableList(req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询变量列表");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-variables/{id}")]
|
||||
[MyAuthorize("风险控制-风控变量查看")]
|
||||
public JsonResult GetRiskVariable(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.GetVariableDetail(id);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询变量详情");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-variables/list")]
|
||||
[MyAuthorize("风险控制-风控变量查看")]
|
||||
public JsonResult GetAllRiskVariables()
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.GetAllVariableList();
|
||||
return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询全部变量列表");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("risk-variables")]
|
||||
[MyAuthorize("风险控制-风控变量新增")]
|
||||
public JsonResult CreateRiskVariable([FromBody] CreateRiskVariableReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.CreateVariable(req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "创建变量");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("risk-variables/{id}")]
|
||||
[MyAuthorize("风险控制-风控变量编辑")]
|
||||
public JsonResult UpdateRiskVariable(long id, [FromBody] UpdateRiskVariableReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.UpdateVariable(id, req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "更新变量");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("risk-variables/{id}")]
|
||||
[MyAuthorize("风险控制-风控变量删除")]
|
||||
public JsonResult DeleteRiskVariable(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
service.DeleteVariable(id);
|
||||
return Json(new { success = true });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "删除变量");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Trade Types
|
||||
|
||||
[HttpGet("trade-types")]
|
||||
[MyAuthorize("风险控制-风控应用查看")]
|
||||
public JsonResult GetTradeTypes()
|
||||
{
|
||||
try
|
||||
{
|
||||
var rows = ConsTrade.AllTradeTypes.Select(t => new { label = t, value = t }).ToList();
|
||||
var total = rows.Count;
|
||||
return Json(new {
|
||||
success = true,
|
||||
data = new {
|
||||
page = 1,
|
||||
records = total,
|
||||
rows = rows,
|
||||
total = total
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询合约类型列表");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Audit Log
|
||||
|
||||
[HttpGet("risk-audit-logs")]
|
||||
[MyAuthorize("风险控制-风控日志查看")]
|
||||
public JsonResult QueryRiskAuditLogs(QueryRiskAuditLogReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.QueryAuditLogs(req);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询风控操作日志列表");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-audit-logs/{id}")]
|
||||
[MyAuthorize("风险控制-风控日志查看")]
|
||||
public JsonResult GetRiskAuditLogDetail(long id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var result = service.GetAuditLogDetail(id);
|
||||
return Json(new { success = true, data = result });
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "查询风控操作日志详情");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("risk-audit-logs/export")]
|
||||
[MyAuthorize("风险控制-风控日志导出")]
|
||||
public IActionResult ExportRiskAuditLogs(QueryRiskAuditLogReq req)
|
||||
{
|
||||
try
|
||||
{
|
||||
var service = new RiskRuleService(CurUser);
|
||||
var bytes = service.ExportAuditLogs(req);
|
||||
return File(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "风控操作日志.xlsx");
|
||||
}
|
||||
catch (ServiceException ex)
|
||||
{
|
||||
return Json(new { success = false, message = ex.Message });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "导出风控操作日志");
|
||||
return Json(new { success = false, message = "系统异常,请联系管理员" });
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -204,7 +204,7 @@
|
||||
<span title="使用系统标的价格" class="glyphicon glyphicon-refresh"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td>{{floatPosition.Quantity}}</td>
|
||||
<td>{{deal.CloseQty}}</td>
|
||||
<td>
|
||||
<vue-number-input v-model="floatPosition.TradingFee" v-bind:format="inputFormatEqvNotional" v-on:input="changeTradingFee"></vue-number-input>
|
||||
<div class="bubble-box">我方{{floatPosition.PayDirection==1?"支付":"收取"}}交易费用</div>
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"ylcms": "server=10.250.202.35;uid=onederiv@OneDeriv#wx_dtpp_test;pooling=true;port=2883;pwd=Onederiv@2026;database=yltrs_ylcms;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"yladmin": "server=10.250.202.35;uid=onederiv@OneDeriv#wx_dtpp_test;pooling=true;port=2883;pwd=Onederiv@2026;database=yltrs_admin;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"ylclient": "server=10.250.202.35;uid=onederiv@OneDeriv#wx_dtpp_test;pooling=true;port=2883;pwd=Onederiv@2026;database=yltrs_client;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"bondoms": "server=10.250.202.35;uid=onederiv@OneDeriv#wx_dtpp_test;pooling=true;port=2883;pwd=Onederiv@2026;database=bond_oms;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;"
|
||||
"ylcms": "server=192.168.2.96;uid=DBAdmin;pooling=true;port=3306;pwd=YieldChain$$2025;database=glms_yltrs_ylcms;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"yladmin": "server=192.168.2.96;uid=DBAdmin;pooling=true;port=3306;pwd=YieldChain$$2025;database=glms_yltrs_admin;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"ylclient": "server=192.168.2.96;uid=DBAdmin;pooling=true;port=3306;pwd=YieldChain$$2025;database=glms_yltrs_client;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;",
|
||||
"bondoms": "server=192.168.2.96;uid=DBAdmin;pooling=true;port=3306;pwd=YieldChain$$2025;database=glms_bond_oms;charset=utf8;Allow User Variables=True;SslMode=none;Connection Timeout=30;IgnoreCommandTransaction=true;"
|
||||
},
|
||||
"AppSettings": {
|
||||
"VirtualPathRoot": "",
|
||||
"UseRightAligned": "",
|
||||
"PluginFolder": "D:\\workspace\\onederiv\\trs\\Plugins\\YLErp.Plugins.GuoLian\\obj\\Debug\\net6.0" // 改为本地目录地址
|
||||
"PluginFolder": "D:\\workspace\\glms\\zszq-trs\\Plugins\\YLErp.Plugins.GuoLian\\obj\\Debug\\net6.0"
|
||||
},
|
||||
"LibreOffice": {
|
||||
"ExePath": "",
|
||||
@@ -75,15 +75,12 @@
|
||||
"SendKafakaCron": "10 0 * * *",
|
||||
"MaxThreadPercent": 0.6, //占系统资源最多60%的线程数量
|
||||
"oa_confg": {
|
||||
"BaseUrl": "http://10.250.202.40:13590",
|
||||
"SubUrl": "/gateway/oaflow/createOaFlow",
|
||||
"QueryUrl": "/gateway/oaflow/getRequestData",
|
||||
"DownloadFileUrl": "/gateway/oaflow/downloadSingleFile",
|
||||
"SystemToken": "QIkox8sv3rVLtiT1wmI4Dp8wSjX9D84Glkp121vRino9fLobWnDiy8ppmqJcv1676TYuxZsGrYelx0whRCMaPyums2VnzIYrpqCFf5tyc3/x22Elf25xgRmd5pH8tLcnPuVOjMrUf0GsoytQCGFkhnrPajhsKq/mSwYQ4OA=", //OA系统key
|
||||
"SystemName": "onederiv",
|
||||
"IsNextFlow": 1, //是否自动提交 默认0
|
||||
"FlowId": 779115,
|
||||
"UploadUrl": "http://10.250.202.40:13590/gateway/oaflow/uploadDoc"
|
||||
"BaseUrl": "http://ip:port",
|
||||
"SubUrl": "",
|
||||
"UploadUrl": "/api/oa/upload", // OA附件上传接口路径
|
||||
"SystemToken": "your-system-token", // OA系统鉴权Token
|
||||
"SystemName": "OTC_TRADE", // 调用方系统标识
|
||||
"IsNextFlow": 0
|
||||
},
|
||||
"GeneralSSO": {
|
||||
"enable": true, //是否启用通用SSO登录
|
||||
|
||||
Reference in New Issue
Block a user