From 65a367e139a49a89c43e4865dc1e06408eafe98c Mon Sep 17 00:00:00 2001 From: hjhan Date: Mon, 17 Aug 2026 17:43:25 +0800 Subject: [PATCH] =?UTF-8?q?test(swap-eod):=20=E8=A1=A5=20A=20=E4=B8=89?= =?UTF-8?q?=E4=B8=AA=E8=B7=AF=E7=94=B1=E5=88=86=E6=94=AF=E6=96=AD=E8=A8=80?= =?UTF-8?q?=20DI=5FBRANCH=5F003/004/005=EF=BC=88=E7=BB=8F=E7=9C=9F?= =?UTF-8?q?=E5=AE=9E=20DealInterests=20=E8=B7=AF=E7=94=B1=E5=99=A8?= =?UTF-8?q?=EF=BC=8C=E9=9B=B6=E7=94=9F=E4=BA=A7=E6=94=B9=E5=8A=A8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SwapModule/DealInterestsScenarioTest.cs | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs b/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs index f2ab23bc..cc13aedf 100644 --- a/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs +++ b/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs @@ -51,6 +51,8 @@ namespace YLErp.Modules.SwapModule public SwapDealService DealService { get; set; } public eod_swap_position LastInterestCalculationEodPosition { get; private set; } + public int LastEventType { get; set; } + public StubEodPositionService() : base(nameof(DealInterestsScenarioTest)) { @@ -71,6 +73,8 @@ namespace YLErp.Modules.SwapModule List closeList = null) { LastInterestCalculationEodPosition = eodPositions.SingleOrDefault(); + LastEventType = eventType; + if (AutoInterests != null) { return AutoInterests; @@ -522,6 +526,109 @@ namespace YLErp.Modules.SwapModule #endregion // ================================================================ + #region 场景2补充:剩余3分支路由断言(经真实 DealInterests 路由器) + + /// + /// [DI_BRANCH_003] 观察日无平仓(observationDay!=null, hasSwap=false, hasClose=false) + /// -> 走 SaveAutoEodInterestPosition(autoSwap 路径)。 + /// 守卫:CalcSwapInterests 收到 eventType=自动互换、tdClose=false。 + /// 补盖 TEST-MATRIX §6 的 AutoSettle 分支。 + /// + [TestMethod] + public void DI_BRANCH_003_观察日自动结息走SaveAutoEodInterestPosition() + { + var service = new StubEodPositionService(); + var td = CreateTrade(); + var position = CreateInterestPosition(); + var settleDate = new DateTime(2026, 5, 10); + var preEod = CreatePreEod(settleDate.AddDays(-1), DailyInterest); + + position.InterestSwapInterval = JsonConvert.SerializeObject(new List + { + new IntervalModel { Date = settleDate, Rate = FixedRate, Settlement = 1 } + }); + + service.ExecuteDealInterests( + new List { position }, + new List { preEod }, + settleDate, td, new List(), + Principal, 0m, 0m, 1m, Principal); + + Assert.IsTrue(service.PersistedPositions.Count > 0, "观察日应生成eod"); + Assert.AreEqual((int)SwapEventTypeEnum.自动互换, service.LastEventType, "观察日自动结息 eventType 应为自动互换"); + // 观察日自动结息走 SaveAutoEodInterestPosition(无平仓):TdCloseInterest 仅为当日利息,不被平仓放大 + Assert.IsTrue(service.PersistedPositions[0].TdCloseInterest < 0.1m, "观察日自动结息无平仓,TdCloseInterest 应仅为当日利息(<0.1),不应含平仓利息"); + Console.WriteLine("观察日自动结息分支 ✅ eventType=自动互换, tdClose=false"); + } + + /// + /// [DI_BRANCH_004] 观察日+平仓(observationDay!=null, hasClose=true) + /// -> 走 SaveAutoEodWithCloseInterestPosition(autoSwap:true)。 + /// 守卫:CalcSwapInterests 收到 eventType=自动互换、tdClose=true。 + /// 补盖 TEST-MATRIX §6 最弱格子(autoSwap=true 部分平仓)。 + /// + [TestMethod] + public void DI_BRANCH_004_观察日平仓走WithClose_autoSwapTrue() + { + var service = new StubEodPositionService(); + var td = CreateTrade(); + var position = CreateInterestPosition(); + var settleDate = new DateTime(2026, 5, 10); + var preEod = CreatePreEod(settleDate.AddDays(-1), DailyInterest * 13); + + position.InterestSwapInterval = JsonConvert.SerializeObject(new List + { + new IntervalModel { Date = settleDate, Rate = FixedRate, Settlement = 1 } + }); + var closeEvent = CreateSwapFlowEvent(settleDate, DailyInterest * 13); + closeEvent.EventType = (int)SwapFlowEventTypeEnum.平仓; + + service.ExecuteDealInterests( + new List { position }, + new List { preEod }, + settleDate, td, new List { closeEvent }, + Principal, 0m, 300m, 1m, Principal); + + Assert.IsTrue(service.PersistedPositions.Count > 0, "观察日+平仓应生成eod"); + Assert.AreEqual((int)SwapEventTypeEnum.自动互换, service.LastEventType, "autoSwap:true -> eventType 应为自动互换"); + // 含平仓:TdCloseInterest 应明显大于纯当日利息(实测约 0.38) + Assert.IsTrue(service.PersistedPositions[0].TdCloseInterest > 0.1m, "观察日+平仓 TdCloseInterest 应含平仓利息(>0.1)"); + Console.WriteLine("观察日+平仓分支 ✅ eventType=自动互换, TdCloseInterest>0.1 (autoSwap:true)"); + } + + /// + /// [DI_BRANCH_005] 非观察日+平仓(observationDay==null, hasClose=true, hasSwap=false) + /// -> 走 SaveAutoEodWithCloseInterestPosition(autoSwap:false)。 + /// 守卫:CalcSwapInterests 收到 eventType=平仓、tdClose=true。 + /// 补盖 TEST-MATRIX §6 的 CloseOnly 分支。 + /// + [TestMethod] + public void DI_BRANCH_005_纯平仓走WithClose_autoSwapFalse() + { + var service = new StubEodPositionService(); + var td = CreateTrade(); + var position = CreateInterestPosition(); + var settleDate = new DateTime(2026, 5, 10); + var preEod = CreatePreEod(settleDate.AddDays(-1), DailyInterest * 13); + + position.InterestSwapInterval = null; + var closeEvent = CreateSwapFlowEvent(settleDate, DailyInterest * 13); + closeEvent.EventType = (int)SwapFlowEventTypeEnum.平仓; + + service.ExecuteDealInterests( + new List { position }, + new List { preEod }, + settleDate, td, new List { closeEvent }, + Principal, 0m, 300m, 1m, Principal); + + Assert.IsTrue(service.PersistedPositions.Count > 0, "纯平仓应生成eod"); + Assert.AreEqual((int)SwapEventTypeEnum.平仓, service.LastEventType, "autoSwap:false -> eventType 应为平仓"); + Assert.IsTrue(service.PersistedPositions[0].TdCloseInterest > 0.1m, "纯平仓 TdCloseInterest 应含平仓利息(>0.1)"); + Console.WriteLine("纯平仓分支 ✅ eventType=平仓, TdCloseInterest>0.1 (autoSwap:false)"); + } + + #endregion + // 场景3:多日守恒——连续收盘归档,InterestIncomeSum 应线性递增 // ================================================================