fix(swap): 修复部分平仓后复利本金计算逻辑(修复T+1)

- 修复部分平仓后下一日复利本金未按剩余比例继承的问题
- 添加对最终日不算尾时历史差分重放的日期边界控制
- 修复算头不算尾快速路径中已平部分进入下一日复利的错误
- 确保重置日动态本金不会被二次缩放导致剩余本金计算错误
- 添加单元测试验证部分平仓后复利本金按剩余70%本金计提的逻辑
- 补充最终全平重放时历史终点包含当日利息后再做差额的测试用例
This commit is contained in:
张名锐
2026-08-08 17:10:29 +08:00
parent aa5a5ed879
commit d3afa6d27c
3 changed files with 61 additions and 1 deletions
@@ -1562,6 +1562,9 @@ namespace YLErp.Modules.SwapModule
"0005 计算不算尾时,部分平仓日终新增复利必须按剩余70%本金计提");
AssertDecimal(196212.213529615939m, partialEod.InterestIncomeSum,
"0005 部分平仓后日终待实现复利必须扣除实际80002.30结算");
AssertDecimal(previousEod.TdInterestPrincipal * (1m - partialNotional / originalNotional),
partialEod.TdInterestPrincipal,
"0005 部分平仓后,下一日复利本金必须只继承剩余70%本金");
var intermediateDate = new DateTime(2026, 5, 18);
var intermediateInterest = dealService.GetInterests(
@@ -1573,6 +1576,39 @@ namespace YLErp.Modules.SwapModule
Assert.IsTrue(Math.Abs(259348.386714765m - intermediateInterest.InterestAmount) <= 0.01m,
$"0005 5/18 复利应承接部分平仓后的累计利息 Expected approximately 259348.386714765, Actual: {intermediateInterest.InterestAmount}");
var intermediateEod = partialEod.Clone();
intermediateEod.id = 18283;
intermediateEod.ValueDate = intermediateDate;
intermediateEod.InterestIncomeSum = intermediateInterest.InterestAmount;
intermediateEod.InterestProfitSum = intermediateInterest.InterestAmount;
intermediateEod.TdInterestPrincipal = remainingNotional;
intermediateEod.PosiNotionalValue = remainingNotional;
var expectedEndFlow = new swap_flow_event { InterestRate = spread };
decimal expectedAmountAtEnd = 0m;
decimal expectedTdAmountAtEnd = 0m;
dealService.CalcDailyCompoundInterest(
finalCloseDate, position, remainingNotional, expectedEndFlow, AnnualDays, false,
intermediateEod.FloatRate, 1m, originalNotional, true, false,
ref expectedAmountAtEnd, ref expectedTdAmountAtEnd);
var expectedPreviousFlow = new swap_flow_event { InterestRate = spread };
decimal expectedAmountAtPreviousEod = 0m;
decimal expectedTdAmountAtPreviousEod = 0m;
dealService.CalcDailyCompoundInterest(
intermediateDate, position, remainingNotional, expectedPreviousFlow, AnnualDays, false,
intermediateEod.FloatRate, 1m, originalNotional, true, true,
ref expectedAmountAtPreviousEod, ref expectedTdAmountAtPreviousEod);
var expectedFinalInterest = intermediateEod.InterestIncomeSum
+ expectedAmountAtEnd - expectedAmountAtPreviousEod;
var finalInterest = dealService.GetInterests(
td, td.trade_extend, finalCloseDate, finalCloseDate,
new List<eod_swap_position> { intermediateEod }, new List<swap_position> { position },
remainingNotional, remainingNotional, 0m, remainingNotional, 1m,
(int)SwapEventTypeEnum., false, false, 0m, originalNotional,
settment: false, newCalcLast: false).Single();
AssertDecimal(expectedFinalInterest, finalInterest.InterestAmount,
"0005 最终全平重放时,历史5/18终点必须包含当日利息后再做差额");
}
[TestMethod]