diff --git a/YLErpDAL/Modules/SwapModule/Accrual/FundingLegAccrual.cs b/YLErpDAL/Modules/SwapModule/Accrual/FundingLegAccrual.cs index a621e489..cba457b8 100644 --- a/YLErpDAL/Modules/SwapModule/Accrual/FundingLegAccrual.cs +++ b/YLErpDAL/Modules/SwapModule/Accrual/FundingLegAccrual.cs @@ -1,4 +1,5 @@ using System; +using YLErp.Core.Interest; using YLErp.Derivatives.Interest; namespace YLErp.Modules.SwapModule.Accrual; @@ -35,6 +36,8 @@ public static class FundingLegAccrual /// 原始名义本金(orginPv),用于保证金腿差分基数。 /// 当日生效利率(已由适配器按腿型封装:固定腿=FixedRate,浮动腿=Spread+IndexFixing)。 /// 计息政策(daycount:是否年化 / 年化天数)。 + /// 本次日终计息对应的日期(用于 trace 标注"哪一天")。 + /// 可选追踪收集器;传 null 时行为与旧版完全一致(纯计算、无副作用)。 /// :Accrued=累计未实现(对应 InterestAmount),AccruedToday=当日利息(对应 TdInterestAmount)。 public static InterestResult AccrueSimpleEod( decimal priorUnrealized, @@ -43,7 +46,9 @@ public static class FundingLegAccrual decimal closeRatio, decimal originalPv, FundingLegRate rate, - AccrualPolicy policy) + AccrualPolicy policy, + DateTime eodDate, + InterestTrace? trace = null) { var baseTdInterestPrincipal = priorAccrualPrincipal + positionPrincipal - originalPv; var baseInterestPrincipal = baseTdInterestPrincipal * closeRatio; @@ -58,8 +63,13 @@ public static class FundingLegAccrual } var totalUnrealized = priorUnrealized + dayInterest; - return new InterestResult( + var result = new InterestResult( Math.Round(totalUnrealized, SwapInterest.FundingLegPrecision, MidpointRounding.AwayFromZero), Math.Round(tdInterest, SwapInterest.FundingLegPrecision, MidpointRounding.AwayFromZero)); + + // 单日追踪:当日利率 / 计息基数 / 当日利息 / 累计未实现。纯函数只产出收集器,落盘由适配器负责。 + trace?.Day(0, eodDate, combinedRate, baseInterestPrincipal, dayInterest, totalUnrealized); + trace?.MarkEnd(result.Accrued, result.AccruedToday); + return result; } } diff --git a/YLErpDAL/Modules/SwapModule/SwapCalcTrace.cs b/YLErpDAL/Modules/SwapModule/SwapCalcTrace.cs index 98d4378e..93dd6011 100644 --- a/YLErpDAL/Modules/SwapModule/SwapCalcTrace.cs +++ b/YLErpDAL/Modules/SwapModule/SwapCalcTrace.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using YLErp.Core.Interest; using YLErp.Helpers; namespace YLErp.Modules.SwapModule @@ -83,5 +84,17 @@ namespace YLErp.Modules.SwapModule public static string Dump() => string.Join(Environment.NewLine, GlobalLines); public static string DumpForRequest() => _reqBuf.Value?.ToString() ?? ""; + + /// + /// 把纯函数产出的 常驻落盘(关键路径日志)。 + /// 每条目经 写出——无条件落盘,与开关无关; + /// 开关打开时同时进内存 buffer 供实时查看 / 单测断言。这是事后 diff 新旧引擎的主通道。 + /// + public static void Persist(InterestTrace? trace) + { + if (trace == null) return; + foreach (var entry in trace.Entries) + Critical(entry.Line); + } } } diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index 818d1d3c..dd61e24f 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -3,6 +3,7 @@ using Newtonsoft.Json; using YLErp.BLL; using YLErp.BLL.Eod; using YLErp.DBModels.Enums; +using YLErp.Core.Interest; using YLErp.Derivatives.Interest; using YLErp.Helpers; using YLErp.Modules.DataProviderModule; @@ -1591,6 +1592,8 @@ namespace YLErp.Modules.SwapModule resetPeriodDays: position.interest_rest_days ?? 1, annualDays: annualDays, isAnnualized: position.IsAnnualized); + // 完整计息 trace:收集器由适配器创建,随后经 SwapCalcTrace 常驻落盘(关键路径日志,无条件)。 + var interestTrace = new InterestTrace(); var result = FundingLegAccrual.AccrueSimpleEod( priorUnrealized: preEodPosition.InterestProfitSum, priorAccrualPrincipal: preEodPosition.TdInterestPrincipal, @@ -1598,9 +1601,12 @@ namespace YLErp.Modules.SwapModule closeRatio: closePercent, originalPv: orginPv, rate: legRate, - policy: accrualPolicy); + policy: accrualPolicy, + eodDate: endDate, + trace: interestTrace); InterestAmount = result.Accrued; TdInterestAmount = result.AccruedToday; + SwapCalcTrace.Persist(interestTrace); } ///