From 3d06e599088ba069d7e1d2df6603220ed3a50f38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=96=B9=E6=B5=B7?= Date: Wed, 27 May 2026 18:24:05 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=98=E4=B8=AD=E5=B9=B3=E4=BB=93=E5=88=A9?= =?UTF-8?q?=E6=81=AF=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SwapModule/GetInterestsUnitTest.cs | 2 +- .../Modules/SwapModule/SwapDealService.cs | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest.cs b/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest.cs index 30c02dde..2c748aca 100644 --- a/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest.cs +++ b/UnitTestProject/Modules/SwapModule/GetInterestsUnitTest.cs @@ -609,7 +609,7 @@ namespace YLErp.Modules.SwapModule ExpectedInterest(1, FixedRate, 0.001m, Principal * 0.5m)) }; var eodInterest = CalcEod("10", new DateTime(2026, 4, 30), eodPositions); - var expectedEod = ExpectedInterest(1, FixedRate, 0.001m, Principal * 0.5m); + var expectedEod = ExpectedInterest(2, FixedRate, 0.001m, Principal * 0.5m); Assert.AreEqual(expectedEod, eodInterest.InterestAmount); } diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index b8bbd82a..38d2f857 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -406,7 +406,7 @@ namespace YLErp.Modules.SwapModule else { // 盘中互换场景,使用 CalcUnwindInterest - interests.Add(CalcUnwindInterest(td, valueDate, endDate, positionClone, rate, floatRate, posiPrincipal, closePrincipal, newClosePercent, annualDays, preEodPosition, eventType, add, swap, orginPv)); + interests.Add(CalcUnwindInterest(td, valueDate, endDate, positionClone, rate, floatRate, posiPrincipal, closePrincipal, newClosePercent, annualDays, preEodPosition, eventType, add, swap, orginPv, calcFirst, calcLast)); } } return interests; @@ -557,7 +557,7 @@ namespace YLErp.Modules.SwapModule /// /// 计算盘中利息(平仓/互换) /// - private swap_flow_event CalcUnwindInterest(trade td, DateTime valueDate, DateTime endDate, swap_position position, decimal rate, decimal floatRate, decimal posiPrincipal, decimal closePrincipal, decimal closePercent, int annualDays, eod_swap_position preEod, int eventType, bool add, bool swap, decimal orginPv) + private swap_flow_event CalcUnwindInterest(trade td, DateTime valueDate, DateTime endDate, swap_position position, decimal rate, decimal floatRate, decimal posiPrincipal, decimal closePrincipal, decimal closePercent, int annualDays, eod_swap_position preEod, int eventType, bool add, bool swap, decimal orginPv, bool calcFirst, bool calcLast) { if (preEod.id == 0) { @@ -567,7 +567,7 @@ namespace YLErp.Modules.SwapModule preEod.ValueDate = td.TradeDate.Value; } - return InitSwapDealInterest(td, valueDate, endDate, rate, position, add, swap, posiPrincipal, closePrincipal, closePercent, annualDays, eventType, preEod, false, orginPv); + return InitSwapDealInterest(td, valueDate, endDate, rate, position, add, swap, posiPrincipal, closePrincipal, closePercent, annualDays, eventType, preEod, false, orginPv, calcFirst, calcLast); } /// /// 初始化利息腿信息 @@ -598,7 +598,9 @@ namespace YLErp.Modules.SwapModule int eventType, eod_swap_position preEodPosition, bool needPrice, - decimal orginPv + decimal orginPv, + bool calcFirst, + bool calcLast ) { decimal interestProfitSum = preEodPosition.InterestProfitSum; @@ -633,11 +635,11 @@ namespace YLErp.Modules.SwapModule var floateRate = preEodPosition.FloatRate; if (position.InterestType == (int)InterestTypeEnum.复利) { - CalcDailyCompoundInterest(preEodPosition, endDate, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, ref InterestAmount, ref TdInterestAmount); + CalcDailyCompoundInterest(preEodPosition, endDate, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount); } else { - CalcDailySimpleInterest(preEodPosition, endDate, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, ref InterestAmount, ref TdInterestAmount); + CalcDailySimpleInterest(preEodPosition, endDate, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount); } interest.InterestAmount = Math.Round(InterestAmount, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); @@ -661,26 +663,26 @@ namespace YLErp.Modules.SwapModule /// 是否年化 /// 年化天数 /// - public void CalcDailyCompoundInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, ref decimal InterestAmount, ref decimal TdInterestAmount) + public void CalcDailyCompoundInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount) { // 复利:利息并入本金 - CalcDailyInterest(preEodPosition, endDate, position, principal, posiPrincipal, flowEvent, annualDays, needPrice, floateRate, closePercent, orginPv, compoundInterest: true, ref InterestAmount, ref TdInterestAmount); + CalcDailyInterest(preEodPosition, endDate, position, principal, posiPrincipal, flowEvent, annualDays, needPrice, floateRate, closePercent, orginPv, compoundInterest: true, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount); } /// /// 计算单利 盘中(按重置天数分段,每段使用对应浮动利率) /// - public void CalcDailySimpleInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, ref decimal InterestAmount, ref decimal TdInterestAmount) + public void CalcDailySimpleInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount) { // 单利:利息不并入本金 - CalcDailyInterest(preEodPosition, endDate, position, principal, posiPrincipal, flowEvent, annualDays, needPrice, floateRate, closePercent, orginPv, compoundInterest: false, ref InterestAmount, ref TdInterestAmount); + CalcDailyInterest(preEodPosition, endDate, position, principal, posiPrincipal, flowEvent, annualDays, needPrice, floateRate, closePercent, orginPv, compoundInterest: false,calcFirst,calcLast, ref InterestAmount, ref TdInterestAmount); } /// /// 通用日度利息计算方法(单利/复利共用) /// /// 是否复利:true=利息并入本金,false=单利 - private void CalcDailyInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool compoundInterest, ref decimal InterestAmount, ref decimal TdInterestAmount) + private void CalcDailyInterest(eod_swap_position preEodPosition, DateTime endDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, bool compoundInterest, bool calcFirst, bool calcLast, ref decimal InterestAmount, ref decimal TdInterestAmount) { var startDate = position.PosiStartDate; decimal interestProfitSum = preEodPosition.InterestProfitSum; @@ -695,6 +697,8 @@ namespace YLErp.Modules.SwapModule for (int i = 0; i <= calcDays; i++) { var accrueDate = startDate.AddDays(i); + if (!calcFirst && accrueDate == startDate) continue; // 首日不算头 + if (!calcLast && accrueDate == endDate) continue; // 到期日不算尾 if (accrueDate > preEodPosition.ValueDate) { if (i % interestPeriod == 0)