fix(swap): 修复复利计算中部分平仓场景下的利息处理逻辑(算头不算尾期初复利)

- 修改单元测试为数据驱动测试,支持多种利息模式验证
- 更新复利计算注释,明确最终日重放时的calcLast规则
- 扩展复利计算条件判断,支持合约名义本金规模和标的期初全价两种模式
- 优化部分平仓日终复利计算逻辑,确保未平仓本金贡献正确保留
This commit is contained in:
张名锐
2026-08-08 16:32:50 +08:00
parent 54a86fccc1
commit aa5a5ed879
3 changed files with 12 additions and 41 deletions
@@ -1249,8 +1249,8 @@ namespace YLErp.Modules.SwapModule
var interestAtPreviousEod = new swap_flow_event { InterestRate = rate };
decimal amountAtPreviousEod = 0m;
decimal tdAmountAtPreviousEod = 0m;
// The previous EOD is a historical endpoint, not the contract tail.
// Include that day's accrual even when the final contract date omits its tail.
// 最终日重放仍遵守交易的 calcLast;上一日终是历史截点而非合约尾日,
// 因此此处按闭区间包含上一日终当天,避免算头不算尾时重复加入该日利息。
CalcDailyCompoundInterest(preEodPosition.ValueDate, position, closePosiNotionalValue,
interestAtPreviousEod, annualDays, needPrice, floateRate, closePrecent, orginPv,
calcFirst, true, ref amountAtPreviousEod, ref tdAmountAtPreviousEod, consumedInterest);
@@ -1418,11 +1418,12 @@ namespace YLErp.Modules.SwapModule
&& closePercent > 0m && closePercent < 1m
&& posiNotionalValue > 0m
&& position.InterestType == (int)InterestTypeEnum.
&& position.InterestMode == (int)InterestModeEnum.)
&& (position.InterestMode == (int)InterestModeEnum.
|| position.InterestMode == (int)InterestModeEnum.))
{
// 部分平仓日终的当日新增复利要保留未平仓本金的贡献。
// 算尾用平仓前全额本金;不算尾时只保留剩余本金,避免把
// 30% 已平部分的当日利息再次带入后续日终
// 模式2(合约名义本金规模)和模式9(标的期初全价)都以名义本金
// 作为复利基数,适用同一部分平仓递推;算尾用平仓前全额当日利息
// 再扣实际结算,不算尾只计剩余本金,避免已平部分利息进入后续复利
var fullPrincipal = lastTdInterestPrincipal > 0m
? lastTdInterestPrincipal
: oriPosiNotionalValue;