From 3d73835be510532b2676dacdad89737f4b93884a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com> Date: Wed, 29 Jul 2026 14:42:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(swap):=20=E7=BB=93=E7=AE=97=E6=88=96?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E5=B9=B3=E4=BB=93=E5=90=8E=EF=BC=8C=E5=BE=85?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=BD=AE0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 NormalizeSettledInterestAmounts 方法处理手工平仓和互换的利息事件精度 - 添加 NormalizeManualSettlementAmounts 方法在手工结算前收敛流水金额 - 将利息计算精度从 ConsGlobal.PriceRound 统一调整为 InterestCalculationPrecision(12位) - 在日终持仓快照中添加精度标准化处理,利息腿保留12位精度 - 修复全量平仓时待实现利息和费用的清零逻辑 - 在收益结算事件后清空待实现利息余额避免重复计算 - 更新单元测试验证现金与两位利息事件的一致性 --- .../SwapModule/SwapUnwindScenarioTest.cs | 31 +++++++ .../Modules/SwapModule/SwapDealService.cs | 80 ++++++++++++++++--- .../SwapModule/SwapEodPositionService.cs | 78 +++++++++++++++++- .../SwapModule/SwapFlowEventService.cs | 2 +- .../Modules/SwapModule/SwapTradeService.cs | 4 +- 5 files changed, 176 insertions(+), 19 deletions(-) diff --git a/UnitTestProject/Modules/SwapModule/SwapUnwindScenarioTest.cs b/UnitTestProject/Modules/SwapModule/SwapUnwindScenarioTest.cs index dd7726cb..ea9bf5c0 100644 --- a/UnitTestProject/Modules/SwapModule/SwapUnwindScenarioTest.cs +++ b/UnitTestProject/Modules/SwapModule/SwapUnwindScenarioTest.cs @@ -258,5 +258,36 @@ namespace YLErp.Modules.SwapModule Assert.AreEqual(500000.00m, savedData.CloseNotionalValue, "平仓名义本金应按两位小数写入事件"); Assert.AreEqual(500000.01, td.StockEqvNotional, 0.000001, "trade 剩余名义本金应在扣减后舍入两位小数"); } + + [TestMethod] + public void UW_010_SwapUnwind_现金与两位利息事件保持一致() + { + var td = SwapDealTestFactory.CreateTrade(); + var service = new TestableSwapDealService(td); + var unwindData = SwapDealTestFactory.CreateUnwindData( + swapRealizedPnL: 10.0049m, closeMethod: (int)CloseMethodEnum.全部平仓, + closePercent: 1m, closeQty: 10000m, closeNotionalValue: 1000000m, positionQty: 10000m); + var floatEvent = new swap_flow_event + { + UnderlyingCode = "UT-FLOAT", PositionType = (int)PositionTypeFlag.Long, + EventType = (int)SwapEventTypeEnum.平仓, PayDirection = 1, MarkClosePnl = 10m + }; + var interestEvent = new swap_flow_event + { + PositionType = 0, InterestAmount = 0.0049m, TdInterestAmount = 0.0049m, + InterestClosePnL = 0.0049m, InterestFee = 0.0049m + }; + unwindData.FlowEvents.Add(floatEvent); + unwindData.FlowEvents.Add(interestEvent); + + service.SwapUnwind(unwindData); + + Assert.AreEqual(0m, interestEvent.InterestAmount); + Assert.AreEqual(0m, interestEvent.TdInterestAmount); + Assert.AreEqual(0m, interestEvent.InterestClosePnL); + Assert.AreEqual(0m, interestEvent.InterestFee); + Assert.AreEqual(10m, unwindData.SwapRealizedPnL); + Assert.AreEqual(-10d, service.ClientCashCalls[0].amount, 0.001d); + } } } diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index ba8b980c..b9cee1fb 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -47,6 +47,51 @@ namespace YLErp.Modules.SwapModule unwindData.CloseNotionalValue = Math.Round(unwindData.CloseNotionalValue, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); } + // 待实现利息会进入 decimal(30,12) 日终快照 + private const int InterestCalculationPrecision = 12; + + /// + /// 手工平仓、手工互换及收益结算的利息事件按金额两位落库。 + /// 自动平仓保留原有计算与落库口径,不适用本阶段的手工结算规则。 + /// + private static bool NormalizeSettledInterestAmounts(IEnumerable flowEvents, int eventType, string eventReason) + { + if ((eventType != (int)SwapEventTypeEnum.平仓 && eventType != (int)SwapEventTypeEnum.互换) + || eventReason == "系统操作_自动平仓") + { + return false; + } + + foreach (var flowEvent in flowEvents.Where(x => string.IsNullOrEmpty(x.UnderlyingCode))) + { + // 只处理利息腿;浮动腿损益在日终快照入口统一按两位落库。 + flowEvent.InterestPrincipal = Math.Round(flowEvent.InterestPrincipal, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); + flowEvent.InterestAmount = Math.Round(flowEvent.InterestAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); + flowEvent.TdInterestAmount = Math.Round(flowEvent.TdInterestAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); + flowEvent.InterestClosePnL = Math.Round(flowEvent.InterestClosePnL, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); + flowEvent.InterestFee = Math.Round(flowEvent.InterestFee, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); + } + return true; + } + + // 客户现金在 SaveSwapDeal 之前创建,手工结算必须先收敛流水并重算汇总金额。 + private void NormalizeManualSettlementAmounts(UnwindData unwindData, int eventType, string eventReason) + { + if (!NormalizeSettledInterestAmounts(unwindData.FlowEvents, eventType, eventReason)) + { + return; + } + + if (unwindData.FlowEvents.Any(x => !string.IsNullOrEmpty(x.UnderlyingCode))) + { + CalcCloseAmount(unwindData); + return; + } + + unwindData.SwapCloseAmount = Math.Round(unwindData.SwapCloseAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); + unwindData.SwapRealizedPnL = Math.Round(unwindData.SwapRealizedPnL, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); + } + /// 保存所有变更(生产: DbContext.SaveChanges;测试: 空操作) protected virtual void SaveAllChanges() { @@ -846,8 +891,8 @@ namespace YLErp.Modules.SwapModule } // 四舍五入并赋值 - interest.InterestAmount = Math.Round(interestAmount, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); - interest.TdInterestAmount = Math.Round(tdInterestAmount, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + interest.InterestAmount = Math.Round(interestAmount, InterestCalculationPrecision, MidpointRounding.AwayFromZero); + interest.TdInterestAmount = Math.Round(tdInterestAmount, InterestCalculationPrecision, MidpointRounding.AwayFromZero); // 计算InterestClosePnL(方向:收取=1为正,支付=-1为负) var interestRatio = position.InterestDirection == 1 ? 1m : -1m; interest.InterestClosePnL = interest.InterestAmount * interestRatio; @@ -962,8 +1007,8 @@ namespace YLErp.Modules.SwapModule CalcDailySimpleInterest(preEodPosition, endDate, position, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, calcFirst, calcLast, ref InterestAmount, ref TdInterestAmount); } - interest.InterestAmount = Math.Round(InterestAmount, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); - interest.TdInterestAmount = Math.Round(TdInterestAmount, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + interest.InterestAmount = Math.Round(InterestAmount, InterestCalculationPrecision, MidpointRounding.AwayFromZero); + interest.TdInterestAmount = Math.Round(TdInterestAmount, InterestCalculationPrecision, MidpointRounding.AwayFromZero); interest.InterestClosePnL = interest.InterestAmount * interestRatio; } if (add) @@ -1047,8 +1092,8 @@ namespace YLErp.Modules.SwapModule // consumedInterest 为绝对值口径(swap_flow_event.InterestAmount 之和),与 interest 口径一致。 interest -= consumedInterest; tdinterest -= consumedInterest; - InterestAmount = Math.Round(interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); - TdInterestAmount = Math.Round(tdinterest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + InterestAmount = Math.Round(interest, InterestCalculationPrecision, MidpointRounding.AwayFromZero); + TdInterestAmount = Math.Round(tdinterest, InterestCalculationPrecision, MidpointRounding.AwayFromZero); } /// @@ -1108,8 +1153,8 @@ namespace YLErp.Modules.SwapModule tdinterest += tdinterest1; } } - InterestAmount = Math.Round(interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); - TdInterestAmount = Math.Round(tdinterest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + InterestAmount = Math.Round(interest, InterestCalculationPrecision, MidpointRounding.AwayFromZero); + TdInterestAmount = Math.Round(tdinterest, InterestCalculationPrecision, MidpointRounding.AwayFromZero); } /// @@ -1178,8 +1223,8 @@ namespace YLErp.Modules.SwapModule tdinterest = tdinterest1; } flowEvent.FloatRate = Convert.ToDecimal(floatRate); - InterestAmount = Math.Round(interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); - TdInterestAmount = Math.Round(tdinterest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + InterestAmount = Math.Round(interest, InterestCalculationPrecision, MidpointRounding.AwayFromZero); + TdInterestAmount = Math.Round(tdinterest, InterestCalculationPrecision, MidpointRounding.AwayFromZero); } /// @@ -1231,8 +1276,8 @@ namespace YLErp.Modules.SwapModule tdinterest /= annualDays; } - InterestAmount = Math.Round(interestProfitSum+interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); - TdInterestAmount = Math.Round(tdinterest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + InterestAmount = Math.Round(interestProfitSum + interest, InterestCalculationPrecision, MidpointRounding.AwayFromZero); + TdInterestAmount = Math.Round(tdinterest, InterestCalculationPrecision, MidpointRounding.AwayFromZero); } /// @@ -1248,6 +1293,7 @@ namespace YLErp.Modules.SwapModule throw new ServiceException("未找到交易信息"); } NormalizeNotionalValues(unwindData); + NormalizeManualSettlementAmounts(unwindData, (int)SwapEventTypeEnum.平仓, "系统操作_平仓"); //CheckLastEod(unwindData.ValueDate, td.StartDate.Value, unwindData.SwapTradeId); //去掉平仓收盘限制 ValidateFrontendPnL(unwindData, isIncome: false); // 只读校验告警,不阻断交易 // 前端按"占期初(original)"语义传 ClosePercent(A);后端全链路按"占剩余(remaining)"语义(B)消费。 @@ -1651,6 +1697,7 @@ namespace YLErp.Modules.SwapModule throw new ServiceException("未找到交易信息"); } unwindData.SwapRealizedPnL = unwindData.SwapCloseAmount; + NormalizeManualSettlementAmounts(unwindData, (int)SwapEventTypeEnum.平仓, "系统操作_平仓"); var trans = DbContext.Database.BeginTransaction(); try { @@ -1694,6 +1741,7 @@ namespace YLErp.Modules.SwapModule throw new ServiceException("未找到交易信息"); } unwindData.SwapRealizedPnL = unwindData.SwapCloseAmount; + NormalizeManualSettlementAmounts(unwindData, (int)SwapEventTypeEnum.互换, "系统操作_互换"); var trans = DbContext.Database.BeginTransaction(); try { @@ -1733,6 +1781,7 @@ namespace YLErp.Modules.SwapModule } NormalizeIncomeUnwindDate(unwindData); ValidateIncomeValueDate(unwindData, td); + NormalizeManualSettlementAmounts(unwindData, (int)SwapEventTypeEnum.互换, "系统操作_互换"); //CheckLastEod(unwindData.ValueDate, td.StartDate.Value, unwindData.SwapTradeId); //去掉平仓收盘限制 ValidateFrontendPnL(unwindData, isIncome: true); // 只读校验告警,不阻断交易 ExecuteInTransaction(() => @@ -1825,6 +1874,7 @@ namespace YLErp.Modules.SwapModule ValidateIncomeValueDate(unwindData, td); } unwindData.SwapRealizedPnL = unwindData.SwapCloseAmount; + NormalizeManualSettlementAmounts(unwindData, eventType, eventType == (int)SwapEventTypeEnum.互换 ? "系统操作_互换" : "系统操作_平仓"); // 前端按"占期初(original)"语义传 ClosePercent(A);后端全链路按"占剩余(remaining)"语义(B)消费。 // 入口统一转换为 B,落库展示用的 A 由 SaveSwapDealInternal 还原。 // 与 SwapUnwind(L1270) 保持一致——缺少此转换会导致 SaveSwapDealInternal 的 B→A 还原出错 @@ -1878,6 +1928,7 @@ namespace YLErp.Modules.SwapModule throw new ServiceException("未找到交易信息"); } var flowList = new List(unwindData.FlowEvents); + NormalizeSettledInterestAmounts(flowList, eventType, eventResason); unwindData.FlowEvents.Clear(); // 落库展示用"占期初(original)"语义(A);计算链(费用递减/全平判定)用"占剩余(remaining)"语义(B)。 // 序列化前把 ClosePercent 还原为 A,序列化后立即还原回 B 供后续使用。 @@ -1977,7 +2028,10 @@ namespace YLErp.Modules.SwapModule position.InterestFeePending += interest.InterestFee; if ((interest.InterestMode == (int)InterestModeEnum.追加预付金 || interest.InterestMode == (int)InterestModeEnum.初始预付金) && eventType == (int)SwapEventTypeEnum.平仓) { - position.InterestPrincipalFix -= interest.InterestPrincipal; + position.InterestPrincipalFix = Math.Round( + position.InterestPrincipalFix - interest.InterestPrincipal, + ConsGlobal.MoneyRound, + MidpointRounding.AwayFromZero); } } } diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs index 9875528a..ca4cf2e4 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs @@ -47,11 +47,72 @@ namespace YLErp.Modules.SwapModule : ConsGlobal.SwapDeliveryPriceRound; } + // 日终利息待实现需跨日累计,按表设计保留 12 位;已实现结算仍按金额两位处理。 + private const int EodInterestStoragePrecision = 12; + + private static decimal RoundMoney(decimal value) + { + return Math.Round(value, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); + } + + private static decimal RoundEodInterest(decimal value) + { + return Math.Round(value, EodInterestStoragePrecision, MidpointRounding.AwayFromZero); + } + + /// + /// 仅在写入 eod_swap_position 前统一快照精度。 + /// 浮动腿收益最终以金额两位展示和存储;利息腿的待实现、计息基数及利率保留 12 位, + /// 使部分结算后的尾差可继续参与后续计息。 + /// + private static void NormalizeEodPositionForStorage(eod_swap_position position) + { + if (string.IsNullOrEmpty(position.UnderlyingCode)) + { + // 利息腿没有标的代码:待实现字段保留高精度,已实现结算字段收敛到金额两位。 + position.InterestPrincipalFix = RoundEodInterest(position.InterestPrincipalFix); + position.InterestRateDefault = RoundEodInterest(position.InterestRateDefault); + position.InterestFeePending = RoundEodInterest(position.InterestFeePending); + position.TdInterestPrincipal = RoundEodInterest(position.TdInterestPrincipal); + position.TdInterestRate = RoundEodInterest(position.TdInterestRate); + position.TdInterestIncome = RoundEodInterest(position.TdInterestIncome); + position.TdInterestFee = RoundEodInterest(position.TdInterestFee); + position.InterestIncomeSum = RoundEodInterest(position.InterestIncomeSum); + position.InterestFeeSum = RoundEodInterest(position.InterestFeeSum); + position.InterestProfitSum = RoundEodInterest(position.InterestProfitSum); + position.FloatRate = RoundEodInterest(position.FloatRate); + position.SwapPositionValue = RoundEodInterest(position.SwapPositionValue); + position.TdCloseInterest = RoundMoney(position.TdCloseInterest); + position.TdCloseInterestFee = RoundMoney(position.TdCloseInterestFee); + position.RealizedInterest = RoundMoney(position.RealizedInterest); + position.RealizedInterestFee = RoundMoney(position.RealizedInterestFee); + } + else + { + // 浮动腿有标的代码:其损益作为金额结果落库,统一按两位四舍五入。 + position.TdPosiDividend = RoundMoney(position.TdPosiDividend); + position.PosiMtmPnL = RoundMoney(position.PosiMtmPnL); + position.PosiDividendSum = RoundMoney(position.PosiDividendSum); + position.PosiFeePending = RoundMoney(position.PosiFeePending); + position.PosiProfitSum = RoundMoney(position.PosiProfitSum); + position.TdCloseMtmPnl = RoundMoney(position.TdCloseMtmPnl); + position.TdCloseDividend = RoundMoney(position.TdCloseDividend); + position.TdCloseFee = RoundMoney(position.TdCloseFee); + position.RealizedMtmPnL = RoundMoney(position.RealizedMtmPnL); + position.RealizedDividend = RoundMoney(position.RealizedDividend); + position.RealizedFee = RoundMoney(position.RealizedFee); + position.SwapPositionValue = RoundMoney(position.SwapPositionValue); + } + position.RealizedPnl = RoundMoney(position.RealizedPnl); + } + #region 可测试化接缝(Seams)——override 这些虚方法可在测试中替换 DB/外部调用,生产代码行为不变 /// 持久化 eod 持仓记录(生产: DbContext.Add;测试: 收集到列表) protected virtual void PersistEodSwapPosition(eod_swap_position position) { + // 所有新增或更新的日终持仓都经过此入口,避免不同日终分支出现精度差异。 + NormalizeEodPositionForStorage(position); var storagePriceRound = GetStorageDeliveryPriceRound(position.UnderlyingInstrumentType, position.UnderlyingCode); position.PosiGrossPrice = Math.Round(position.PosiGrossPrice, storagePriceRound, MidpointRounding.AwayFromZero); position.UnderlyingPrice = Math.Round(position.UnderlyingPrice, storagePriceRound, MidpointRounding.AwayFromZero); @@ -1017,8 +1078,17 @@ namespace YLErp.Modules.SwapModule intersetAcmount /= tradeExtend.AnnualDays; } newEodPayPosition.TdInterestIncome = intersetAcmount;// 要算一下当天产生的利息 - newEodPayPosition.InterestIncomeSum = eodPayPosition.InterestIncomeSum + newEodPayPosition.TdInterestIncome - newEodPayPosition.TdCloseInterest; //上一天待实现 + 当天产生的利息 - flowEvents的利息 - newEodPayPosition.InterestFeeSum = eodPayPosition.InterestFeeSum + newEodPayPosition.TdInterestFee - newEodPayPosition.TdCloseInterestFee; + if (valueDate >= td.ExerciseDate.Value) + { + // 当前分支已有最终收益结算事件:该事件已包含待实现余额并按两位结出,快照不再留存尾差。 + newEodPayPosition.InterestIncomeSum = 0; + newEodPayPosition.InterestFeeSum = 0; + } + else + { + newEodPayPosition.InterestIncomeSum = eodPayPosition.InterestIncomeSum + newEodPayPosition.TdInterestIncome - newEodPayPosition.TdCloseInterest; + newEodPayPosition.InterestFeeSum = eodPayPosition.InterestFeeSum + newEodPayPosition.TdInterestFee - newEodPayPosition.TdCloseInterestFee; + } newEodPayPosition.InterestProfitSum = newEodPayPosition.InterestIncomeSum + newEodPayPosition.InterestFeeSum; //持仓价值 newEodPayPosition.SwapPositionValue = newEodPayPosition.InterestProfitSum * ratio + newEodPayPosition.PosiProfitSum; @@ -1277,14 +1347,16 @@ namespace YLErp.Modules.SwapModule $",TdCloseInterestFee is {newEodPayPosition.TdCloseInterestFee}"); if (closePercent == 1) { + // 全量平仓后不应把待实现利息或费用带入下一交易日。 newEodPayPosition.InterestIncomeSum = 0; + newEodPayPosition.InterestFeeSum = 0; } else { newEodPayPosition.InterestIncomeSum = InterestAmount; + newEodPayPosition.InterestFeeSum = eodPayPosition.InterestFeeSum + newEodPayPosition.TdInterestFee - newEodPayPosition.TdCloseInterestFee; } //持仓内容-利息腿-损益统计(本方视角) - newEodPayPosition.InterestFeeSum = eodPayPosition.InterestFeeSum + newEodPayPosition.TdInterestFee - newEodPayPosition.TdCloseInterestFee; newEodPayPosition.InterestProfitSum = newEodPayPosition.InterestIncomeSum + newEodPayPosition.InterestFeeSum; //持仓价值 newEodPayPosition.SwapPositionValue = newEodPayPosition.InterestProfitSum * ratio + newEodPayPosition.PosiProfitSum; diff --git a/YLErpDAL/Modules/SwapModule/SwapFlowEventService.cs b/YLErpDAL/Modules/SwapModule/SwapFlowEventService.cs index 2b28cca0..c986aa8a 100644 --- a/YLErpDAL/Modules/SwapModule/SwapFlowEventService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapFlowEventService.cs @@ -460,7 +460,7 @@ namespace YLErp.Modules.SwapModule flow_Event.InterestDirection = position.InterestDirection; flow_Event.InterestRate = position.InterestRateDefault; - flow_Event.InterestPrincipal = position.InterestPrincipalFix; + flow_Event.InterestPrincipal = Math.Round(position.InterestPrincipalFix, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); flow_Event.InterestSwapInterval = position.InterestSwapInterval; flow_Event.InterestMode = position.InterestMode; flow_Event.UnderlyingInstrumentType = position.UnderlyingInstrumentType; diff --git a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs index 3c673d43..ffd85f89 100644 --- a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs @@ -1382,7 +1382,7 @@ namespace YLErp.Modules.SwapModule position.InterestDirection = swap.InterestDirection; position.InterestMode = swap.InterestMode; position.InterestRateDefault = swap.InterestRateDefault; - position.InterestPrincipalFix = swap.InterestPrincipalFix; + position.InterestPrincipalFix = Math.Round(swap.InterestPrincipalFix, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); position.InterestSwapInterval = swap.InterestSwapInterval; position.PosiStartDate = td.StartDate.Value; position.PosiMatuirityDate = td.ExerciseDate.Value; @@ -1656,7 +1656,7 @@ namespace YLErp.Modules.SwapModule { posi.InterestAmount = eodPosi.RealizedInterest; posi.InterestFeePending = eodPosi.InterestFeePending; - posi.InterestPrincipalFix= eodPosi.InterestPrincipalFix; + posi.InterestPrincipalFix = Math.Round(eodPosi.InterestPrincipalFix, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero); posi.PosiTradingFeePending = eodPosi.PosiFeePending; posi.PosiDividendIncome = eodPosi.PosiDividendSum; posi.PosiQuantity = eodPosi.PosiQuantity;