using System; using System.Collections.Generic; using System.Linq; using YLErp.BLL; using YLErp.DBModels; using YLErp.Enums; using YLErp.Modules.UnderlyingModule; namespace YLErp.Modules.MarginModule { /// /// 预付金模板V2 取数帮助类:按交易绑定的模板(trade_margin_template → margin_template_v2 → margin_template_detail) /// 取 初始预付金率x / 维持预付金率y,供交易确认书、预付金计算等消费点统一使用。 /// 匹配维度:生效日期(ValueDate 最新)→ 利率债期限档(SpanConfig.BondTerm,四档,空=全部兜底)→ 标的资产类型(UnderlyingType 标志位)。 /// public static class MarginTemplateV2RateHelper { /// /// 取数结果。率已统一换算为小数(如 0.1 表示 10%),调用方直接用。 /// public class MarginRateResult { /// /// 命中的模板 /// public margin_template_v2 Template { get; set; } /// /// 命中的明细参数行(无预付金规则时为 null) /// public margin_template_detail Detail { get; set; } /// /// 初始预付金率 x(小数) /// public decimal? InitRate { get; set; } /// /// 维持预付金率 y(小数) /// public decimal? MaintainRate { get; set; } } /// /// 按交易绑定的模板取 初始/维持预付金率。 /// /// 交易ID /// 标的代码(用于计算利率债期限档) /// 标的资产类型(trade/swap_position 的 UnderlyingInstrumentType,如 TBonds) /// 业务日期 /// 命中返回结果;交易未绑定模板、模板无效、规则非 无预付金/区间追保结构、或明细无匹配行时返回 null(由调用方决定兜底) public static MarginRateResult GetTradeMarginRate(int tradeId, string underlyingCode, string underlyingInstrumentType, DateTime valueDate) { using (var db = new YLContext()) { return GetTradeMarginRate(tradeId, underlyingCode, underlyingInstrumentType, valueDate, db); } } /// /// 按交易绑定的模板取 初始/维持预付金率(调用方传入 DbContext,供批量场景复用连接)。 /// public static MarginRateResult GetTradeMarginRate(int tradeId, string underlyingCode, string underlyingInstrumentType, DateTime valueDate, YLContext db) { //1.交易绑定(ValueDate 最新) var binding = db.trade_margin_template.AsNoTracking() .Where(x => x.TradeId == tradeId && x.ValueDate <= valueDate) .OrderByDescending(x => x.ValueDate) .FirstOrDefault(); if (binding == null) { return null; } var template = db.margin_template_v2.AsNoTracking().FirstOrDefault(x => x.id == binding.MarginTemplateId); if (template == null || !template.IsValid) { return null; } //2.无预付金规则:率直接为 0 if (template.RuleType == (int)MarginRuleTypeEnum.无预付金) { return new MarginRateResult { Template = template, InitRate = 0m, MaintainRate = 0m }; } if (template.RuleType != (int)MarginRuleTypeEnum.区间追保结构) { //其他规则不在本帮助类支持范围,显式返回 null return null; } //3.区间追保结构:取 ValueDate 最新生效的一组明细(同一 ValueDate 下有多行参数组) var detailQuery = db.margin_template_detail.AsNoTracking() .Where(x => x.MarginTemplateId == template.id && x.ValueDate <= valueDate); if (!detailQuery.Any()) { return null; } var latestValueDate = detailQuery.Max(x => x.ValueDate); var details = detailQuery.Where(x => x.ValueDate == latestValueDate).ToList(); //4.利率债期限档匹配:精确档 → "全部"(BondTerm 为空)兜底 var term = UnderlyingHelper.GetApplicableMarginTerm(underlyingCode, valueDate); var matched = details.Where(x => x.SpanConfig != null && x.SpanConfig.BondTerm == term).ToList(); if (!matched.Any()) { matched = details.Where(x => x.SpanConfig == null || string.IsNullOrEmpty(x.SpanConfig.BondTerm)).ToList(); } if (!matched.Any()) { return null; } //5.标的资产类型匹配(仅当模板选了"按资产类型分类"):精确标志位 → 通配行(None/All)兜底 if (template.UnderlyingSeperateType == (int)UnderlyingSeperateTypeEnum.CustomInstrumentType && Enum.TryParse(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; } } }