From 57156feec1f8101be442cbfd98619ae273527c3d Mon Sep 17 00:00:00 2001 From: hjhan Date: Wed, 12 Aug 2026 13:37:40 +0800 Subject: [PATCH] =?UTF-8?q?refactor(accrual):=20=E6=8F=90=E5=8F=96ResolveF?= =?UTF-8?q?loatRate=E6=94=B6=E5=8F=A3FR007=E5=AE=9A=E7=9B=98=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EOD单日取率(CompoundEod/SimpleEod)与intraday多日取率(BuildSegmentRates) 原各有一份相同的GetFixingDate+TryGetFixing+throw逻辑(~8行/处,3处共24行)。 提取为私有 ResolveFloatRate(position, date, fallback): - 无浮动标的返回fallback; 取到非零fixing返回fixing; 取不到抛异常 - EOD: isResetDay ? ResolveFloatRate(...) : floateRate (1行替代12行) - BuildSegmentRates: 循环内直接调用(1行替代8行) 净减~15行, FR007定盘逻辑收口到一处 SwapModule零回归(7基线/510通过) --- .../Modules/SwapModule/SwapDealService.cs | 58 ++++++------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index 367cef46..376aa685 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -1326,6 +1326,19 @@ namespace YLErp.Modules.SwapModule return interest; } + /// + /// 按 interest_rule 取 FR007 定盘价。无浮动标的时返回 fallback;取不到抛异常。 + /// EOD 单日取率 + BuildSegmentRates 多日取率共用此方法,FR007 定盘逻辑收口到一处。 + /// + private decimal ResolveFloatRate(swap_position position, DateTime date, decimal fallback) + { + if (string.IsNullOrEmpty(position.FloatRateUnderlyingCode)) return fallback; + var fixingDate = IndexFixerBase.GetFixingDate(date, position.interest_rule); + if (IndexFixer.TryGetFixing(fixingDate, position.FloatRateUnderlyingCode, out decimal fixing)) + return fixing != 0m ? fixing : fallback; + throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{fixingDate:yyyy年MM月dd日}的价格"); + } + /// /// 按重置周期切分利率段,每段记录 all-in 利率(spread+fixing)。返回 (分段列表, 末段浮动利率)。 /// fetchAfterDate: 仅该日期之后的重置日才取 FR007(单利传 ValueDate,复利传 null 全程取)。 @@ -1341,19 +1354,8 @@ namespace YLErp.Modules.SwapModule for (int i = 0; i <= calcDays; i += interestPeriod) { var resetDate = startDate.AddDays(i); - if ((fetchAfterDate == null || resetDate > fetchAfterDate.Value) - && !string.IsNullOrEmpty(position.FloatRateUnderlyingCode)) - { - var fixingDate = IndexFixerBase.GetFixingDate(resetDate, position.interest_rule); - if (IndexFixer.TryGetFixing(fixingDate, position.FloatRateUnderlyingCode, out decimal fixing)) - { - if (fixing != 0m) currentFloat = fixing; - } - else - { - throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{fixingDate:yyyy年MM月dd日}的价格"); - } - } + if (fetchAfterDate == null || resetDate > fetchAfterDate.Value) + currentFloat = ResolveFloatRate(position, resetDate, currentFloat); rates.Add((resetDate, spread + currentFloat)); } return (rates, currentFloat); @@ -1467,19 +1469,7 @@ namespace YLErp.Modules.SwapModule // 重置日按 interest_rule 重新定盘浮动利率(GLMS-JIATT-20260805 根因—— // 重置日=平仓日必须用新利率,否则沿用旧周期利率并污染后续 EOD)。非重置日沿用 floateRate。 - decimal effectiveFloat = floateRate; - if (isResetDay && !string.IsNullOrEmpty(position.FloatRateUnderlyingCode)) - { - var fixingDate = IndexFixerBase.GetFixingDate(endDate, position.interest_rule); - if (IndexFixer.TryGetFixing(fixingDate, position.FloatRateUnderlyingCode, out decimal fixing)) - { - if (fixing != 0m) effectiveFloat = fixing; - } - else - { - throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{fixingDate:yyyy年MM月dd日}的价格"); - } - } + var effectiveFloat = isResetDay ? ResolveFloatRate(position, endDate, floateRate) : floateRate; flowEvent.FloatRate = effectiveFloat; // remainingFraction:重置日把上一日终待实现利息按本次平仓基数分摊(EOD 全量为 1)。 @@ -1537,21 +1527,9 @@ namespace YLErp.Modules.SwapModule // 取率:重置日按 interest_rule 重新定盘浮动利率(GLMS-JIATT-20260805 根因—— // 重置日=平仓日必须用新利率,否则沿用旧周期利率并污染后续 EOD)。 - decimal effectiveFloat = floateRate; int interestPeriod = position.interest_rest_days ?? 1; - if ((endDate - tradeDate).Days % interestPeriod == 0 - && !string.IsNullOrEmpty(position.FloatRateUnderlyingCode)) - { - var fixingDate = IndexFixerBase.GetFixingDate(endDate, position.interest_rule); - if (IndexFixer.TryGetFixing(fixingDate, position.FloatRateUnderlyingCode, out decimal fixing)) - { - if (fixing != 0m) effectiveFloat = fixing; - } - else - { - throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{fixingDate:yyyy年MM月dd日}的价格"); - } - } + var isResetDay = (endDate - tradeDate).Days % interestPeriod == 0; + var effectiveFloat = isResetDay ? ResolveFloatRate(position, endDate, floateRate) : floateRate; flowEvent.FloatRate = effectiveFloat;