fix(swap): 修复复利重置日部分平仓后本金计算逻辑

- 修复复利重置日部分平仓后当日利息计算,使用已结转待实现利息的剩余复利本金
- 修复算尾部分平仓后EOD保留剩余复利本金的逻辑,按计息模式返回口径处理
- 修复模式2和模式9在部分平仓时的本金计算差异,避免重复比例调整
- 修复不算尾情况下重置日后已并入本金的待实现利息遗漏问题
- 新增对话案例回归测试验证部分平仓后最终全平场景的正确性
- 添加多种计息模式和交易类型的回归测试用例
This commit is contained in:
张名锐
2026-08-09 16:06:09 +08:00
parent 421662a07c
commit 48e8447925
3 changed files with 407 additions and 6 deletions
@@ -1422,30 +1422,35 @@ namespace YLErp.Modules.SwapModule
|| position.InterestMode == (int)InterestModeEnum.))
{
// 模式2(合约名义本金规模)和模式9(标的期初全价)都以名义本金
// 作为复利基数,适用同一部分平仓递推;算尾用平仓前全额当日利息
// 再扣实际结算,不算尾只计剩余本金,避免已平部分利息进入后续复利。
// 作为复利基数;算尾用平仓前全额当日利息再扣实际结算,
// 不算尾只计剩余本金,避免已平部分利息进入后续复利。
var fullPrincipal = lastTdInterestPrincipal > 0m
? lastTdInterestPrincipal
: oriPosiNotionalValue;
// 当日计提按平仓前全额动态本金;跨日携带必须只留剩余仓位。
// calcLast=true 返回的是本次已平部分动态本金,按平仓比例反推全额后取剩余
// calcLast=true 时,模式2返回本次已平部分本金,需反推剩余本金
// 模式9返回的已是剩余本金,不能再次按比例放大(GLMS-20260421-0004)。
// calcLast=false 快速路径返回上一 EOD 全额本金,保留原剩余比例缩放。
var usesFullPreviousEodPrincipal = !calcLast
&& hasPreviousEod
&& (valueDate - eodPayPosition.ValueDate).Days == 1
&& (valueDate - position.PosiStartDate).Days % (position.interest_rest_days ?? 1) != 0;
if (calcLast)
if (calcLast
&& position.InterestMode == (int)InterestModeEnum.)
{
// calcLast=true 的 InterestPrincipal 是已平部分,不是跨日剩余本金。
// 模式2的 InterestPrincipal 是已平部分,不是跨日剩余本金。
newEodPayPosition.TdInterestPrincipal *= (1m - closePercent) / closePercent;
}
else if (usesFullPreviousEodPrincipal)
{
newEodPayPosition.TdInterestPrincipal *= 1m - closePercent;
}
// 不算尾时,TdInterestPrincipal 已由计息器完成重置日待实现利息结转,
// 并在非重置日分支按剩余仓位调整;若再次用上日本金乘剩余比例,
// 会漏掉重置后已并入本金的待实现利息(如 2026-08-04 两笔 JIATT 交易)。
var accrualPrincipal = calcLast
? fullPrincipal
: fullPrincipal * (1m - closePercent);
: newEodPayPosition.TdInterestPrincipal;
newEodPayPosition.TdInterestIncome = accrualPrincipal
* (newEodPayPosition.TdInterestRate + newEodPayPosition.FloatRate);
if (position.IsAnnualized)