diff --git a/UnitTestProject/Modules/SwapModule/GLMS20260817Fr007UnwindMorningTest.cs b/UnitTestProject/Modules/SwapModule/GLMS20260817Fr007UnwindMorningTest.cs index a4c65c4b..57360ea2 100644 --- a/UnitTestProject/Modules/SwapModule/GLMS20260817Fr007UnwindMorningTest.cs +++ b/UnitTestProject/Modules/SwapModule/GLMS20260817Fr007UnwindMorningTest.cs @@ -452,6 +452,40 @@ namespace YLErp.Modules.SwapModule Assert.AreEqual(expectedStartDayInterest, w10.Fe.InterestAmount - w00.Fe.InterestAmount, 0.0000001m, "不算头(00)应恰好少计开始日一天利息(CalcFirst 回归锚)"); } + + // ── EOD 收盘归档路径(settment=true,此前全套件仅覆盖盘中 settment:false)── + // EOD 不取尾日价的依赖链:InitInterestDate 到期日回拨(endDate=D-1) + CalcEodInterest 的 + // calcToday=false(valueDate==到期日且不算尾) 整体跳过 ByEod 重算——ByEod 的取价 + // (CalcDailyCompoundInterestByEod/CalcDailySimpleInterestByEod 的 isResetDay→ResolveFloatRate) + // 不看 calcLast,任何一环回归都会让到期日收盘重新索要尾日 FR007。以下三例钉死该链。 + + [TestMethod] + public void Eod_NoTail_MaturityDayFr007Missing_Succeeds() + { + // 到期日=7/20(重置日)当天收盘,尾日价未发布 → 不算尾应放行(回拨+跳过重算两道闸) + AssertNoThrow(Run(InterestTypeEnum.复利, includeCloseDate: false, calcMode: "10", + exerciseDate: CloseDate, preEod: BuildPreEod(new DateTime(2026, 7, 13)), settment: true), + "EOD 不算尾(10)+到期日缺价 → 应放行(尾日不参与计息,不得取价)"); + } + + [TestMethod] + public void Eod_Tail_MaturityDayFr007Missing_StillThrows() + { + var o = Run(InterestTypeEnum.复利, includeCloseDate: false, calcMode: "11", + exerciseDate: CloseDate, preEod: BuildPreEod(new DateTime(2026, 7, 13)), settment: true); + Assert.IsTrue(o.Threw, "EOD 算尾(11)+到期日(重置日)缺价 → 应拦截(该日利率被消费)"); + StringAssert.Contains(o.Ex.Message, "FR007"); + } + + [TestMethod] + public void Eod_MidTradeResetDayFr007Missing_StillThrows() + { + // 非到期日的盘中重置日:不算尾也不豁免——新利率自当日起被持续持仓消费,ByEod 必须取到 + var o = Run(InterestTypeEnum.复利, includeCloseDate: false, calcMode: "10", + preEod: BuildPreEod(new DateTime(2026, 7, 13)), settment: true); + Assert.IsTrue(o.Threw, "EOD 不算尾(10)+非到期重置日(7/20)缺价 → 仍应拦截(ByEod 取价链,真实依赖)"); + StringAssert.Contains(o.Ex.Message, "FR007"); + } } }