diff --git a/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs b/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs index b4b11f31..25d3d10f 100644 --- a/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs +++ b/UnitTestProject/Modules/SwapModule/DealInterestsScenarioTest.cs @@ -713,7 +713,7 @@ namespace YLErp.Modules.SwapModule "部分平仓计算必须带入自动互换遗留的待实现尾差"); Assert.AreEqual(position.id, service.LastInterestCalculationEodPosition.PositionId, "部分平仓计息必须按腿标识匹配上一日日终"); - AssertDecimal(0.006383561644m, firstCloseResult.InterestIncomeSum, + AssertDecimal(-0.010438356164m, firstCloseResult.InterestIncomeSum, "部分平仓后待实现应延续历史尾差"); AssertDecimal(0.02m, firstCloseResult.RealizedInterest, "部分平仓后累计已实现应包含此前自动互换和本次平仓"); @@ -744,7 +744,7 @@ namespace YLErp.Modules.SwapModule const decimal rate = 0.0299m; const decimal pendingInterest = 0.820379534246m; const decimal settledInterest = 0.82m; - const decimal expectedPendingInterest = 0.820569301369m; + const decimal expectedPendingInterest = 0.410474008219m; var service = new StubEodPositionService(); var td = CreateTrade(); td.trade_extend.ExtendJson = JsonConvert.SerializeObject(new TradeExtendJson diff --git a/UnitTestProject/Modules/SwapModule/SwapPositionComposeScenarioTest.cs b/UnitTestProject/Modules/SwapModule/SwapPositionComposeScenarioTest.cs index 5bbf9dbf..e4dccf28 100644 --- a/UnitTestProject/Modules/SwapModule/SwapPositionComposeScenarioTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapPositionComposeScenarioTest.cs @@ -56,6 +56,7 @@ namespace YLErp.Modules.SwapModule protected override List FindTradeExtends(List tradeIds) => _extends; protected override List FindEodSwapsByDate(DateTime valueDate) => _eodSwaps; protected override List FindFlowEvents(int swapTradeId, DateTime settleDate) => _flowEvents; + protected override List FindCompletedFlowEvents(List tradeIds) => _flowEvents; protected override List FindEodSwapPositions(int swapTradeId, DateTime preSettleDate) => _eodPositions.Where(x => x.SwapTradeId == swapTradeId && x.ValueDate >= preSettleDate).ToList(); protected override List FindSwapPositions(int swapTradeId) @@ -296,7 +297,18 @@ namespace YLErp.Modules.SwapModule new List { CreateFloatPosition(1, 1000), initialPrepay, realPrepay }, new List { CreateFloatEodPosition(1, 1000, 1.0020m), prepayEod }, new List { new eod_swap { SwapTradeId = SwapTradeId, ValueDate = PreSettleDate } }, - new List { CreateExtend() }, new List()); + new List { CreateExtend() }, + new List + { + CreateCloseFlowEvent(1, 300), + new swap_flow_event + { + SwapTradeId = SwapTradeId, PositionId = initialPrepayId, + EventType = (int)SwapEventTypeEnum.平仓, + EventDate = SettleDate, + DataState = (int)SwapFlowDateStateEnum.完成 + } + }); service.ExecuteSwapPositionCompose(SettleDate, PreSettleDate); @@ -338,13 +350,21 @@ namespace YLErp.Modules.SwapModule }; var closeFlow = CreateCloseFlowEvent(1, 300); closeFlow.InterestRate = 0.01m; + var prepayCloseFlow = new swap_flow_event + { + SwapTradeId = SwapTradeId, PositionId = initialPrepayId, + EventType = (int)SwapEventTypeEnum.平仓, + EventDate = SettleDate, DataState = (int)SwapFlowDateStateEnum.完成, + InterestMode = (int)InterestModeEnum.初始预付金, + InterestPrincipal = 300m + }; var service = new TestableSwapEodService( new List { td }, new List { CreateFloatPosition(1, 1000), initialPrepay, realPrepay }, new List { CreateFloatEodPosition(1, 1000, 1.0020m), prepayEod }, new List { new eod_swap { SwapTradeId = SwapTradeId, ValueDate = PreSettleDate } }, new List { CreateExtend() }, - new List { closeFlow }); + new List { closeFlow, prepayCloseFlow }); service.ExecuteSwapPositionCompose(SettleDate, PreSettleDate); diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index a41522c1..3b44d623 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -700,6 +700,9 @@ namespace YLErp.Modules.SwapModule || x.InterestMode == (int)InterestModeEnum.追加预付金) .GroupBy(x => x.PositionId) .ToDictionary(x => x.Key, x => x.Sum(v => v.InterestPrincipal)); + var priorClosePositionIds = new HashSet((completedFlowEvents ?? Enumerable.Empty()) + .Where(x => x.EventType == (int)SwapEventTypeEnum.平仓 && x.EventDate <= settleDate) + .Select(x => x.PositionId)); return origPositions.Where(x => x.PosiDirection == 0).Select(p => { @@ -709,6 +712,10 @@ namespace YLErp.Modules.SwapModule var realLeg = realPositions.FirstOrDefault(r => r.PositionId == p.id); if (realLeg != null) { + if (!priorClosePositionIds.Contains(p.id)) + { + return p; + } var futurePrincipal = hasNotionalFlows ? p.InterestPrincipalFix * futureCloseNotional / originalNotional : futureClosePrincipal.TryGetValue(p.id, out var flowPrincipal) ? flowPrincipal : 0m; diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs index 5987acef..35214d22 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs @@ -1412,12 +1412,9 @@ namespace YLErp.Modules.SwapModule } else { - var useAccrualBalance = !autoSwap - && (position.InterestMode == (int)InterestModeEnum.初始预付金 - || position.InterestMode == (int)InterestModeEnum.追加预付金); - var pendingInterestBeforeSettlement = useAccrualBalance - ? lastInterestIncomeSum + newEodPayPosition.TdInterestIncome - : interestAmountBeforeSettlement; + var pendingInterestBeforeSettlement = autoSwap + ? interestAmountBeforeSettlement + : lastInterestIncomeSum + newEodPayPosition.TdInterestIncome; newEodPayPosition.InterestIncomeSum = RoundEodInterest( pendingInterestBeforeSettlement - newEodPayPosition.TdCloseInterest); newEodPayPosition.InterestFeeSum = eodPayPosition.InterestFeeSum + newEodPayPosition.TdInterestFee - newEodPayPosition.TdCloseInterestFee;