From c42335363b4f89a4aae705c41565d2c3f569e35d Mon Sep 17 00:00:00 2001 From: hjhan Date: Mon, 17 Aug 2026 18:18:02 +0800 Subject: [PATCH] =?UTF-8?q?test(swap-eod):=20SwapInterestScenario3And4Floa?= =?UTF-8?q?tingTest=20=E7=9A=84=20TdInterestPrincipal=20=E6=94=B9=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E4=B8=8D=E5=8F=98=E9=87=8F=EF=BC=88=E5=B0=81=E6=AD=BB?= =?UTF-8?q?=E5=81=87=E7=BB=BF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 场景4 原 TdInterestPrincipal 断言 = 生产公式镜像(reverseMode2 ? base*(1-cp)/cp : base), 与生产 if(calcLast && mode2) TdInterestPrincipal *= (1-cp)/cp 逐字同构,永远跟自己一致, 故 mode9 被错误反推(GLMS-20260421-0004 膨胀 ~2.3x)时测试仍绿——假绿。 改为:mode9 用独立 else if 锁死 expected=LastBaseInterestPrincipal(反推前 base), 彻底脱离 reverseMode2 布尔拼写,封死重基线陷阱。已实跑证明:注入 mode9 反推 bug 后 唯一变红 T+1浮动减点算头算尾(实测 TdInterestPrincipal=494982903.27),回滚生产恢复 24/24。 零生产改动。 --- .../SwapInterestScenario3And4FloatingTest.cs | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/UnitTestProject/Modules/SwapModule/SwapInterestScenario3And4FloatingTest.cs b/UnitTestProject/Modules/SwapModule/SwapInterestScenario3And4FloatingTest.cs index 5bc338e8..e6a99ca7 100644 --- a/UnitTestProject/Modules/SwapModule/SwapInterestScenario3And4FloatingTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapInterestScenario3And4FloatingTest.cs @@ -492,19 +492,33 @@ namespace UnitTestProject.Modules.SwapModule _eod.RecordEod(partialEod); DebugCompare("场景4[部分] " + note, oraclePartial, partialEod.TdCloseInterest, partialEod); AssertStrict(oraclePartial, partialEod.TdCloseInterest, "场景4[部分] " + note); - // 覆盖 mode 2/9 分叉(SwapEodPositionService:1436-1469):部分平仓后 TdInterestPrincipal 的经济口径 - // 必须 = 剩余动态本金(剩余名义本金 + 已并入本金的重置日待实现利息),mode2/9 应当一致。 - // 单利:line 1491 直接取 posiNotionalValue = remainingNotional,无累计利息。 - // 复利:base = interests.First().InterestPrincipal(本服务 CalcSwapInterests 已捕获到 LastBaseInterestPrincipal); - // mode2 仅在 calcLast 时于 1464 行反推剩余(× (1-cp)/cp),mode9 直取 base(GLMS-20260421-0004 禁止反推)。 - // calcLast=false(如“算头不算尾”)或 mode9 被错误反推会膨胀 ~2.3 倍(494982903.27),下方断言精确拦截回归。 + // TdInterestPrincipal 独立经济不变量断言(取代原 reverseMode2 镜像布尔)。 + // 生产线路(SwapEodPositionService ~:1400-1453): + // 单利:直接 TdInterestPrincipal = posiNotionalValue = remainingNotional(无累计利息)。 + // 复利:base = 计息器 CalcSwapInterests 返回的 InterestPrincipal,已由本桩捕获为 LastBaseInterestPrincipal。 + // - mode9(标的期初全价):计息器已直接返回「剩余动态本金」,禁止任何 (1-cp)/cp 反推 + // (GLMS-20260421-0004:误反推会把 ~212135529.97 膨胀到 ~494982903.27)。 + // - mode2(合约名义本金规模)仅 calcLast 时 InterestPrincipal 为已平部分,需反推剩余 + // = base*(1-cp)/cp(经济恒等式 remaining = closed/cp − closed,非代码镜像)。 + // 下方用独立 if 锁死 mode9=base,不依赖 reverseMode2 布尔的拼写—— + // 重基线时即便把 reverseMode2 错写成含 mode9,mode9 仍走 base 分支,断言照红。 decimal expectedTdPrincipal; if (!compound) { expectedTdPrincipal = remainingNotional; } + else if (interestMode == (int)InterestModeEnum.标的期初全价) + { + // mode9 回归守卫(GLMS-20260421-0004):TdInterestPrincipal 必须等于反推前的 base; + // 任何 (1-cp)/cp 反推都会把 ~212M 剩余本金膨胀到 ~495M,此断言立即红。 + expectedTdPrincipal = _eod.LastBaseInterestPrincipal; + } else { + // mode2(合约名义本金规模):仅 calcLast 时 InterestPrincipal 为已平部分,需反推剩余 + // = base*(1-cp)/cp(经济恒等式 remaining = closed/cp − closed,非代码镜像)。 + // !calcLast 时生产走 usesFullPreviousEodPrincipal 分支(*= (1-cp)),本测因部分平仓前一日 eod + // 差 3 天使 Days==1 不成立而跳过,故此处取 base。 var cp = partialCloseNotional / Notional; // = 0.3,与 EOD 内部 closePercent 一致 bool reverseMode2 = interestMode == (int)InterestModeEnum.合约名义本金规模 && calcLast; expectedTdPrincipal = reverseMode2