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 应线性递增 // ================================================================