(underlyingInstrumentType, out var instrumentFlag))
+ {
+ var byInstrument = matched.Where(x => (x.UnderlyingType & instrumentFlag) > 0).ToList();
+ if (byInstrument.Any())
+ {
+ matched = byInstrument;
+ }
+ else
+ {
+ var wildcard = matched.Where(x => x.UnderlyingType == UnderlyingTypeEnum.None || x.UnderlyingType == UnderlyingTypeEnum.All).ToList();
+ if (wildcard.Any())
+ {
+ matched = wildcard;
+ }
+ }
+ }
+
+ var detail = matched.First();
+ return new MarginRateResult
+ {
+ Template = template,
+ Detail = detail,
+ InitRate = ToDecimalRate(detail.MarginRatio1),
+ MaintainRate = ToDecimalRate(detail.MarginRatio2)
+ };
+ }
+
+ ///
+ /// 模板页录入的百分数(如 10 表示 10%)换算为小数(0.1)
+ ///
+ private static decimal? ToDecimalRate(double? ratio)
+ {
+ return ratio.HasValue ? (decimal)(ratio.Value / 100d) : (decimal?)null;
+ }
+ }
+}
diff --git a/YLErpDAL/Modules/SwapModule/SwapMarginTemplateConfigService.cs b/YLErpDAL/Modules/SwapModule/SwapMarginTemplateConfigService.cs
index 27c10b4a..3f95bba5 100644
--- a/YLErpDAL/Modules/SwapModule/SwapMarginTemplateConfigService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapMarginTemplateConfigService.cs
@@ -12,9 +12,10 @@ namespace YLErp.Modules.SwapModule
public static SwapMarginTemplateConfig GetConfig()
{
//保证金模板V2迁移:交易页"保证金模板"下拉的选项改为"预付金模板V2"页面维护的模板(自定义+全局默认,存模板名称),不再使用数据字典
+ //互换交易只显示"适用结构"包含 收益互换 的模板
using var db = new YLErp.BLL.YLContext();
var items = db.margin_template_v2
- .Where(item => !item.IsForClient && item.IsValid)
+ .Where(item => !item.IsForClient && item.IsValid && item.TradeTypes.Contains("收益互换"))
.OrderBy(item => item.IsDefault).ThenBy(item => item.id)
.Select(item => new SelectItem { Text = item.Name, Value = item.Name })
.ToArray();
diff --git a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs
index 2fc1fc87..ccc58da6 100644
--- a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs
@@ -134,9 +134,9 @@ namespace YLErp.Modules.SwapModule
DbContext.trade_margin_template.RemoveRange(olds);
if (!string.IsNullOrWhiteSpace(dbTrade.MarginTemplateName))
{
- //匹配自定义+全局默认模板(重名时优先自定义)
+ //匹配自定义+全局默认模板(重名时优先自定义),模板"适用结构"需包含 收益互换
var template = DbContext.margin_template_v2
- .Where(x => x.Name == dbTrade.MarginTemplateName && !x.IsForClient && x.IsValid)
+ .Where(x => x.Name == dbTrade.MarginTemplateName && !x.IsForClient && x.IsValid && x.TradeTypes.Contains("收益互换"))
.OrderBy(x => x.IsDefault)
.FirstOrDefault();
if (template != null)
diff --git a/YLErpWeb/Controllers/margin_template_v2Controller.cs b/YLErpWeb/Controllers/margin_template_v2Controller.cs
index 60edfece..b540be3c 100644
--- a/YLErpWeb/Controllers/margin_template_v2Controller.cs
+++ b/YLErpWeb/Controllers/margin_template_v2Controller.cs
@@ -301,19 +301,43 @@ namespace YLErp.Web.Controllers
if (marginTemplate.Details.Count() > 1)
{
- var underlyingType = UnderlyingTypeEnum.None;
- foreach (var detail in marginTemplate.Details)
+ if (marginTemplate.RuleType == (int)MarginRuleTypeEnum.区间追保结构)
{
- if (detail.UnderlyingType == UnderlyingTypeEnum.None)
+ //区间追保结构:按 利率债期限档(SpanConfig.BondTerm)分组校验,同一期限档内标的类型不允许重复,不同期限档允许相同标的类型
+ foreach (var termGroup in marginTemplate.Details.GroupBy(x => x.SpanConfig?.BondTerm ?? ""))
{
- throw new Exception("标的类型不能为空");
- }
- if ((detail.UnderlyingType & underlyingType) > 0)
- {
- throw new Exception("存在重复的标的类型:" + UnderlyingTypeUtil.GetDesc(detail.UnderlyingType & underlyingType));
- }
+ var termUnderlyingType = UnderlyingTypeEnum.None;
+ foreach (var detail in termGroup)
+ {
+ if ((detail.UnderlyingType & termUnderlyingType) > 0)
+ {
+ if (marginTemplate.UnderlyingSeperateType == (int)UnderlyingSeperateTypeEnum.None)
+ {
+ throw new Exception("同一利率债期限档下存在重复的参数组");
+ }
+ throw new Exception("存在重复的标的类型:" + UnderlyingTypeUtil.GetDesc(detail.UnderlyingType & termUnderlyingType));
+ }
- underlyingType |= detail.UnderlyingType;
+ termUnderlyingType |= detail.UnderlyingType;
+ }
+ }
+ }
+ else
+ {
+ var underlyingType = UnderlyingTypeEnum.None;
+ foreach (var detail in marginTemplate.Details)
+ {
+ if (detail.UnderlyingType == UnderlyingTypeEnum.None)
+ {
+ throw new Exception("标的类型不能为空");
+ }
+ if ((detail.UnderlyingType & underlyingType) > 0)
+ {
+ throw new Exception("存在重复的标的类型:" + UnderlyingTypeUtil.GetDesc(detail.UnderlyingType & underlyingType));
+ }
+
+ underlyingType |= detail.UnderlyingType;
+ }
}
}
diff --git a/YLErpWeb/Views/margin_template_v2/margin_template_v2ClientEdit.cshtml b/YLErpWeb/Views/margin_template_v2/margin_template_v2ClientEdit.cshtml
index 42f6428b..25de064a 100644
--- a/YLErpWeb/Views/margin_template_v2/margin_template_v2ClientEdit.cshtml
+++ b/YLErpWeb/Views/margin_template_v2/margin_template_v2ClientEdit.cshtml
@@ -138,7 +138,7 @@
@@ -203,6 +203,16 @@
+
+
+
+
@@ -423,12 +433,12 @@
-
+
-
+
@@ -467,6 +477,16 @@
+
+
+
+
diff --git a/YLErpWeb/Views/margin_template_v2/margin_template_v2DefaultEdit.cshtml b/YLErpWeb/Views/margin_template_v2/margin_template_v2DefaultEdit.cshtml
index 4cfc68e4..d55145c2 100644
--- a/YLErpWeb/Views/margin_template_v2/margin_template_v2DefaultEdit.cshtml
+++ b/YLErpWeb/Views/margin_template_v2/margin_template_v2DefaultEdit.cshtml
@@ -143,7 +143,7 @@
@@ -183,6 +183,16 @@
+
+
+
+
@@ -403,12 +413,12 @@
-
+
-
+
@@ -451,6 +461,16 @@
+
+
+
+
diff --git a/YLErpWeb/Views/margin_template_v2/margin_template_v2Edit.cshtml b/YLErpWeb/Views/margin_template_v2/margin_template_v2Edit.cshtml
index 03dee11a..5538a2d7 100644
--- a/YLErpWeb/Views/margin_template_v2/margin_template_v2Edit.cshtml
+++ b/YLErpWeb/Views/margin_template_v2/margin_template_v2Edit.cshtml
@@ -136,6 +136,16 @@
+
+
+
+
@@ -325,6 +335,16 @@
+
+
+
+
diff --git a/YLErpWeb/wwwroot/Scripts/app/marginTemplate/marginTemplateV2DefaultEdit.js b/YLErpWeb/wwwroot/Scripts/app/marginTemplate/marginTemplateV2DefaultEdit.js
index 26c09da6..ed181d71 100644
--- a/YLErpWeb/wwwroot/Scripts/app/marginTemplate/marginTemplateV2DefaultEdit.js
+++ b/YLErpWeb/wwwroot/Scripts/app/marginTemplate/marginTemplateV2DefaultEdit.js
@@ -95,7 +95,7 @@ const vue = new Vue({
this.marginTemplate.Comments = "名义本金*Max(x,y-0.5*虚值比例)+ Flag*Max(0,PV);\n其中虚值比例 = max(0, P - 执行价)/期初价格,当计算日为成交日时,Flag = 0,P = 期初价格,当计算日不为成交日时,Flag = 1,P = 标的现价;\n若勾选了“取与保底金额孰小”,则取较小的一个;\n保底金额 =ABS(执行价格 - 保底价格)* ABS(交易数量)。";
break;
case MarginRuleTypeEnum.区间追保结构:
- this.marginTemplate.Comments = "预付金占用为名义本金的固定比例。支持按标的资产类型(利率债/信用债/其它债券/股票/股指等全部资产类型)分别设置初始预付金率x、维持预付金率y;以期初净价为基准,按(x-y)逐档推算预警线/平仓线,标的价格触及档位线时触发追保或平仓。";
+ this.marginTemplate.Comments = "预付金占用为名义本金的固定比例。按利率债期限(<5y/5y-10y/10y-30y/>30y)分别设置初始预付金率x、维持预付金率y,支持再按标的资产类型(利率债/信用债/其它债券/股票/股指等全部资产类型)分组;以期初净价为基准,按(x-y)逐档推算预警线/平仓线,标的价格触及档位线时触发追保或平仓。";
break;
case MarginRuleTypeEnum.默认预付金规则:
this.marginTemplate.Comments = "考虑了14种场景下的Span算法与Delta算法比较的通用预付金规则,该规则可以调整Span涨跌幅度";
diff --git a/YLErpWeb/wwwroot/Scripts/app/marginTemplate/marginTemplateV2Edit.js b/YLErpWeb/wwwroot/Scripts/app/marginTemplate/marginTemplateV2Edit.js
index a176d959..1725b76e 100644
--- a/YLErpWeb/wwwroot/Scripts/app/marginTemplate/marginTemplateV2Edit.js
+++ b/YLErpWeb/wwwroot/Scripts/app/marginTemplate/marginTemplateV2Edit.js
@@ -81,7 +81,7 @@ const vue = new Vue({
this.marginTemplate.Comments = "名义本金*Max(x,y-0.5*虚值比例)+ Flag*Max(0,PV);\n其中虚值比例 = max(0, P - 执行价)/期初价格,当计算日为成交日时,Flag = 0,P = 期初价格,当计算日不为成交日时,Flag = 1,P = 标的现价;\n若勾选了“取与保底金额孰小”,则取较小的一个;\n保底金额 =ABS(执行价格 - 保底价格)* ABS(交易数量)。";
break;
case MarginRuleTypeEnum.区间追保结构:
- this.marginTemplate.Comments = "预付金占用为名义本金的固定比例。以期初净价为基准,按(初始预付金率x-维持预付金率y)逐档推算预警线/平仓线,标的价格触及档位线时触发追保或平仓。";
+ this.marginTemplate.Comments = "预付金占用为名义本金的固定比例。按利率债期限(<5y/5y-10y/10y-30y/>30y)分别设置初始预付金率x、维持预付金率y;以期初净价为基准,按(x-y)逐档推算预警线/平仓线,标的价格触及档位线时触发追保或平仓。";
break;
case MarginRuleTypeEnum.单独计算规则:
this.marginTemplate.Comments = "基于宏源定制的预付金规则,用于计算单笔交易,不参与Span预付金规则的轧差。";