fix(swap): 修复复利重置日部分平仓后本金计算逻辑
- 修复复利重置日部分平仓后当日利息计算,使用已结转待实现利息的剩余复利本金 - 修复算尾部分平仓后EOD保留剩余复利本金的逻辑,按计息模式返回口径处理 - 修复模式2和模式9在部分平仓时的本金计算差异,避免重复比例调整 - 修复不算尾情况下重置日后已并入本金的待实现利息遗漏问题 - 新增对话案例回归测试验证部分平仓后最终全平场景的正确性 - 添加多种计息模式和交易类型的回归测试用例
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user