From ef37c8e71d931130cc9614cc607ddfc71e8c8a8c Mon Sep 17 00:00:00 2001 From: hjhan Date: Fri, 14 Aug 2026 17:30:46 +0800 Subject: [PATCH] =?UTF-8?q?refactor(swap):=20=E5=90=88=E5=B9=B6=E5=A4=9A?= =?UTF-8?q?=E7=A9=BA=E5=90=8D=E4=B9=89=E6=9C=AC=E9=87=91=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E4=B8=BA=E5=8D=95=E4=B8=80=20posiTotalNotional=20=E5=B9=B6?= =?UTF-8?q?=E5=8A=A0=E5=9B=BA=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DealInterests 的 posiLongNotionalValue + posiShortNotionalValue 合并为 posiTotalNotional(调用点以 posiLongNotional+posiShortNotional 求和传入),净减一个参数 - SwapDealService / SwapEodPositionService / InterestCalcRequest 同步收敛多空死管道参数 - 19 个测试调用点适配新签名 - SwapEodPositionServiceIntegrationTest 参数计数断言由裸数字改为参数名集合断言(CollectionAssert.AreEquivalent,对增删/重排/改名敏感) --- .../SwapModule/BondTrsAutoSwapScenarioTest.cs | 2 +- .../ConsumedInterestScenarioTest.cs | 8 ++-- .../DealInterestsGoldenReplayTest.cs | 2 +- .../SwapModule/DealInterestsScenarioTest.cs | 38 ++++++++-------- .../GLMS20260703CloseInterestTest.cs | 2 +- .../GetInterestsEntrySemanticsTest.cs | 14 +++--- .../SwapModule/GetInterestsUnitTest_T0.cs | 8 ++-- .../SwapModule/GetInterestsUnitTest_T1.cs | 14 +++--- .../Margin/MarginInterestGoldenReplayTest.cs | 2 +- .../SwapModule/MultiStepConservationTest.cs | 12 +++--- .../PrepaidPrincipalCloseTraceTest.cs | 2 +- .../PrepaidPrincipalClosingChainTraceTest.cs | 2 +- ...wapCloseConversationCasesRegressionTest.cs | 2 +- .../SwapEodPositionServiceIntegrationTest.cs | 12 +++++- .../SwapInterestScenario1And2Test.cs | 8 ++-- .../SwapInterestScenario3And4FloatingTest.cs | 8 ++-- .../SwapPositionComposeScenarioTest.cs | 4 +- .../SwapSingleTradeVerificationTest.cs | 8 ++-- .../SwapUnwindPrepayPrincipalBugTdd.cs | 10 ++--- .../SwapUnwindSameDayDoublePartialTest.cs | 2 +- .../Modules/SwapModule/InterestCalcRequest.cs | 22 ++++------ .../Modules/SwapModule/SwapDealService.cs | 11 +---- .../SwapModule/SwapEodPositionService.cs | 43 +++++++++---------- 23 files changed, 116 insertions(+), 120 deletions(-) diff --git a/UnitTestProject/Modules/SwapModule/BondTrsAutoSwapScenarioTest.cs b/UnitTestProject/Modules/SwapModule/BondTrsAutoSwapScenarioTest.cs index a53dcffa..e42c8de3 100644 --- a/UnitTestProject/Modules/SwapModule/BondTrsAutoSwapScenarioTest.cs +++ b/UnitTestProject/Modules/SwapModule/BondTrsAutoSwapScenarioTest.cs @@ -145,7 +145,7 @@ namespace YLErp.Modules.SwapModule protected override List CalcSwapInterests( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false, List closeList = null) diff --git a/UnitTestProject/Modules/SwapModule/ConsumedInterestScenarioTest.cs b/UnitTestProject/Modules/SwapModule/ConsumedInterestScenarioTest.cs index c7bfc2f7..457de583 100644 --- a/UnitTestProject/Modules/SwapModule/ConsumedInterestScenarioTest.cs +++ b/UnitTestProject/Modules/SwapModule/ConsumedInterestScenarioTest.cs @@ -125,7 +125,7 @@ namespace YLErp.Modules.SwapModule var position = CreateCompoundPosition(); var interests = service.GetInterests(td, td.trade_extend, unwindDate, unwindDate, new List(), new List { position }, - Principal, Principal, Principal, Principal, closePercent, + Principal, Principal, closePercent, (int)SwapEventTypeEnum.平仓, false, Principal, add: false, settment: false, newCalcLast: false); Assert.AreEqual(1, interests.Count); @@ -356,7 +356,7 @@ namespace YLErp.Modules.SwapModule var interests = ServiceByDate().GetInterests(td, td.trade_extend, unwindDate, unwindDate, new List(), new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, add: false, settment: false, newCalcLast: false); @@ -420,7 +420,7 @@ namespace YLErp.Modules.SwapModule var result = service.GetInterests(td, td.trade_extend, resetDate, resetDate, new List { preEod }, new List { position }, - remainingPrincipal, remainingPrincipal, 0m, remainingPrincipal, 1m, + remainingPrincipal, remainingPrincipal, 1m, (int)SwapEventTypeEnum.平仓, true, remainingPrincipal, add: false, settment: false, newCalcLast: false).Single(); @@ -466,7 +466,7 @@ namespace YLErp.Modules.SwapModule var result = service.GetInterests(td, td.trade_extend, unwindDate, unwindDate, new List { preEod }, new List { position }, - remainingPrincipal, remainingPrincipal, 0m, remainingPrincipal, 1m, + remainingPrincipal, remainingPrincipal, 1m, (int)SwapEventTypeEnum.平仓, false, remainingPrincipal, add: false, settment: false, newCalcLast: false).Single(); diff --git a/UnitTestProject/Modules/SwapModule/DealInterestsGoldenReplayTest.cs b/UnitTestProject/Modules/SwapModule/DealInterestsGoldenReplayTest.cs index dafec3db..cc86d5be 100644 --- a/UnitTestProject/Modules/SwapModule/DealInterestsGoldenReplayTest.cs +++ b/UnitTestProject/Modules/SwapModule/DealInterestsGoldenReplayTest.cs @@ -47,7 +47,7 @@ namespace YLErp.Modules.SwapModule { DealInterests(interestList, eodPositions, new List(), settleDate, td, new List(), new List(), null, - posiLongNational, 0m, 0m, grossPrice, orginPv); + posiLongNational + 0m, 0m, grossPrice, orginPv); } } diff --git a/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs b/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs index c0b83382..079a6ba7 100644 --- a/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs +++ b/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs @@ -63,7 +63,7 @@ namespace YLErp.Modules.SwapModule trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, @@ -77,7 +77,7 @@ namespace YLErp.Modules.SwapModule } return (DealService ?? new SwapDealService(this)).GetInterests(td, tradeExtend, valueDate, unwindDate, - eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue, + eodPositions, positions, posiNotionalValue, closePosiNotionalValue, closePrecent, eventType, tdClose, orginPv, add, settment, newCalcLast, closeList); } @@ -99,7 +99,7 @@ namespace YLErp.Modules.SwapModule decimal orginPv = DealInterestsScenarioTest.Principal) { SaveAutoEodInterestPosition(eodPayPosition, null, position, td, valueDate, interval, - lastEodSwap, posiLongNotional, 0m, 1m, orginPv); + lastEodSwap, posiLongNotional + 0m, 1m, orginPv); return PersistedPositions.LastOrDefault(); } @@ -110,7 +110,7 @@ namespace YLErp.Modules.SwapModule decimal closeNotional, bool autoSwap) { SaveAutoEodWithCloseInterestPosition(eodPayPosition, null, position, td, valueDate, interval, - posiLongNotional, posiShortNotional, flowEvents, closeNotional, autoSwap, 1m, + posiLongNotional + posiShortNotional, flowEvents, closeNotional, autoSwap, 1m, DealInterestsScenarioTest.Principal); return PersistedPositions.LastOrDefault(); } @@ -121,7 +121,7 @@ namespace YLErp.Modules.SwapModule decimal grossPrice, decimal orginPv) { SaveEodInterestPositionCopy(eodPayPosition, null, valueDate, td, position, null, - false, posiLongNotional, posiShortNotional, grossPrice, orginPv); + false, posiLongNotional + posiShortNotional, grossPrice, orginPv); return PersistedPositions.LastOrDefault(); } @@ -134,7 +134,7 @@ namespace YLErp.Modules.SwapModule { DealInterests(interestList, eodPositions, new List(), settleDate, td, flowEvents, new List(), null, - posiLongNational, posiShortNational, closeNational, grossPrice, orginPv); + posiLongNational + posiShortNational, closeNational, grossPrice, orginPv); } } @@ -1229,7 +1229,7 @@ namespace YLErp.Modules.SwapModule var result = new SwapDealService(service).GetInterests( td, td.trade_extend, closeDate, closeDate, new List { previousEod }, new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, orginPv, false, settment: false, newCalcLast: false, closeList: null).Single(); @@ -1268,7 +1268,7 @@ namespace YLErp.Modules.SwapModule var firstCloseInterest = dealService.GetInterests( td, td.trade_extend, firstCloseDate, firstCloseDate, new List(), new List { position }, - originalNotional, originalNotional, 0m, remainingNotional, 0.5m, + originalNotional, remainingNotional, 0.5m, (int)SwapEventTypeEnum.平仓, false, originalNotional, settment: false).Single(); var firstCloseCash = Math.Round(firstCloseInterest.InterestAmount, ConsGlobal.MoneyRound, @@ -1286,13 +1286,13 @@ namespace YLErp.Modules.SwapModule var replayAtPreviousEod = dealService.GetInterests( td, td.trade_extend, firstCloseDate, firstCloseDate, new List(), new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, originalNotional, settment: false).Single(); var replayAtFinalClose = dealService.GetInterests( td, td.trade_extend, finalCloseDate, finalCloseDate, new List(), new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, originalNotional, settment: false).Single(); var expectedFinalInterest = firstCloseEod.InterestIncomeSum @@ -1306,7 +1306,7 @@ namespace YLErp.Modules.SwapModule var finalCloseInterest = dealService.GetInterests( td, td.trade_extend, finalCloseDate, finalCloseDate, new List { firstCloseEod }, new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, originalNotional, settment: false).Single(); var finalCloseCash = Math.Round(finalCloseInterest.InterestAmount, ConsGlobal.MoneyRound, @@ -1434,7 +1434,7 @@ namespace YLErp.Modules.SwapModule var partial = service.GetInterests( td, td.trade_extend, partialCloseDate, partialCloseDate, new List { previousEod }, new List { position }, - notional, notional, 0m, partialNotional, partialPercent, + notional, partialNotional, partialPercent, (int)SwapEventTypeEnum.平仓, false, notional, settment: false).Single(); AssertDecimal(84090.95m, Math.Round(partial.InterestAmount, ConsGlobal.MoneyRound, @@ -1444,7 +1444,7 @@ namespace YLErp.Modules.SwapModule var final = service.GetInterests( td, td.trade_extend, maturityDate, maturityDate, new List(), new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, remainingNotional, settment: false, newCalcLast: true).Single(); AssertDecimal(268428.73m, Math.Round(final.InterestAmount, ConsGlobal.MoneyRound, @@ -1575,7 +1575,7 @@ namespace YLErp.Modules.SwapModule var intermediateInterest = dealService.GetInterests( td, td.trade_extend, intermediateDate, intermediateDate, new List { partialEod }, new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, originalNotional, settment: false, newCalcLast: true).Single(); Assert.IsTrue(Math.Abs(259348.386714765m - intermediateInterest.InterestAmount) <= 0.01m, @@ -1706,7 +1706,7 @@ namespace YLErp.Modules.SwapModule var intermediateInterest = dealService.GetInterests( td, td.trade_extend, intermediateDate, intermediateDate, new List { partialEod }, new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, originalNotional, settment: false, newCalcLast: true).Single(); Assert.IsTrue(Math.Abs(259348.386714765m - intermediateInterest.InterestAmount) <= 0.01m, @@ -1739,7 +1739,7 @@ namespace YLErp.Modules.SwapModule var finalInterest = dealService.GetInterests( td, td.trade_extend, finalCloseDate, finalCloseDate, new List { intermediateEod }, new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, originalNotional, settment: false, newCalcLast: false).Single(); AssertDecimal(expectedFinalInterest, finalInterest.InterestAmount, @@ -1829,7 +1829,7 @@ namespace YLErp.Modules.SwapModule var result = dealService.GetInterests( td, td.trade_extend, finalCloseDate, finalCloseDate, new List { previousEod }, new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, remainingNotional, settment: false).Single(); @@ -1927,7 +1927,7 @@ namespace YLErp.Modules.SwapModule var partialInterest = dealService.GetInterests( td, td.trade_extend, partialCloseDate, partialCloseDate, new List { preCloseEod }, new List { position }, - originalNotional, originalNotional, 0m, partialNotional, partialClosePercent, + originalNotional, partialNotional, partialClosePercent, (int)SwapEventTypeEnum.平仓, false, originalNotional, settment: false).Single(); AssertExcelMoney(scenario.ExpectedPartialInterest, partialInterest.InterestAmount, @@ -1976,7 +1976,7 @@ namespace YLErp.Modules.SwapModule var finalInterest = dealService.GetInterests( td, td.trade_extend, finalCloseDate, finalCloseDate, new List { finalPreEod }, new List { position }, - remainingNotional, remainingNotional, 0m, remainingNotional, 1m, + remainingNotional, remainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, remainingNotional, settment: false).Single(); AssertExcelMoney(scenario.ExpectedFinalInterest, finalInterest.InterestAmount, diff --git a/UnitTestProject/Modules/SwapModule/GLMS20260703CloseInterestTest.cs b/UnitTestProject/Modules/SwapModule/GLMS20260703CloseInterestTest.cs index ccd5c26d..398c8b3a 100644 --- a/UnitTestProject/Modules/SwapModule/GLMS20260703CloseInterestTest.cs +++ b/UnitTestProject/Modules/SwapModule/GLMS20260703CloseInterestTest.cs @@ -209,7 +209,7 @@ namespace YLErp.Modules.SwapModule CloseDate, CloseDate, // valueDate / unwindDate new List(), // eodPositions(空) new List { position }, - Notional, Notional, Notional, Notional, // posiNotional / long / short / closePosiNotional + Notional, Notional, // posiNotional / closePosiNotional 1m, // closePercent (int)SwapEventTypeEnum.平仓, false, Notional, // tdClose / orginPv diff --git a/UnitTestProject/Modules/SwapModule/GetInterestsEntrySemanticsTest.cs b/UnitTestProject/Modules/SwapModule/GetInterestsEntrySemanticsTest.cs index 46f8f1e4..b3d1ed58 100644 --- a/UnitTestProject/Modules/SwapModule/GetInterestsEntrySemanticsTest.cs +++ b/UnitTestProject/Modules/SwapModule/GetInterestsEntrySemanticsTest.cs @@ -142,11 +142,11 @@ namespace YLErp.Modules.SwapModule var intraday = CreateService().GetIntradayUnwindInterests(InterestCalcRequest.IntradayUnwind( td, td.trade_extend, UnwindDate, UnwindDate, eodPositions, positions, - PreClose, PreClose, 0m, Closed, ClosePercent, + PreClose, Closed, ClosePercent, (int)SwapEventTypeEnum.平仓, tdClose: true, orginPv: PreClose, add: true, newCalcLast: false, closeList: null)); var eodPostClose = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate, - eodPositions, positions, Remaining, Remaining, 0m, Closed, 1m, + eodPositions, positions, Remaining, Closed, 1m, (int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose, add: true, settment: false, newCalcLast: false, closeList: null); @@ -177,11 +177,11 @@ namespace YLErp.Modules.SwapModule var intraday = CreateService().GetIntradayUnwindInterests(InterestCalcRequest.IntradayUnwind( td, td.trade_extend, UnwindDate, UnwindDate, eodPositions, positions, - PreClose, PreClose, 0m, Closed, ClosePercent, + PreClose, Closed, ClosePercent, (int)SwapEventTypeEnum.平仓, tdClose: true, orginPv: PreClose, add: true, newCalcLast: false, closeList: null)); var eodPostClose = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate, - eodPositions, positions, Remaining, Remaining, 0m, Closed, 1m, + eodPositions, positions, Remaining, Closed, 1m, (int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose, add: true, settment: false, newCalcLast: false, closeList: null); @@ -209,7 +209,7 @@ namespace YLErp.Modules.SwapModule // 全平:剩余=0,平掉=全部 1000 var result = CreateService().GetInterests(td, td.trade_extend, UnwindDate, UnwindDate, - eodPositions, positions, 0m, 0m, 0m, PreClose, 1m, + eodPositions, positions, 0m, PreClose, 1m, (int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose, add: true, settment: false, newCalcLast: false, closeList: null); @@ -244,7 +244,7 @@ namespace YLErp.Modules.SwapModule trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, @@ -282,7 +282,7 @@ namespace YLErp.Modules.SwapModule var req = InterestCalcRequest.EodPostCloseSettle( td, td.trade_extend, UnwindDate, UnwindDate, new List { preEod }, positions, - remainingNotionalAfterClose: Remaining, remainingLongNotional: Remaining, remainingShortNotional: 0m, + remainingNotionalAfterClose: Remaining, closedNotional: Closed, eventType: (int)SwapEventTypeEnum.平仓, tdClose: false, orginPv: PreClose, add: true, newCalcLast: false); diff --git a/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest_T0.cs b/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest_T0.cs index c4aad82c..7a590d08 100644 --- a/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest_T0.cs +++ b/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest_T0.cs @@ -228,7 +228,7 @@ namespace YLErp.Modules.SwapModule var position = CreateFloatInterestPosition(interestRule, interestType, fixedRate); var interests = _service.GetInterests(td, td.trade_extend, valueDate, unwindDate, eodPositions, new List { position }, - posiNotional, posiNotional, posiNotional, posiNotional, closePercent, + posiNotional, posiNotional, closePercent, (int)SwapEventTypeEnum.平仓, false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList); AssertInterestEqual(1, interests.Count); @@ -244,7 +244,7 @@ namespace YLErp.Modules.SwapModule var position = CreateFloatInterestPosition(interestRule, interestType, fixedRate); var interests = _service.GetInterests(td, td.trade_extend, valueDate, valueDate, eodPositions, new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, false, settment: true, newCalcLast: false, closeList: closeList); AssertInterestEqual(1, interests.Count); @@ -263,7 +263,7 @@ namespace YLErp.Modules.SwapModule var position = CreateFixedInterestPosition(fixedRate, interestRule); var interests = _service.GetInterests(td, td.trade_extend, valueDate, unwindDate, eodPositions, new List { position }, - posiNotional, posiNotional, posiNotional, posiNotional, closePercent, + posiNotional, posiNotional, closePercent, (int)SwapEventTypeEnum.平仓, false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList); AssertInterestEqual(1, interests.Count); @@ -279,7 +279,7 @@ namespace YLErp.Modules.SwapModule var position = CreateFixedInterestPosition(fixedRate, interestRule); var interests = _service.GetInterests(td, td.trade_extend, valueDate, valueDate, eodPositions, new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, false, settment: true, newCalcLast: false, closeList: closeList); AssertInterestEqual(1, interests.Count); diff --git a/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest_T1.cs b/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest_T1.cs index 672e80bb..93a26203 100644 --- a/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest_T1.cs +++ b/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest_T1.cs @@ -322,7 +322,7 @@ namespace YLErp.Modules.SwapModule valueDate, unwindDate, eodPositions, new List { position }, - posiNotional, posiNotional, posiNotional, posiNotional, closePercent, + posiNotional, posiNotional, closePercent, (int)SwapEventTypeEnum.平仓, false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList); @@ -346,7 +346,7 @@ namespace YLErp.Modules.SwapModule valueDate, valueDate, eodPositions, new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, false, settment: true, newCalcLast: false, closeList: closeList); @@ -371,7 +371,7 @@ namespace YLErp.Modules.SwapModule valueDate, valueDate, eodPositions, new List { position }, - Principal, Principal, Principal, Principal, closePercent, + Principal, Principal, closePercent, (int)SwapEventTypeEnum.自动互换, false, Principal, false, settment: false, newCalcLast: false, closeList: closeList); @@ -407,7 +407,7 @@ namespace YLErp.Modules.SwapModule valueDate, unwindDate, eodPositions, new List { position }, - posiNotional, posiNotional, posiNotional, posiNotional, closePercent, + posiNotional, posiNotional, closePercent, (int)SwapEventTypeEnum.平仓, false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList); @@ -430,7 +430,7 @@ namespace YLErp.Modules.SwapModule valueDate, valueDate, eodPositions, new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, false, settment: true, newCalcLast: false, closeList: closeList); @@ -1716,7 +1716,7 @@ namespace YLErp.Modules.SwapModule valueDate, unwindDate, eodPositions, new List { position }, - posiNotional, posiNotional, posiNotional, posiNotional, closePercent, + posiNotional, posiNotional, closePercent, (int)SwapEventTypeEnum.平仓, false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList); @@ -1747,7 +1747,7 @@ namespace YLErp.Modules.SwapModule valueDate, unwindDate, eodPositions, new List { position }, - posiNotional, posiNotional, posiNotional, posiNotional, closePercent, + posiNotional, posiNotional, closePercent, (int)SwapEventTypeEnum.平仓, false, posiNotional, false, settment: false, newCalcLast: newCalcLast, closeList: closeList); diff --git a/UnitTestProject/Modules/SwapModule/Margin/MarginInterestGoldenReplayTest.cs b/UnitTestProject/Modules/SwapModule/Margin/MarginInterestGoldenReplayTest.cs index 62c948dc..e9816011 100644 --- a/UnitTestProject/Modules/SwapModule/Margin/MarginInterestGoldenReplayTest.cs +++ b/UnitTestProject/Modules/SwapModule/Margin/MarginInterestGoldenReplayTest.cs @@ -99,7 +99,7 @@ namespace UnitTestProject.Modules.SwapModule.Margin { oldList = svc.GetInterests(td, extend, valueDate, valueDate, preEods, marginPositions, - 0m, 0m, 0m, 0m, 1.0m, + 0m, 0m, 1.0m, (int)SwapEventTypeEnum.自动互换, tdClose: false, orginPv: 0m, add: false, settment: true, newCalcLast: false, closeList: null); diff --git a/UnitTestProject/Modules/SwapModule/MultiStepConservationTest.cs b/UnitTestProject/Modules/SwapModule/MultiStepConservationTest.cs index 12196bdd..8ea6d60b 100644 --- a/UnitTestProject/Modules/SwapModule/MultiStepConservationTest.cs +++ b/UnitTestProject/Modules/SwapModule/MultiStepConservationTest.cs @@ -119,7 +119,7 @@ namespace YLErp.Modules.SwapModule var position = CreateInterestPosition(); var interests = service.GetInterests(td, td.trade_extend, unwindDate, unwindDate, new List(), new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, add: false, settment: false, newCalcLast: false); return interests.Count > 0 ? interests[0].InterestAmount : 0m; @@ -142,7 +142,7 @@ namespace YLErp.Modules.SwapModule }; var interests = service.GetInterests(td, td.trade_extend, valueDate, valueDate, new List { preEod }, new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, add: false, settment: true, newCalcLast: false); if (interests.Count == 0) return (0m, 0m); @@ -313,7 +313,7 @@ namespace YLErp.Modules.SwapModule var svc5 = new StubDealService(0m, floatRate: 0.001); var i5 = svc5.GetInterests(td, td.trade_extend, day5, day5, new List(), new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, settment: false); decimal swap1 = i5.Count > 0 ? i5[0].InterestAmount : 0m; @@ -322,7 +322,7 @@ namespace YLErp.Modules.SwapModule var svc10 = new StubDealService(swap1, floatRate: 0.001); var i10 = svc10.GetInterests(td, td.trade_extend, day10, day10, new List(), new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, settment: false); decimal swap2 = i10.Count > 0 ? i10[0].InterestAmount : 0m; @@ -332,7 +332,7 @@ namespace YLErp.Modules.SwapModule var svc15 = new StubDealService(totalConsumed, floatRate: 0.001); var i15 = svc15.GetInterests(td, td.trade_extend, day15, day15, new List(), new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, settment: false); decimal finalUnwind = i15.Count > 0 ? i15[0].InterestAmount : 0m; @@ -362,7 +362,7 @@ namespace YLErp.Modules.SwapModule var svc = new StubDealService(0m, floatRate: 0.001); var interests = svc.GetInterests(td, td.trade_extend, unwindDate, unwindDate, new List(), new List { position }, - Principal, Principal, Principal, Principal, 1m, + Principal, Principal, 1m, (int)SwapEventTypeEnum.平仓, false, Principal, settment: false); return interests.Count > 0 ? interests[0].InterestAmount : 0m; diff --git a/UnitTestProject/Modules/SwapModule/PrepaidPrincipalCloseTraceTest.cs b/UnitTestProject/Modules/SwapModule/PrepaidPrincipalCloseTraceTest.cs index fdfeb04c..37c50207 100644 --- a/UnitTestProject/Modules/SwapModule/PrepaidPrincipalCloseTraceTest.cs +++ b/UnitTestProject/Modules/SwapModule/PrepaidPrincipalCloseTraceTest.cs @@ -103,7 +103,7 @@ namespace YLErp.Modules.SwapModule SwapCalcTrace.Reset(); var eod = new List { MakeEod(valueDate, PrepayRemaining, 0m) }; var fe = _svc.GetInterests(td, td.trade_extend, FullDate, FullDate, eod, - new List { pos }, PrepayFix, PrepayFix, PrepayFix, PrepayFix, 1m, + new List { pos }, PrepayFix, PrepayFix, 1m, (int)SwapEventTypeEnum.平仓, false, PrepayFix, false, settment: false, newCalcLast: calcLast, closeList: null)[0]; var trace = SwapCalcTrace.Dump(); diff --git a/UnitTestProject/Modules/SwapModule/PrepaidPrincipalClosingChainTraceTest.cs b/UnitTestProject/Modules/SwapModule/PrepaidPrincipalClosingChainTraceTest.cs index 44e9f844..ad3a7182 100644 --- a/UnitTestProject/Modules/SwapModule/PrepaidPrincipalClosingChainTraceTest.cs +++ b/UnitTestProject/Modules/SwapModule/PrepaidPrincipalClosingChainTraceTest.cs @@ -101,7 +101,7 @@ namespace YLErp.Modules.SwapModule protected override List CalcSwapInterests( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false, List closeList = null) diff --git a/UnitTestProject/Modules/SwapModule/SwapCloseConversationCasesRegressionTest.cs b/UnitTestProject/Modules/SwapModule/SwapCloseConversationCasesRegressionTest.cs index e4abce0b..0d6afc17 100644 --- a/UnitTestProject/Modules/SwapModule/SwapCloseConversationCasesRegressionTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapCloseConversationCasesRegressionTest.cs @@ -80,7 +80,7 @@ namespace YLErp.Modules.SwapModule var result = service.GetInterests( trade, trade.trade_extend, closeCase.CloseDate, closeCase.CloseDate, new List { previousEod }, new List { position }, - closeCase.RemainingNotional, closeCase.RemainingNotional, 0m, + closeCase.RemainingNotional, closeCase.RemainingNotional, 1m, (int)SwapEventTypeEnum.平仓, false, closeCase.InterestType == 0 ? closeCase.RemainingNotional : closeCase.OriginalNotional, diff --git a/UnitTestProject/Modules/SwapModule/SwapEodPositionServiceIntegrationTest.cs b/UnitTestProject/Modules/SwapModule/SwapEodPositionServiceIntegrationTest.cs index ee7235e3..b4ab66bf 100644 --- a/UnitTestProject/Modules/SwapModule/SwapEodPositionServiceIntegrationTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapEodPositionServiceIntegrationTest.cs @@ -1,3 +1,4 @@ +using System.Linq; using System.Reflection; using YLErp.DBModels.Enums; @@ -272,7 +273,16 @@ namespace YLErp.Modules.SwapModule Console.WriteLine($" ✓ {scenario.Scenario}"); } - Assert.AreEqual(13, parameters.Length, "DealInterests应有13个参数"); + // 校验参数集合(按名称,对参数增删/重排/改名均敏感,比裸数字更稳) + var expectedParamNames = new[] + { + "interestList", "eodPositions", "todyEodPositions", "settleDate", + "td", "flowEvents", "autoInterests", "lastEodSwap", + "posiTotalNotional", "closeNational", "grossPrice", "orginPv" + }; + var actualParamNames = parameters.Select(p => p.Name).ToArray(); + CollectionAssert.AreEquivalent(expectedParamNames, actualParamNames, + "DealInterests 参数集合应与预期一致(新增/重排/改名参数时请同步更新此列表)"); Console.WriteLine("✅ 分支覆盖分析完成"); } } diff --git a/UnitTestProject/Modules/SwapModule/SwapInterestScenario1And2Test.cs b/UnitTestProject/Modules/SwapModule/SwapInterestScenario1And2Test.cs index 12b3941d..9d1e4c59 100644 --- a/UnitTestProject/Modules/SwapModule/SwapInterestScenario1And2Test.cs +++ b/UnitTestProject/Modules/SwapModule/SwapInterestScenario1And2Test.cs @@ -56,7 +56,7 @@ namespace UnitTestProject.Modules.SwapModule protected override List CalcSwapInterests( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false, List closeList = null) @@ -64,7 +64,7 @@ namespace UnitTestProject.Modules.SwapModule var svc = new StubSwapDealService( new OptUserInfo(0, nameof(SwapInterestScenario1And2Test), OptUserFrom.UnitTest), _floatRates); return svc.GetInterests(td, tradeExtend, valueDate, unwindDate, - eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue, + eodPositions, positions, posiNotionalValue, closePosiNotionalValue, closePrecent, eventType, tdClose, orginPv, add, settment, newCalcLast, closeList); } @@ -74,7 +74,7 @@ namespace UnitTestProject.Modules.SwapModule List flowEvents, decimal closeNotional, eod_swap_position prevEod) { SaveAutoEodWithCloseInterestPosition(prevEod, null, position, td, valueDate, null, - posiLongNotional, posiShortNotional, flowEvents, closeNotional, false, 1m, + posiLongNotional + posiShortNotional, flowEvents, closeNotional, false, 1m, posiLongNotional + posiShortNotional); return PersistedPositions.LastOrDefault(); } @@ -211,7 +211,7 @@ namespace UnitTestProject.Modules.SwapModule var interests = svc.GetInterests( td, td.trade_extend, valueDate, valueDate, prevEod, new List { position }, - closeNotional, closeNotional, 0m, closeNotional, 1m, + closeNotional, closeNotional, 1m, (int)SwapEventTypeEnum.平仓, false, closeNotional, false, settment: false, newCalcLast: isMaturity); Assert.AreEqual(1, interests.Count); diff --git a/UnitTestProject/Modules/SwapModule/SwapInterestScenario3And4FloatingTest.cs b/UnitTestProject/Modules/SwapModule/SwapInterestScenario3And4FloatingTest.cs index a86c20e4..5bc338e8 100644 --- a/UnitTestProject/Modules/SwapModule/SwapInterestScenario3And4FloatingTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapInterestScenario3And4FloatingTest.cs @@ -178,7 +178,7 @@ namespace UnitTestProject.Modules.SwapModule protected override List CalcSwapInterests( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false, List closeList = null) @@ -186,7 +186,7 @@ namespace UnitTestProject.Modules.SwapModule var svc = new RealSwapDealService( new OptUserInfo(0, nameof(SwapInterestScenario3And4FloatingTest), OptUserFrom.UnitTest), _floatRates, FlowEvents); var interests = svc.GetInterests(td, tradeExtend, valueDate, unwindDate, - eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue, + eodPositions, positions, posiNotionalValue, closePosiNotionalValue, closePrecent, eventType, tdClose, orginPv, add, settment, newCalcLast, closeList); // 捕获 base InterestPrincipal(= EOD:1406 行赋给 TdInterestPrincipal 的值,反推前),供 TdInterestPrincipal 断言镜像分叉。 @@ -226,7 +226,7 @@ namespace UnitTestProject.Modules.SwapModule List flowEvents, decimal closeNotional, eod_swap_position prevEod) { SaveAutoEodWithCloseInterestPosition(prevEod, null, position, _td, valueDate, null, - posiLongNotional, posiShortNotional, flowEvents, closeNotional, false, 1m, + posiLongNotional + posiShortNotional, flowEvents, closeNotional, false, 1m, posiLongNotional + posiShortNotional); return PersistedPositions.LastOrDefault(); } @@ -394,7 +394,7 @@ namespace UnitTestProject.Modules.SwapModule var interests = svc.GetInterests( td, td.trade_extend, valueDate, valueDate, prevEod, new List { position }, - closeNotional, closeNotional, 0m, closeNotional, 1m, + closeNotional, closeNotional, 1m, (int)SwapEventTypeEnum.平仓, false, closeNotional, false, settment: false, newCalcLast: isMaturity); Assert.AreEqual(1, interests.Count); diff --git a/UnitTestProject/Modules/SwapModule/SwapPositionComposeScenarioTest.cs b/UnitTestProject/Modules/SwapModule/SwapPositionComposeScenarioTest.cs index 166bd4dc..708ac5cf 100644 --- a/UnitTestProject/Modules/SwapModule/SwapPositionComposeScenarioTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapPositionComposeScenarioTest.cs @@ -79,14 +79,14 @@ namespace YLErp.Modules.SwapModule protected override List CalcSwapInterests( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false, List closeList = null) { LastInterestCalculationPositions = positions; return base.CalcSwapInterests(td, tradeExtend, valueDate, unwindDate, - eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue, + eodPositions, positions, posiNotionalValue, closePosiNotionalValue, closePrecent, eventType, tdClose, orginPv, add, settment, newCalcLast, closeList); } diff --git a/UnitTestProject/Modules/SwapModule/SwapSingleTradeVerificationTest.cs b/UnitTestProject/Modules/SwapModule/SwapSingleTradeVerificationTest.cs index f4ddee13..ceb2976d 100644 --- a/UnitTestProject/Modules/SwapModule/SwapSingleTradeVerificationTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapSingleTradeVerificationTest.cs @@ -59,7 +59,7 @@ namespace UnitTestProject.Modules.SwapModule protected override List CalcSwapInterests( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, bool add = false, bool settment = true, bool newCalcLast = false, List closeList = null) @@ -67,7 +67,7 @@ namespace UnitTestProject.Modules.SwapModule var svc = new StubSwapDealService( new OptUserInfo(0, nameof(SwapSingleTradeVerificationTest), OptUserFrom.UnitTest), _floatRates); return svc.GetInterests(td, tradeExtend, valueDate, unwindDate, - eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue, + eodPositions, positions, posiNotionalValue, closePosiNotionalValue, closePrecent, eventType, tdClose, orginPv, add, settment, newCalcLast, closeList); } @@ -77,7 +77,7 @@ namespace UnitTestProject.Modules.SwapModule List flowEvents, decimal closeNotional, eod_swap_position prevEod) { SaveAutoEodWithCloseInterestPosition(prevEod, null, position, td, valueDate, null, - posiLongNotional, posiShortNotional, flowEvents, closeNotional, false, 1m, + posiLongNotional + posiShortNotional, flowEvents, closeNotional, false, 1m, posiLongNotional + posiShortNotional); return PersistedPositions.LastOrDefault(); } @@ -213,7 +213,7 @@ namespace UnitTestProject.Modules.SwapModule var interests = svc.GetInterests( td, td.trade_extend, valueDate, valueDate, prevEod, new List { position }, - closeNotional, closeNotional, 0m, closeNotional, 1m, + closeNotional, closeNotional, 1m, (int)SwapEventTypeEnum.平仓, false, closeNotional, false, settment: false, newCalcLast: isMaturity); Assert.AreEqual(1, interests.Count); diff --git a/UnitTestProject/Modules/SwapModule/SwapUnwindPrepayPrincipalBugTdd.cs b/UnitTestProject/Modules/SwapModule/SwapUnwindPrepayPrincipalBugTdd.cs index d29a3e80..cf01b63b 100644 --- a/UnitTestProject/Modules/SwapModule/SwapUnwindPrepayPrincipalBugTdd.cs +++ b/UnitTestProject/Modules/SwapModule/SwapUnwindPrepayPrincipalBugTdd.cs @@ -93,7 +93,7 @@ namespace YLErp.Modules.SwapModule var position = MakePrepayPosition(); var interests = _svc.GetInterests(td, td.trade_extend, UnwindDate, UnwindDate, eodPositions, new List { position }, - UnderlyingNotional, UnderlyingNotional, UnderlyingNotional, UnderlyingNotional, closePercent, + UnderlyingNotional, UnderlyingNotional, closePercent, (int)SwapEventTypeEnum.平仓, false, UnderlyingNotional, false, settment: false, newCalcLast: false, closeList: null); Assert.AreEqual(1, interests.Count, "预付金腿应生成 1 条 flow_event"); @@ -111,7 +111,7 @@ namespace YLErp.Modules.SwapModule var position = MakePrepayPosition(fix, rate); var interests = _svc.GetInterests(td, td.trade_extend, UnwindDate, UnwindDate, eodPositions, new List { position }, - notional, notional, notional, notional, closePercent, + notional, notional, closePercent, (int)SwapEventTypeEnum.平仓, false, notional, false, settment: false, newCalcLast: false, closeList: null); Assert.AreEqual(1, interests.Count, "预付金腿应生成 1 条 flow_event"); @@ -279,7 +279,7 @@ namespace YLErp.Modules.SwapModule }; var interests = _svc.GetInterests(td, td.trade_extend, ProdUnwindDate, ProdUnwindDate, eod, new List { position }, - fix, fix, fix, fix, closePercent, + fix, fix, closePercent, (int)SwapEventTypeEnum.平仓, false, fix, false, settment: false, newCalcLast: false, closeList: null); Assert.AreEqual(1, interests.Count, "预付金腿应生成 1 条 flow_event"); @@ -373,7 +373,7 @@ namespace YLErp.Modules.SwapModule // orginPv 传 notional:非预付金腿不走 877-881 的 Fix 对齐,dynomicPrincipal = notional + notional - notional = notional var interests = _svc.GetInterests(td, td.trade_extend, ProdUnwindDate, ProdUnwindDate, eod, new List { position }, - notional, notional, notional, notional * closePercent, closePercent, + notional, notional * closePercent, closePercent, (int)SwapEventTypeEnum.平仓, false, notional, false, settment: false, newCalcLast: false, closeList: null); Assert.AreEqual(1, interests.Count, "非预付金腿应生成 1 条 flow_event"); @@ -488,7 +488,7 @@ namespace YLErp.Modules.SwapModule }; var interests = _svc.GetInterests(td, td.trade_extend, ProdUnwindDate, ProdUnwindDate, eodPos, new List { position }, - baseP, baseP, baseP, baseP * closePercent, closePercent, + baseP, baseP * closePercent, closePercent, (int)SwapEventTypeEnum.平仓, false, baseP, false, settment: eodPath, newCalcLast: false, closeList: null); Assert.AreEqual(1, interests.Count, $"mode={mode} 应生成 1 条 flow_event"); diff --git a/UnitTestProject/Modules/SwapModule/SwapUnwindSameDayDoublePartialTest.cs b/UnitTestProject/Modules/SwapModule/SwapUnwindSameDayDoublePartialTest.cs index 27a957f8..5e03e9c6 100644 --- a/UnitTestProject/Modules/SwapModule/SwapUnwindSameDayDoublePartialTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapUnwindSameDayDoublePartialTest.cs @@ -121,7 +121,7 @@ namespace YLErp.Modules.SwapModule var position = MakePosition(currentNotional); var interests = _svc.GetInterests(td, td.trade_extend, UnwindDate, UnwindDate, MakeLastEod(), new List { position }, - currentNotional, currentNotional, currentNotional, currentNotional * closePercent, closePercent, + currentNotional, currentNotional * closePercent, closePercent, (int)SwapEventTypeEnum.平仓, false, N, false, settment: false, newCalcLast: false, closeList: null); Assert.AreEqual(1, interests.Count, "标的期初全价腿应生成 1 条 flow_event"); diff --git a/YLErpDAL/Modules/SwapModule/InterestCalcRequest.cs b/YLErpDAL/Modules/SwapModule/InterestCalcRequest.cs index 1be9364d..fcaff397 100644 --- a/YLErpDAL/Modules/SwapModule/InterestCalcRequest.cs +++ b/YLErpDAL/Modules/SwapModule/InterestCalcRequest.cs @@ -8,7 +8,8 @@ namespace YLErp.Modules.SwapModule; /// GetInterestsEntrySemanticsTest 的口径留档),位置参数无法表达该约束。 /// /// 用法:只能经两个场景工厂构造——工厂形参名即该场景语义(平仓前剩余 / 平仓后剩余 / 实际平掉额), -/// 物理上防止两套语义混传。needPrice/grossPrice 为原方法死参数(体内零消费),本对象不承载。 +/// 物理上防止两套语义混传。needPrice/grossPrice(原方法死参数)与 posiLong/posiShortNotionalValue +/// (多空组合子系统删除后计息链零消费的管道死参数)均不承载。 /// public sealed class InterestCalcRequest { @@ -21,8 +22,6 @@ public sealed class InterestCalcRequest /// 当日适用名义本金。语义随场景:盘中=平仓【前】剩余;EOD平仓后收盘=平仓【后】剩余;EOD增量=当前剩余。 public decimal PosiNotionalValue { get; } - public decimal PosiLongNotionalValue { get; } - public decimal PosiShortNotionalValue { get; } /// 本次实际平掉本金(两场景恒同义)。mode2 无条件覆盖 / mode9 全平兜底的输入。 public decimal ClosePosiNotionalValue { get; } @@ -40,15 +39,14 @@ public sealed class InterestCalcRequest private InterestCalcRequest( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePercent, int eventType, bool tdClose, decimal orginPv, bool add, bool newCalcLast, List closeList) { Td = td; TradeExtend = tradeExtend; ValueDate = valueDate; UnwindDate = unwindDate; EodPositions = eodPositions; Positions = positions; - PosiNotionalValue = posiNotionalValue; PosiLongNotionalValue = posiLongNotionalValue; - PosiShortNotionalValue = posiShortNotionalValue; ClosePosiNotionalValue = closePosiNotionalValue; + PosiNotionalValue = posiNotionalValue; ClosePosiNotionalValue = closePosiNotionalValue; ClosePercent = closePercent; EventType = eventType; TdClose = tdClose; OrginPv = orginPv; Add = add; NewCalcLast = newCalcLast; CloseList = closeList; } @@ -62,13 +60,11 @@ public sealed class InterestCalcRequest public static InterestCalcRequest IntradayUnwind( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal preCloseNotional, decimal preCloseLongNotional, decimal preCloseShortNotional, - decimal closedNotional, decimal closePercentRemaining, + decimal preCloseNotional, decimal closedNotional, decimal closePercentRemaining, int eventType, bool tdClose, decimal orginPv, bool add, bool newCalcLast, List closeList) => new(td, tradeExtend, valueDate, unwindDate, eodPositions, positions, - preCloseNotional, preCloseLongNotional, preCloseShortNotional, - closedNotional, closePercentRemaining, + preCloseNotional, closedNotional, closePercentRemaining, eventType, tdClose, orginPv, add, newCalcLast, closeList); /// @@ -80,12 +76,10 @@ public sealed class InterestCalcRequest public static InterestCalcRequest EodPostCloseSettle( trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal remainingNotionalAfterClose, decimal remainingLongNotional, decimal remainingShortNotional, - decimal closedNotional, + decimal remainingNotionalAfterClose, decimal closedNotional, int eventType, bool tdClose, decimal orginPv, bool add, bool newCalcLast) => new(td, tradeExtend, valueDate, unwindDate, eodPositions, positions, - remainingNotionalAfterClose, remainingLongNotional, remainingShortNotional, - closedNotional, 1m, // 恒1:本次事件全额结息(非 closeNational / 期初比例) + remainingNotionalAfterClose, closedNotional, 1m, // 恒1:本次事件全额结息(非 closeNational / 期初比例) eventType, tdClose, orginPv, add, newCalcLast, closeList: null); } diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index e05f3b3d..d4c15bd2 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -467,16 +467,11 @@ namespace YLErp.Modules.SwapModule // 迭代源仍用 origPositions(保留 orig.id → eod_swap_position.PositionId 的日终匹配), // 仅对预付金腿以实时腿的剩余本金克隆覆盖,故此处不改任何日终匹配行为。 var positions = ResolveInterestLegPositions(origPositions, realPostitions); - var fpositions = origPositions.Where(x => x.PosiDirection > 0).ToList(); - var longPositions = fpositions.Where(x => x.PositionType == (int)PositionTypeFlag.Long).ToList(); - var shortPositions = fpositions.Where(x => x.PositionType == (int)PositionTypeFlag.Short).ToList(); var tradeExtend = DbContext.trade_extend.FirstOrDefault(x => x.TradeId == tradeId); List eventTypes = new List() { (int)SwapEventTypeEnum.平仓, (int)SwapEventTypeEnum.互换, (int)SwapEventTypeEnum.自动互换 }; var lastEod = DbContext.eod_swap.Where(x => x.ValueDate < unwindDate && x.SwapTradeId == tradeId).OrderByDescending(o => o.ValueDate).FirstOrDefault(); var _preSetteDate = lastEod == null ? unwindDate.AddDays(-1) : lastEod.ValueDate; List lastEodPositions = new SwapEodPositionService(this).GetPreEodPositions(tradeId, _preSetteDate);//上一交易数据 - var posiLongNotionalValue = longPositions.Sum(s => s.PosiNotionalValue);// 剩余名义本金 - var posiShortNotionalValue = shortPositions.Sum(s => s.PosiNotionalValue);// 剩余名义本金 var stockEqvNotional = realPostitions.Where(x => x.PosiDirection > 0).Sum(s => s.PosiNotionalValue); // 当前平仓前的实时剩余本金 var posiNotionalValue = stockEqvNotional * closePercent;// 本次平仓名义本金 var orginPv = ResolveUnwindPreviousNotional(lastEod, lastEodPositions, stockEqvNotional); // 上一日终的浮动端本金 @@ -489,7 +484,7 @@ namespace YLErp.Modules.SwapModule // 显式入口:平仓前剩余本金 + 实际平掉额 + B语义比例,盘中重放(语义见 InterestCalcRequest.IntradayUnwind) interests = GetIntradayUnwindInterests(InterestCalcRequest.IntradayUnwind( td, tradeExtend, valueDate, unwindDate, lastEodPositions, positions, - stockEqvNotional, posiLongNotionalValue, posiShortNotionalValue, posiNotionalValue, + stockEqvNotional, posiNotionalValue, closePercent, eventType, tdClose, orginPv, add: true, newCalcLast: false, closeList)); return interests; } @@ -626,7 +621,7 @@ namespace YLErp.Modules.SwapModule /// public List GetIntradayUnwindInterests(InterestCalcRequest req) => GetInterests(req.Td, req.TradeExtend, req.ValueDate, req.UnwindDate, req.EodPositions, req.Positions, - req.PosiNotionalValue, req.PosiLongNotionalValue, req.PosiShortNotionalValue, req.ClosePosiNotionalValue, + req.PosiNotionalValue, req.ClosePosiNotionalValue, req.ClosePercent, req.EventType, req.TdClose, req.OrginPv, req.Add, settment: false, req.NewCalcLast, req.CloseList); @@ -638,8 +633,6 @@ namespace YLErp.Modules.SwapModule List eodPositions, List positions, decimal posiNotionalValue, - decimal posiLongNotionalValue, - decimal posiShortNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs index 0af04ee6..cb2f3d4e 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs @@ -90,7 +90,7 @@ namespace YLErp.Modules.SwapModule trade td, trade_extend tradeExtend, DateTime valueDate, DateTime unwindDate, List eodPositions, List positions, - decimal posiNotionalValue, decimal posiLongNotionalValue, decimal posiShortNotionalValue, + decimal posiNotionalValue, decimal closePosiNotionalValue, decimal closePrecent, int eventType, bool tdClose, decimal orginPv, @@ -98,7 +98,7 @@ namespace YLErp.Modules.SwapModule List closeList = null) { return new SwapDealService(this).GetInterests(td, tradeExtend, valueDate, unwindDate, - eodPositions, positions, posiNotionalValue, posiLongNotionalValue, posiShortNotionalValue, + eodPositions, positions, posiNotionalValue, closePosiNotionalValue, closePrecent, eventType, tdClose, orginPv, add, settment, newCalcLast, closeList); } @@ -112,7 +112,7 @@ namespace YLErp.Modules.SwapModule /// protected virtual List CalcEodPostCloseSettleInterests(InterestCalcRequest req) => CalcSwapInterests(req.Td, req.TradeExtend, req.ValueDate, req.UnwindDate, req.EodPositions, req.Positions, - req.PosiNotionalValue, req.PosiLongNotionalValue, req.PosiShortNotionalValue, + req.PosiNotionalValue, req.ClosePosiNotionalValue, req.ClosePercent, req.EventType, req.TdClose, req.OrginPv, req.Add, settment: false, req.NewCalcLast, req.CloseList); @@ -369,7 +369,7 @@ namespace YLErp.Modules.SwapModule var closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize * s.PosiGrossPrice); var grossPrice = curEodPosis.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0; //处理利息腿 - DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice, orginPv); + DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional + posiShortNotional, closePosiNotional, grossPrice, orginPv); //获取自动互换的 interval 信息,用于确定结算日期 IntervalModel autoInterval = null; foreach (var interest in interestList) @@ -441,8 +441,7 @@ namespace YLErp.Modules.SwapModule List flowEvents, List autoInterests, eod_swap lastEodSwap, - decimal posiLongNational, - decimal posiShortNational, + decimal posiTotalNotional, decimal closeNational, decimal grossPrice, decimal orginPv) @@ -453,7 +452,7 @@ namespace YLErp.Modules.SwapModule Log.Info($"[DealInterests] 参数验证 - settleDate: {settleDate:yyyy-MM-dd}, td.id: {td?.id}, td.TradeNumber: {td?.TradeNumber}"); Log.Info($"[DealInterests] 参数验证 - interestList.Count: {interestList?.Count ?? 0}, eodPositions.Count: {eodPositions?.Count ?? 0}, todyEodPositions.Count: {todyEodPositions?.Count ?? 0}"); Log.Info($"[DealInterests] 参数验证 - flowEvents.Count: {flowEvents?.Count ?? 0}, autoInterests.Count: {autoInterests?.Count ?? 0}"); - Log.Info($"[DealInterests] 参数验证 - posiLongNational: {posiLongNational}, posiShortNational: {posiShortNational}, closeNational: {closeNational}, grossPrice: {grossPrice}, orginPv: {orginPv}"); + Log.Info($"[DealInterests] 参数验证 - posiTotalNotional: {posiTotalNotional}, closeNational: {closeNational}, grossPrice: {grossPrice}, orginPv: {orginPv}"); // 验证关键参数 if (td == null) @@ -501,7 +500,7 @@ namespace YLErp.Modules.SwapModule { if (!hasClose)//当日无平仓 { - var _autoInterests = SaveAutoEodInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, lastEodSwap, posiLongNational, posiShortNational, grossPrice, orginPv); + var _autoInterests = SaveAutoEodInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, lastEodSwap, posiTotalNotional, grossPrice, orginPv); if (_autoInterests.Count > 0) { autoInterests.AddRange(_autoInterests); @@ -509,7 +508,7 @@ namespace YLErp.Modules.SwapModule } else { - var _autoInterests = SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, true, grossPrice, orginPv); + var _autoInterests = SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiTotalNotional, swapEvents, closeNational, true, grossPrice, orginPv); if (_autoInterests.Count > 0) { autoInterests.AddRange(_autoInterests); @@ -522,11 +521,11 @@ namespace YLErp.Modules.SwapModule } else if (hasClose) { - SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, false, grossPrice, orginPv); + SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiTotalNotional, swapEvents, closeNational, false, grossPrice, orginPv); } else//无自动互换、互换/平仓,复制上一日终信息,并计算当日新增利息 { - SaveEodInterestPositionCopy(eodPosition, tdEodPosition, settleDate, td, interest, lastEodSwap, true, posiLongNational, posiShortNational, grossPrice, orginPv); + SaveEodInterestPositionCopy(eodPosition, tdEodPosition, settleDate, td, interest, lastEodSwap, true, posiTotalNotional, grossPrice, orginPv); } } } @@ -1093,7 +1092,7 @@ namespace YLErp.Modules.SwapModule /// 上一平仓/互换日期 /// 当日平仓金额 /// 上一日终框架合约估值 - protected List SaveAutoEodInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, eod_swap lastEodSwap, decimal posiLongNotional, decimal posiShortNational, decimal grossPrice, decimal orginPv) + protected List SaveAutoEodInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, eod_swap lastEodSwap, decimal posiTotalNotional, decimal grossPrice, decimal orginPv) { Log.Info($"[SaveAutoEodInterestPosition] 开始执行 - valueDate: {valueDate:yyyy-MM-dd}, td.id: {td?.id}, position.id: {position?.id}"); @@ -1132,7 +1131,7 @@ namespace YLErp.Modules.SwapModule } var tradeExtend = td.trade_extend.ExtendObj; - decimal posiNotionalValue = posiLongNotional + posiShortNational; + decimal posiNotionalValue = posiTotalNotional; decimal closePercent = 1; var ratio = DirectionRatio.InterestLegPnl(position.InterestDirection, position.InterestMode); if (eodPayPosition == null) @@ -1159,7 +1158,7 @@ namespace YLErp.Modules.SwapModule { orginPv = eodPayPosition.InterestPrincipalFix; } - var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, posiNotionalValue, closePercent, (int)SwapEventTypeEnum.自动互换, false, orginPv, true); + var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiNotionalValue, closePercent, (int)SwapEventTypeEnum.自动互换, false, orginPv, true); decimal interestAmountBeforeSettlement = interests.Sum(x => x.InterestAmount); decimal tdInterestAmount = interests.Sum(x => x.TdInterestAmount); @@ -1244,7 +1243,7 @@ namespace YLErp.Modules.SwapModule /// 当日平仓金额 /// 上一日终框架合约估值 /// 平仓主信息 - protected List SaveAutoEodWithCloseInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, decimal posiLongNotional, decimal posiShortNational, List flowEvents, decimal closeNational, bool autoSwap, decimal grossPrice, decimal orginPv) + protected List SaveAutoEodWithCloseInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, decimal posiTotalNotional, List flowEvents, decimal closeNational, bool autoSwap, decimal grossPrice, decimal orginPv) { Log.Info($"eodPayPosition is {JsonHelper.Serialize(eodPayPosition, false)},newEodPayPosition is {JsonHelper.Serialize(newEodPayPosition, false)}"); var tradeExtend = td.trade_extend.ExtendObj; @@ -1255,8 +1254,8 @@ namespace YLErp.Modules.SwapModule // 调用共享计息器。因此策略的 "posiNotional × closePercent" 在本例会得到 212197382.46, // 而本次实际应结的平仓本金是 closeNational=90941735.34。该语义错位由 // SwapDealService.GetInterests 的模式2无条件修正、模式9全平零值兜底分流处理,不能删除。 - decimal oriPosiNotionalValue = posiLongNotional + posiShortNational + closeNational; - decimal posiNotionalValue = posiLongNotional + posiShortNational; + decimal oriPosiNotionalValue = posiTotalNotional + closeNational; + decimal posiNotionalValue = posiTotalNotional; // ratio 只负责把腿内原始金额转换为本方盈亏方向,不参与计息金额本身的计算。 var ratio = DirectionRatio.InterestLegPnl(position.InterestDirection, position.InterestMode); // 首次日终结算可能包含当日收盘,因此尚无先前的日终利息持仓。 @@ -1324,7 +1323,7 @@ namespace YLErp.Modules.SwapModule // 该组合触发 GetInterests 内共享计息器的模式2/9本金修正(见其"根因位置"注释,勿删)。 var interests = CalcEodPostCloseSettleInterests(InterestCalcRequest.EodPostCloseSettle( td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, - posiNotionalValue, posiLongNotional, posiShortNational, closeNational, + posiNotionalValue, closeNational, eventType, tdClose: false, orginPv, add: true, newCalcLast: autoSwap || calcLast)); // TdInterestAmount:计息器返回的全腿当日/累计参考值,用于拆出 EOD 的当日新增。 // interestAmountBeforeSettlement:本次事件发生前理论应结的高精度利息。 @@ -1505,7 +1504,7 @@ namespace YLErp.Modules.SwapModule /// 上一交易日 /// 当前结算日 /// 互换交易主干 - protected void SaveEodInterestPositionCopy(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, DateTime valueDate, trade td, swap_position position, eod_swap lastEodSwap, bool needPrice, decimal posiLongNational, decimal posiShortNational, decimal grossPrice, decimal orginPv) + protected void SaveEodInterestPositionCopy(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, DateTime valueDate, trade td, swap_position position, eod_swap lastEodSwap, bool needPrice, decimal posiTotalNotional, decimal grossPrice, decimal orginPv) { Log.Info($"eodPayPosition is {JsonHelper.Serialize(eodPayPosition, false)},newEodPayPosition is {JsonHelper.Serialize(newEodPayPosition, false)}"); List intervals = position.SwapIntervalList; @@ -1529,7 +1528,7 @@ namespace YLErp.Modules.SwapModule eodPayPosition.InterestPrincipalFix = position.InterestPrincipalFix; eodPayPosition.InterestRateDefault = position.InterestRateDefault; eodPayPosition.InterestSwapInterval = position.InterestSwapInterval; - eodPayPosition.TdInterestPrincipal = interestModes.Contains(position.InterestMode) ? eodPayPosition.InterestPrincipalFix : posiLongNational + posiShortNational; + eodPayPosition.TdInterestPrincipal = interestModes.Contains(position.InterestMode) ? eodPayPosition.InterestPrincipalFix : posiTotalNotional; eodPayPosition.PosiStartDate = td.StartDate.Value; eodPayPosition.PosiMatuirityDate = td.ExerciseDate.Value; eodPayPosition.IsAnnualized = position.IsAnnualized; @@ -1552,7 +1551,7 @@ namespace YLErp.Modules.SwapModule orginPv = eodPayPosition.InterestPrincipalFix; } bool longShort = td.StructureType == ClientMarginTypeEnum.多空组合.ToString(); - decimal oriPosiNotionalValue = posiLongNational + posiShortNational; + decimal oriPosiNotionalValue = posiTotalNotional; decimal posiNotionalValue = oriPosiNotionalValue; if (lastEodSwap == null) { @@ -1577,7 +1576,7 @@ namespace YLErp.Modules.SwapModule { preEodPositions.Add(eodPayPosition); } - var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNational, posiShortNational, posiNotionalValue, closePercent, 0, false, orginPv); + var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiNotionalValue, closePercent, 0, false, orginPv); UpdateDbOption(newEodPayPosition); newEodPayPosition.PosiStatus = 0;