#EQD-6948 国联民生-实现保证金规则(2)追保金额的产生与收盘计算 ETF 子类分档(转债ETF/科创债ETF)
This commit is contained in:
@@ -108,7 +108,7 @@ namespace YLErp.Modules.MarginModule
|
||||
var latestValueDate = detailQuery.Max(x => x.ValueDate);
|
||||
var details = detailQuery.Where(x => x.ValueDate == latestValueDate).ToList();
|
||||
|
||||
//4.利率债期限档匹配:精确档 → "全部"(BondTerm 为空)兜底
|
||||
//4.利率债/分档ETF 期限档匹配:精确档 → "全部"(BondTerm 为空)兜底
|
||||
var term = UnderlyingHelper.GetApplicableMarginTerm(underlyingCode, valueDate);
|
||||
var matched = details.Where(x => x.SpanConfig != null && x.SpanConfig.BondTerm == term).ToList();
|
||||
if (!matched.Any())
|
||||
@@ -120,13 +120,12 @@ namespace YLErp.Modules.MarginModule
|
||||
return null;
|
||||
}
|
||||
|
||||
//5.标的资产类型匹配(仅当模板选了"按资产类型分类"):精确标志位 → 通配行(None/All)兜底
|
||||
//标的细分分类判定钩子:本期默认返回 null → 走下方原有标志位匹配/通配行兜底,行为与现状一致;
|
||||
//后续需求(转债ETF/科创债ETF/中债指数等细分)实现判定规则后,此处按 (BondTerm, EtfKind) 元组匹配明细行。
|
||||
//5.ETF 子类行优先(子类区分度高于期限):标的有 EtfSubType(基金类)时优先取 EtfKind=子类 的行——
|
||||
//期限档匹配未命中子类行时再单独尝试"子类 + BondTerm 空"(子类不分档通配);无子类行维持原 matched(基金通配兜底)
|
||||
var underlyingCategory = GetUnderlyingCategory(underlyingCode, underlyingInstrumentType);
|
||||
if (underlyingCategory != null)
|
||||
{
|
||||
//TODO: 后续需求实现:按 (SpanConfig.BondTerm, SpanConfig.EtfKind) 元组匹配明细行,替代/补充下方标志位匹配
|
||||
matched = PreferCategoryRows(matched, details, underlyingCategory);
|
||||
}
|
||||
|
||||
if (template.UnderlyingSeperateType == (int)UnderlyingSeperateTypeEnum.CustomInstrumentType
|
||||
@@ -157,6 +156,26 @@ namespace YLErp.Modules.MarginModule
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ETF 子类行优先匹配(纯函数,单测覆盖):
|
||||
/// termMatched 为期限档匹配结果(含精确档/BondTerm 空兜底),allDetails 为该模板当日全部明细行。
|
||||
/// 优先取 termMatched 中 EtfKind=category 的行;没有则取"allDetails 中 EtfKind=category 且 BondTerm 空"的子类不分档行;
|
||||
/// 都没有时原样返回 termMatched(基金通配行兜底)。
|
||||
/// </summary>
|
||||
public static List<margin_template_detail> PreferCategoryRows(List<margin_template_detail> termMatched,
|
||||
List<margin_template_detail> allDetails, string category)
|
||||
{
|
||||
var byCategory = termMatched.Where(x => x.SpanConfig != null && x.SpanConfig.EtfKind == category).ToList();
|
||||
if (byCategory.Any())
|
||||
{
|
||||
return byCategory;
|
||||
}
|
||||
var categoryWildcard = allDetails
|
||||
.Where(x => x.SpanConfig != null && x.SpanConfig.EtfKind == category && string.IsNullOrEmpty(x.SpanConfig.BondTerm))
|
||||
.ToList();
|
||||
return categoryWildcard.Count > 0 ? categoryWildcard : termMatched;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// R1 模板三层级找到即停解析(public 供集成测试与后续消费方复用):
|
||||
/// 1.交易绑定 trade_margin_template(自定义/录入时显式选择,ValueDate 最新 ≤ 业务日)——找到即停,
|
||||
@@ -348,12 +367,19 @@ namespace YLErp.Modules.MarginModule
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标的细分分类判定钩子(转债ETF/科创债ETF/中债指数等),public 供单元测试回归默认行为。
|
||||
/// 本期默认返回 null → 走通配行兜底,行为与现状一致;后续需求按业务给的判定规则(代码段/标的维护字段)实现。
|
||||
/// 标的细分分类判定钩子(ETF 子类,2026-08-24 实装):基金类标的返回标的维护页维护的
|
||||
/// underlying_manager.EtfSubType(取值来自数据字典"ETF 子类":国债 ETF/政金债 ETF/…/科创债 ETF/可转债 ETF,
|
||||
/// 基金类必填);非基金或未维护返回 null → 走标志位匹配/通配行兜底(债券/股票等行为与现状一致)。
|
||||
/// 后续其他细分(中债指数 IndexKind 等)在本方法内扩展。
|
||||
/// </summary>
|
||||
public static string GetUnderlyingCategory(string underlyingCode, string underlyingInstrumentType)
|
||||
{
|
||||
return null;
|
||||
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode);
|
||||
if (underlying == null || underlying.UnderlyingInstrumentType != ConsGlobal.InstrumentType.Fund)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return string.IsNullOrWhiteSpace(underlying.EtfSubType) ? null : underlying.EtfSubType.Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user