feat(swap): 实现预付金利息腿实时剩余本金计算功能

- 新增 ResolveInterestLegPositionsAsOf 方法处理预付金利息腿实时本金计算
- 添加 FindCompletedFlowEvents 方法查询已完成的现金流事件
- 在日终持仓服务中集成实时剩余本金计算逻辑
- 移除日终重复扣减预付金本金的逻辑
- 优化利息端估值计算方式
- 添加部分平仓后预付金日终按实时剩余本金计息的测试用例
- 增加平仓日预付金日终不得重复扣减实时剩余本金的验证
- 完善历史回放场景下的本金调整功能
This commit is contained in:
张名锐
2026-08-06 14:32:38 +08:00
parent 6bbe9b1c13
commit 9ef45650c7
3 changed files with 233 additions and 6 deletions
@@ -307,6 +307,14 @@ namespace YLErp.Modules.SwapModule
return DbContext.swap_flow_event.Where(eventExpression).ToList();
}
protected virtual List<swap_flow_event> FindCompletedFlowEvents(List<int> tradeIds)
{
return DbContext.swap_flow_event
.Where(x => tradeIds.Contains(x.SwapTradeId)
&& x.DataState == (int)SwapFlowDateStateEnum.)
.ToList();
}
#endregion
/// <summary>
@@ -352,6 +360,7 @@ namespace YLErp.Modules.SwapModule
var tradeRealPositionList = allTradePositionList.Where(t => !t.IsInitial).ToList();
var tradeExtendList = FindTradeExtends(tradeIds);
var eodSwapList = FindEodSwapsByDate(preSettleDate);
var completedFlowEvents = FindCompletedFlowEvents(tradeIds);
List<int> eventTyps = new List<int>() { (int)SwapEventTypeEnum., (int)SwapEventTypeEnum., (int)SwapEventTypeEnum. };
foreach (var td in tradeQueryList)
{
@@ -364,7 +373,10 @@ namespace YLErp.Modules.SwapModule
var realPositions = tradeRealPositionList.Where(s => s.SwapTradeId == td.id);
var posiList = positions.Where(x => x.PosiQuantity > 0).ToList();
var realPosiList = realPositions.ToList();
var interestList = positions.Where(x => x.InterestDirection > 0).ToList();
var tradeCompletedFlowEvents = completedFlowEvents.Where(x => x.SwapTradeId == td.id).ToList();
var interestList = SwapDealService.ResolveInterestLegPositionsAsOf(
positions.ToList(), realPosiList, tradeCompletedFlowEvents, settleDate)
.Where(x => x.InterestDirection > 0).ToList();
DateTime posiDate = td.TradeDate.Value;//交易日期
var lastEodSwap = eodSwapList.FirstOrDefault(x => x.SwapTradeId == td.id);
//上一交易日无日终归档,且不是交易日期,且当前收盘日期不是交易日期,报错
@@ -1351,8 +1363,9 @@ namespace YLErp.Modules.SwapModule
//持仓内容-利息腿
newEodPayPosition.InterestDirection = position.InterestDirection;
newEodPayPosition.InterestMode = position.InterestMode;
// ResolveInterestLegPositions 已提供平仓后的实时剩余本金,日终不再重复扣减。
newEodPayPosition.InterestPrincipalFix = position.InterestPrincipalFix;
newEodPayPosition.InterestPrincipalFix *= (1 - closePercent);
// newEodPayPosition.InterestPrincipalFix *= (1 - closePercent);
newEodPayPosition.InterestRateDefault = position.InterestRateDefault;
newEodPayPosition.InterestSwapInterval = position.InterestSwapInterval;
newEodPayPosition.IsAnnualized = position.IsAnnualized;
@@ -1364,9 +1377,11 @@ namespace YLErp.Modules.SwapModule
newEodPayPosition.interest_rest_days = position.interest_rest_days;
newEodPayPosition.interest_rule = position.interest_rule;
//利息端估值用信息
newEodPayPosition.TdInterestPrincipal = position.InterestMode == (int)InterestModeEnum.
? posiNotionalValue
: interests.Count > 0 ? interests.First().InterestPrincipal : 0;
newEodPayPosition.TdInterestPrincipal = interestModes.Contains(position.InterestMode)
? position.InterestPrincipalFix
: position.InterestMode == (int)InterestModeEnum.
? posiNotionalValue
: interests.Count > 0 ? interests.First().InterestPrincipal : 0;
if (interval != null)
{
newEodPayPosition.TdInterestRate = interval.Rate;