From 7c993f7bb26817ff073fe8e426ecd9bb5c0d4ba5 Mon Sep 17 00:00:00 2001 From: hjhan Date: Thu, 2 Jul 2026 08:57:55 +0800 Subject: [PATCH] =?UTF-8?q?refactor(swap):=20DealFloatPositions=E5=A4=96?= =?UTF-8?q?=E9=83=A8=E4=BE=9D=E8=B5=96=E8=99=9A=E6=96=B9=E6=B3=95=E6=8E=A5?= =?UTF-8?q?=E7=BC=9D(=E5=88=86=E7=BA=A2=E5=9C=BA=E6=99=AF=E5=87=86?= =?UTF-8?q?=E5=A4=87)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 加3个protected virtual虚方法: - GetUnderlyingPrice: 标的市场价格(原UnderlyingCodePrice) - GetUnderlyingData: 标的缓存数据(原DataCacheProvider) - CalcBondPayment: 债券付息(原new BondPaymentService) 替换CopyEodPosition/UpdateEodPosition/SaveCurrentEodInitalPosi 内部的外部调用为调虚方法,生产代码行为不变。 这3个接缝使浮动腿归档的分红计算可测(TdPosiDividend/PosiDividendSum)。 验证: 108个测试全通过。 --- .../SwapModule/SwapEodPositionService.cs | 41 +++++++++++++------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs index 0a8046e5..e2864304 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs @@ -153,6 +153,24 @@ namespace YLErp.Modules.SwapModule ClearSwapPositions(td, tradeDate, eventTypes, false); } + /// 获取标的市场价格(生产: UnderlyingCodePrice查缓存+中债估值;测试: 返回固定值) + protected virtual decimal GetUnderlyingPrice(string code, DateTime settleDate, out decimal vobp) + { + return UnderlyingCodePrice(code, settleDate, out vobp); + } + + /// 获取标的缓存数据(生产: DataCacheProvider;测试: 返回内存对象) + protected virtual underlying_manager GetUnderlyingData(string underlyingCode) + { + return DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode); + } + + /// 计算债券付息(生产: BondPaymentService;测试: 返回固定值) + protected virtual decimal CalcBondPayment(string underlyingCode, DateTime fromDate, DateTime toDate, decimal qty, int shortRatio, int directionRatio) + { + return new BondPaymentService(UserInfo).CalcPayment(underlyingCode, fromDate, toDate, qty, shortRatio, directionRatio); + } + #endregion /// @@ -1488,7 +1506,7 @@ namespace YLErp.Modules.SwapModule curretEod.id = 0; curretEod.ValueDate = valueDate; } - var um = DataCacheProvider.GetUnderlyingDataSource().GetData(eod.UnderlyingCode); + var um = GetUnderlyingData(eod.UnderlyingCode); if (um == null) { return curretEod; @@ -1497,13 +1515,12 @@ namespace YLErp.Modules.SwapModule int shortRatio = eod.PositionType == (int)PositionTypeFlag.Long ? 1 : -1; int directionRatio = eod.PosiDirection == (int)SwapDirectionEnum.收取 ? 1 : -1; curretEod.PosiStatus = curretEod.PosiQuantity == 0 ? 1 : 0; - var price = UnderlyingCodePrice(eod.UnderlyingCode, dealDate, out decimal vobp); + var price = GetUnderlyingPrice(eod.UnderlyingCode, dealDate, out decimal vobp); curretEod.dv01 = Dv01Helper.CalcDv01(eod.UnderlyingCode, curretEod.PosiQuantity, eod.PosiDirection, eod.PositionType, vobp); decimal tax = um.ValueAddedTax ?? 0; - BondPaymentService bondPaymentService = new BondPaymentService(UserInfo); if (valueDate > td.StartDate.Value && curretEod.PosiQuantity > 0) { - decimal payment = bondPaymentService.CalcPayment(curretEod.UnderlyingCode, eod.ValueDate, valueDate, curretEod.PosiQuantity, shortRatio, directionRatio); + decimal payment = CalcBondPayment(curretEod.UnderlyingCode, eod.ValueDate, valueDate, curretEod.PosiQuantity, shortRatio, directionRatio); // 考虑增值税 curretEod.TdPosiDividend = Math.Round(payment / (1 + tax) * (1 - tax), 2); } @@ -1570,7 +1587,7 @@ namespace YLErp.Modules.SwapModule curretEod.ValueDate = valueDate; } - var um = DataCacheProvider.GetUnderlyingDataSource().GetData(eod.UnderlyingCode); + var um = GetUnderlyingData(eod.UnderlyingCode); if (um == null) { return curretEod; @@ -1578,11 +1595,10 @@ namespace YLErp.Modules.SwapModule var dealDate = curretEod.ValueDate; int shortRatio = eod.PositionType == (int)PositionTypeFlag.Long ? 1 : -1; int directionRatio = eod.PosiDirection == (int)SwapDirectionEnum.收取 ? 1 : -1; - var price = UnderlyingCodePrice(eod.UnderlyingCode, dealDate, out decimal vobp); + var price = GetUnderlyingPrice(eod.UnderlyingCode, dealDate, out decimal vobp); var todayConsumedDividend = CalcConsumedDividend(curretEod, unwindEvents); var originNotional = (decimal)td.OriginalStockEqvNotional / swapPosition.PosiNetPrice; - BondPaymentService bondPaymentService = new BondPaymentService(UserInfo); - decimal totalPayment = bondPaymentService.CalcPayment(curretEod.UnderlyingCode, td.StartDate.Value, valueDate, (decimal)originNotional, shortRatio, directionRatio); + decimal totalPayment = CalcBondPayment(curretEod.UnderlyingCode, td.StartDate.Value, valueDate, (decimal)originNotional, shortRatio, directionRatio); decimal tax = um.ValueAddedTax ?? 0; decimal totalInterest = totalPayment / (1 + tax) * (1 - tax); SetPriceInfoByFlowEvent(eod, curretEod, unwindEvents, swapPosition); @@ -1595,7 +1611,7 @@ namespace YLErp.Modules.SwapModule // 修改,互换事件会影响待实现的分红的,现在要算上 if (valueDate > td.StartDate.Value && (curretEod.PosiQuantity > 0)) { - decimal payment = bondPaymentService.CalcPayment(curretEod.UnderlyingCode, eod.ValueDate, valueDate, curretEod.PosiQuantity, shortRatio, directionRatio); + decimal payment = CalcBondPayment(curretEod.UnderlyingCode, eod.ValueDate, valueDate, curretEod.PosiQuantity, shortRatio, directionRatio); curretEod.TdPosiDividend = Math.Round(payment / (1 + tax) * (1 - tax), 2); } curretEod.RealizedMtmPnL = eod.RealizedMtmPnL + curretEod.TdCloseMtmPnl; @@ -1737,7 +1753,7 @@ namespace YLErp.Modules.SwapModule protected eod_swap_position SaveCurrentEodInitalPosi(swap_position position, trade td, DateTime settleDate, DateTime preSettleDate, List unwindEvents) { eod_swap_position curretEod = new eod_swap_position(); - var um = DataCacheProvider.GetUnderlyingDataSource().GetData(position.UnderlyingCode); + var um = GetUnderlyingData(position.UnderlyingCode); if (um == null) { return curretEod; @@ -1770,7 +1786,7 @@ namespace YLErp.Modules.SwapModule curretEod.ContractSize = position.ContractSize; curretEod.CountRatio = position.CountRatio; curretEod.PosiTradingFee = position.PosiTradingFee; - curretEod.UnderlyingPrice = UnderlyingCodePrice(position.UnderlyingCode, dealDate, out decimal vobp); + curretEod.UnderlyingPrice = GetUnderlyingPrice(position.UnderlyingCode, dealDate, out decimal vobp); SetPriceInfoByFlowEvent(eod, curretEod, unwindEvents, position); curretEod.dv01 = Dv01Helper.CalcDv01(curretEod.UnderlyingCode, curretEod.PosiQuantity, curretEod.PosiDirection, curretEod.PositionType, vobp); //if (settleDate == td.TradeDate) @@ -1787,8 +1803,7 @@ namespace YLErp.Modules.SwapModule if (!hasSwapEvent && settleDate > td.StartDate.Value && curretEod.PosiQuantity > 0) { decimal tax = um.ValueAddedTax ?? 0; - BondPaymentService bondPaymentService = new BondPaymentService(UserInfo); - decimal payment = bondPaymentService.CalcPayment(curretEod.UnderlyingCode, td.StartDate.Value, settleDate, curretEod.PosiQuantity, shortRatio, directionRatio); + decimal payment = CalcBondPayment(curretEod.UnderlyingCode, td.StartDate.Value, settleDate, curretEod.PosiQuantity, shortRatio, directionRatio); payment = Math.Round(payment / (1 + tax) * (1 - tax), 2); //var consumedDividend = CalcConsumedDividend(curretEod, unwindEvents); 首日应该没有分红 curretEod.TdPosiDividend = payment;