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;
}
}
}