diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs
index 5bc0a222..ffcc5ee7 100644
--- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs
@@ -1150,6 +1150,25 @@ namespace YLErp.Modules.SwapModule
return InitSwapDealInterest(td, valueDate, endDate, rate, position, add, swap, posiPrincipal, closePrincipal, closePercent, annualDays, eventType, preEod, false, orginPv, calcFirst, calcLast, consumedInterest);
}
+ ///
+ /// 保证金腿的 orginPv 维度重映射。
+ ///
+ /// 保证金腿被迫走融资腿的差分公式(dynomicPrincipal = TdInterestPrincipal + posiPrincipal - orginPv),
+ /// 但 orginPv 对融资腿是"交易名义本金(千万~亿级)",对保证金腿必须是"保证金本金"——
+ /// 否则维度不匹配会算出巨负值。本方法把保证金场景的 orginPv 对齐到"上一日保证金本金"。
+ ///
+ /// 待迁入 Margin 模块:保证金独立计息入口建好后,此方法移入 MarginAccount/MarginService。
+ ///
+ private decimal ResolveMarginOrginPv(swap_position position, eod_swap_position preEodPosition, decimal fallback)
+ {
+ var previousBalance = preEodPosition.InterestPrincipalFix != 0m
+ ? preEodPosition.InterestPrincipalFix
+ : preEodPosition.TdInterestPrincipal;
+ return preEodPosition.id != 0 && previousBalance != 0m
+ ? previousBalance
+ : fallback;
+ }
+
///
/// 初始化利息腿信息
///
@@ -1203,22 +1222,10 @@ namespace YLErp.Modules.SwapModule
interest.ClientId = td.ClientId;
interest.UnwindDate = endDate;
- // 根因修复:预付金(保证金)腿的计息基数维度应为"保证金本金"自身,而非整笔交易的名义本金(orginPv)。
- // 否则公式 dynomicPrincipal = TdInterestPrincipal + posiPrincipal - orginPv
- // 会把交易名义本金(千万~亿级)当减项扣掉,使"应返还本金"(InterestPrincipal)与计息基数变成巨负值。
- // 此处将预付金腿的 orginPv 对齐为上一日保证金本金;无历史归档时才取当前本金。
- // 差分公式必须使用同一时点口径:上一日本金 + 当前本金 - 上一本金 = 当前本金。
- // 若已有部分平仓后仍取当前本金,会把上一日本金原样保留,导致当日继续按平仓前本金计息。
- // 仅作用于初始预付金(5)/追加预付金(6);其它计息模式(含债券本金腿 标的期初全价=9)仍用交易名义本金,不受影响。
- if (position.InterestMode == (int)InterestModeEnum.初始预付金
- || position.InterestMode == (int)InterestModeEnum.追加预付金)
+ // 保证金腿的 orginPv 对齐到保证金本金维度,避免差分公式维度不匹配算出巨负值
+ if (MarginModes.Contains(position.InterestMode))
{
- var previousPrincipal = preEodPosition.InterestPrincipalFix != 0m
- ? preEodPosition.InterestPrincipalFix
- : preEodPosition.TdInterestPrincipal;
- orginPv = preEodPosition.id != 0 && previousPrincipal != 0m
- ? previousPrincipal
- : position.InterestPrincipalFix;
+ orginPv = ResolveMarginOrginPv(position, preEodPosition, position.InterestPrincipalFix);
}
if (swap)