diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index 7e69e78b..b22c70e7 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -486,7 +486,10 @@ namespace YLErp.Modules.SwapModule && eventTypes.Contains(x.EventType) && x.DataState == (int)SwapFlowDateStateEnum.完成).ToList(); bool tdClose = closeList.Count > 0; - interests = GetInterests(td, tradeExtend, valueDate, unwindDate, lastEodPositions, positions, stockEqvNotional, posiLongNotionalValue, posiShortNotionalValue, posiNotionalValue, closePercent, eventType, tdClose, false, grossPrice ?? 0, orginPv, true, false,false, closeList); + // 显式入口(语义见 GetIntradayUnwindInterests 注释):平仓前剩余本金 + 实际平掉额 + B语义比例,盘中重放 + interests = GetIntradayUnwindInterests(td, tradeExtend, valueDate, unwindDate, lastEodPositions, positions, + stockEqvNotional, posiLongNotionalValue, posiShortNotionalValue, posiNotionalValue, + closePercent, eventType, tdClose, orginPv, add: true, newCalcLast: false, closeList); return interests; } @@ -616,6 +619,40 @@ namespace YLErp.Modules.SwapModule /// /// /// + /// + /// 【盘中平仓/互换结息】显式入口——GetInterests(settment:false) 盘中语义的具名封装(2026-08 显式化重构)。 + /// + /// 语义契约(与 EOD 平仓后收盘的 CalcEodPostCloseSettleInterests 相反,勿混用): + /// preCloseNotional = 平仓【前】实时剩余本金(原 GetUnwindInterests 的 stockEqvNotional); + /// closedNotional = 本次实际平掉本金(= preCloseNotional × closePercentRemaining); + /// closePercentRemaining = 平仓比例,B 语义【占剩余】(前端传 A 占期初,须先经 ToRemainingClosePercent 转换); + /// 计息走 CalcUnwindInterest 全区间重放(orginPv 参与保证金腿差分)。 + /// + /// needPrice/grossPrice 为 GetInterests 的历史死参数(方法体内无消费),本入口不再暴露。 + /// + public List GetIntradayUnwindInterests( + trade td, + trade_extend tradeExtend, + DateTime valueDate, + DateTime unwindDate, + List eodPositions, + List positions, + decimal preCloseNotional, + decimal preCloseLongNotional, + decimal preCloseShortNotional, + decimal closedNotional, + decimal closePercentRemaining, + int eventType, + bool tdClose, + decimal orginPv, + bool add, + bool newCalcLast, + List closeList) + => GetInterests(td, tradeExtend, valueDate, unwindDate, eodPositions, positions, + preCloseNotional, preCloseLongNotional, preCloseShortNotional, closedNotional, + closePercentRemaining, eventType, tdClose, needPrice: false, grossPrice: 0m, + orginPv, add, settment: false, newCalcLast, closeList); + public List GetInterests( trade td, trade_extend tradeExtend, diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs index be097caf..795b5829 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs @@ -102,6 +102,33 @@ namespace YLErp.Modules.SwapModule grossPrice, orginPv, add, settment, newCalcLast, closeList); } + /// + /// 【EOD 当日有平仓后的收盘结息】显式入口——原 SaveAutoEodWithCloseInterestPosition 直调 + /// CalcSwapInterests(settment:false) 的具名封装(2026-08 显式化重构)。 + /// + /// 语义契约(与盘中 SwapDealService.GetIntradayUnwindInterests 相反,勿混用): + /// remainingNotionalAfterClose = 平仓【后】剩余本金(GetInterests.posiNotionalValue 形参位); + /// closedNotional = 本次实际平掉本金(GetInterests.closePosiNotionalValue 形参位); + /// 结息比例恒 1(本次事件全额结息)。该组合会触发 GetInterests 内 mode2 无条件覆盖 / + /// mode9 全平兜底(见其"根因位置"注释,勿删)。 + /// 计息走 CalcUnwindInterest 全区间重放(settment:false)。 + /// + /// 默认实现仍经 CalcSwapInterests 转发,保持既有测试替身对该虚接缝的拦截不变。 + /// + protected virtual List CalcEodPostCloseSettleInterests( + trade td, trade_extend tradeExtend, + DateTime valueDate, DateTime unwindDate, + List eodPositions, List positions, + decimal remainingNotionalAfterClose, decimal remainingLongNotional, decimal remainingShortNotional, + decimal closedNotional, + int eventType, bool tdClose, + decimal grossPrice, decimal orginPv, + bool add, bool newCalcLast) + => CalcSwapInterests(td, tradeExtend, valueDate, unwindDate, eodPositions, positions, + remainingNotionalAfterClose, remainingLongNotional, remainingShortNotional, + closedNotional, 1m, eventType, tdClose, needPrice: true, grossPrice, orginPv, + add, settment: false, newCalcLast, closeList: null); + // FindTrade 已上提到基类 SwapTradeBaseService(三子类实现一致,消除重复) /// 查找交易扩展(生产: DbContext.trade_extend;测试: 内存字典) @@ -1306,9 +1333,11 @@ namespace YLErp.Modules.SwapModule List preEodPositions = new List(); preEodPositions.Add(eodPayPosition); var calcLast = tradeExtend?.InterestCalcMode?.EndsWith("1") ?? true; - // 此处 closePercent=1 表示 EOD 计算本次事件时走全额结息;它不是 closeNational / oriPosiNotionalValue。 - // 与上方“收盘后剩余本金”同时传入会触发共享计息器的模式2/9本金修正,见 GetInterests。 - var interests = CalcSwapInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, closeNational, 1, eventType, false, true, grossPrice, orginPv, true, settment: false, newCalcLast: autoSwap || calcLast); + // 显式入口(语义见 CalcEodPostCloseSettleInterests 注释):平仓后剩余本金 + 实际平掉额 + 恒1全额结息。 + // 该组合会触发 GetInterests 内共享计息器的模式2/9本金修正(见其"根因位置"注释,勿删)。 + var interests = CalcEodPostCloseSettleInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, + posiNotionalValue, posiLongNotional, posiShortNational, closeNational, + eventType, tdClose: false, grossPrice, orginPv, add: true, newCalcLast: autoSwap || calcLast); // TdInterestAmount:计息器返回的全腿当日/累计参考值,用于拆出 EOD 的当日新增。 // interestAmountBeforeSettlement:本次事件发生前理论应结的高精度利息。 // manualSettledInterestAmount:swap_flow_event 实际落库的手工结息,金额已按分处理。