From 4b9bcfb2dc0ab831f3d8d7321515f1dc0edadaf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=96=B9=E6=B5=B7?= Date: Fri, 18 Apr 2025 17:00:25 +0800 Subject: [PATCH] =?UTF-8?q?bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs | 3 +++ .../Modules/RiskModule/QuotaMonitorService.cs | 7 +++--- .../Modules/SwapModule/SwapDealService.cs | 11 +++++----- .../SwapModule/SwapEodPositionService.cs | 22 +++++++++++++------ .../SwapModule/SwapTradeAutoService.cs | 2 +- YLErpWeb/Views/SwapTrade2/SwapIncome.cshtml | 2 +- YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml | 3 +-- .../Scripts/app/swaptrade/EodPositionRisks.js | 4 ++-- .../Scripts/app/swaptrade/incomeSwapTrade.js | 11 +++++----- .../Scripts/app/swaptrade/unwindSwapTrade.js | 11 +++++----- 10 files changed, 42 insertions(+), 34 deletions(-) diff --git a/YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs b/YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs index 887a8714..5a5891ca 100644 --- a/YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs +++ b/YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs @@ -667,6 +667,9 @@ namespace YLErp.BLL.Eod bondDb.SaveChanges(); } } + sql = $"{nameof(ClientPosition.create_time)}<'{datenow.AddSeconds(-1):yyyy-MM-dd HH:mm:ss}' or {nameof(ClientPosition.position_qty)}=0"; + bondDb.BulkDelete(sql); + bondDb.SaveChanges(); #endregion return realtimePositionList; } diff --git a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs index 6109aa61..dcffef4c 100644 --- a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs +++ b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs @@ -4312,11 +4312,12 @@ namespace YLErp.Modules.RiskModule { var um = ums.FirstOrDefault(x => x.UnderlyingCode == item.security_id); var bondPrice = EodPriceQueryService.GetBondPrice(dealDate, item.security_id); - double lastPrice = bondPrice != null ? bondPrice.ClosePrice : (um.Price ?? 0) * Convert.ToDouble(ConsGlobal.bondPriceMultiple); + double lastPrice = bondPrice != null ? bondPrice.ClosePrice : (um?.Price ?? 0) * Convert.ToDouble(ConsGlobal.bondPriceMultiple); var bond = new UnderlyingBond(); - if (um.IsBond()&&string.IsNullOrEmpty(um.ExJson)) { + if (um!=null&& um.IsBond()&&string.IsNullOrEmpty(um.ExJson)) { bond = JsonHelper.Deserialize(um.ExJson); } + bond.IssueSize = bond.IssueSize ?? 0; return new CheckQuotaMoitorModel { Qty = item.position_qty ?? 0, @@ -4333,7 +4334,7 @@ namespace YLErp.Modules.RiskModule Delta = (decimal)((item.side == 0 ? item.deal_full_price_avg : -item.deal_full_price_avg) * (item.position_qty ?? 0) * ConsGlobal.bondPriceMultiple), UnderlyingId = um?.id ?? 0, LastPrice = (decimal)lastPrice, - Circulation = (bond.IssueSize * 100000000m) ?? 0, + Circulation = (bond.IssueSize * 100000000) ?? 0, Pnl = (decimal)((item.full_price_now - item.deal_full_price_avg) * (item.position_qty ?? 0) * ConsGlobal.bondPriceMultiple), Current = item.Current, }; diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index 8ac87b9a..f3345033 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -409,7 +409,6 @@ namespace YLErp.Modules.SwapModule _posiNotionalValue = position.InterestPrincipalFix * closePrecent; positionClone.InterestDirection = position.InterestDirection == (int)SwapDirectionEnum.收取 ? (int)SwapDirectionEnum.支付 : (int)SwapDirectionEnum.收取; } - var calendar = "chn"; if (!string.IsNullOrEmpty(position.FloatRateUnderlyingCode)) { // 获取重置频率,如果为空则默认为1 @@ -418,7 +417,7 @@ namespace YLErp.Modules.SwapModule // 计算从 td.StartDate 到 endDate 的天数 var days = (endDate - td.StartDate.Value).Days; // 获取合适的 rateDate - DateTime rateDate = GetRateDate(position.interest_rule, td.StartDate.Value, endDate, days, interestPeriod, calendar); + DateTime rateDate = GetRateDate(position.interest_rule, td.StartDate.Value, endDate, days, interestPeriod); // 如果不需要重置,并且上一日已有 FloatRate,则不再查找 if (preEodPosition.id != 0 && days % interestPeriod != 0) @@ -434,7 +433,7 @@ namespace YLErp.Modules.SwapModule position.FloatRate = Convert.ToDecimal(floatRate); positionClone.FloatRate = position.FloatRate; } - else + else if(!swap) { throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{rateDate:yyyy年MM月dd日}的价格"); } @@ -467,16 +466,16 @@ namespace YLErp.Modules.SwapModule /// /// 根据给定条件获取 rateDate /// - private DateTime GetRateDate(int? interest_rule, DateTime startDate, DateTime endDate, int days, int interestPeriod, string calendar) + private DateTime GetRateDate(int? interest_rule, DateTime startDate, DateTime endDate, int days, int interestPeriod) { // 判断是否达到重置周期 if (days % interestPeriod == 0) { - return QdpCalendarHelper.GetNonHolidayDefore(endDate.AddDays(interest_rule ?? 0), calendar); + return QdpCalendarHelper.GetNonHolidayDefore(endDate.AddDays(interest_rule ?? 0)); } // 如果不在重置周期内,使用 td.StartDate 来获取 rateDate - return QdpCalendarHelper.GetNonHolidayDefore(startDate.AddDays(interest_rule ?? 0), calendar); + return QdpCalendarHelper.GetNonHolidayDefore(startDate.AddDays(interest_rule ?? 0)); } /// /// 初始化利息腿信息 diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs index 531160cb..34ac96d9 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs @@ -139,7 +139,15 @@ namespace YLErp.Modules.SwapModule var longEventTypes = eventTyps; longEventTypes.Add((int)SwapFlowEventTypeEnum.开仓); var flowEvents = new List(); - Expression> eventExpression = x => x.SwapTradeId == td.id && x.DataState == (int)SwapFlowDateStateEnum.完成 && longEventTypes.Contains(x.EventType)&& x.EventDate == settleDate; + Expression> eventExpression = x => x.SwapTradeId == td.id && x.DataState == (int)SwapFlowDateStateEnum.完成 && longEventTypes.Contains(x.EventType); + if (settleDate == td.TradeDate) + { + eventExpression = eventExpression.And(x => x.EventDate == settleDate); + } + else + { + eventExpression = eventExpression.And(x => x.UnwindDate == settleDate); + } flowEvents = DbContext.swap_flow_event.Where(eventExpression).ToList(); var preDealDate = GetPreDealDate(td.id, settleDate, eventTyps);//上一次平仓/互换/自动互换处理日期 List autoInterests = new List();//自动互换利息腿信息 @@ -1341,15 +1349,15 @@ namespace YLErp.Modules.SwapModule curretEod.PosiTradingFee = position.PosiTradingFee; curretEod.UnderlyingPrice = UnderlyingCodePrice(position.UnderlyingCode, dealDate, out decimal vobp); SetPriceInfoByFlowEvent(eod, curretEod, unwindEvents, position); - if (settleDate == td.TradeDate) - { - curretEod.UnderlyingPrice = curretEod.PosiGrossPrice; - //curretEod.TdCloseMtmPnl = 0; - //curretEod.TdCloseFee = 0; - } curretEod.TdCloseDividend = curretEod.TdPosiDividend; curretEod.UnderlyingMarketValue = curretEod.UnderlyingPrice * curretEod.PosiQuantity * curretEod.ContractSize * shortRatio; curretEod.PosiMtmPnL = (curretEod.UnderlyingPrice - curretEod.PosiGrossPrice) * curretEod.PosiQuantity * curretEod.ContractSize * shortRatio * directionRatio; + if (settleDate == td.TradeDate) + { + curretEod.PosiMtmPnL = 0; + //curretEod.TdCloseMtmPnl = 0; + //curretEod.TdCloseFee = 0; + } curretEod.PosiDividendSum = curretEod.TdPosiDividend; curretEod.PosiProfitSum = curretEod.PosiMtmPnL + curretEod.PosiDividendSum + curretEod.VTradingFee; curretEod.RealizedMtmPnL = curretEod.TdCloseMtmPnl; diff --git a/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs b/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs index 1f159820..5dd07db5 100644 --- a/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs @@ -1208,7 +1208,7 @@ namespace YLErp.Modules.SwapModule var unwindPercent =1- (flowQty / swapFlow.TradingQty); var fee = (1 - unwindPercent) * swapFlow.TradingFeePending; swapFlow.TradingQty = flowQty; - swapFlow.TradingAmount = swapFlow.TradingQty; + swapFlow.TradingAmount = swapFlow.TradingQty* swapFlow.TradingAmountAvg; swapFlow.TradingFeePending = fee; return NewSwapTrade(swapFlow, client, asset, underlying, floatRate, clientMarginTemplate,clearingAgency); } diff --git a/YLErpWeb/Views/SwapTrade2/SwapIncome.cshtml b/YLErpWeb/Views/SwapTrade2/SwapIncome.cshtml index 98b8c1a4..d17f8053 100644 --- a/YLErpWeb/Views/SwapTrade2/SwapIncome.cshtml +++ b/YLErpWeb/Views/SwapTrade2/SwapIncome.cshtml @@ -146,7 +146,7 @@ {{priceFormat(floatPosition.PosiGrossPrice)}} {{priceFormat(floatPosition.TradingAmountNetAvg)}} - + diff --git a/YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml b/YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml index 8b88a357..a34d3a21 100644 --- a/YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml +++ b/YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml @@ -197,8 +197,7 @@ {{priceFormat(floatPosition.PosiGrossPrice)}} - - + diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js index c0691b8f..3818a18f 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/EodPositionRisks.js @@ -185,9 +185,9 @@ function colModelGridEodPosition() { align: 'center', formatter: StockEqvNotionalFormat }, { - name: 'eodPosition.PosiTradingFee', + name: 'eodPosition.PosiFeePending', label: '交易费用佣金', - index: 'eodPosition.PosiTradingFee', + index: 'eodPosition.PosiFeePending', width: 90, align: 'center', formatter: StockEqvNotionalFormat diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/incomeSwapTrade.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/incomeSwapTrade.js index 15f9b317..7c990171 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/incomeSwapTrade.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/incomeSwapTrade.js @@ -104,9 +104,7 @@ const vue = new Vue({ main.post("/underlying_manager/GetUnderlyingPriceByCode", { code: thisObj.floatPosition.UnderlyingCode, ValueDate: thisObj.deal.ValueDate }) .done(function (res) { - if (thisObj.deal.StructureType != '普通收益互换') { - res.obj = res.obj * 1; - } + res.obj = res.obj * 100; thisObj.floatPosition.TradingAmountAvg = otcformat.trading.umprice(res.obj); thisObj.calcFloatClosePnl(); }); @@ -125,7 +123,7 @@ const vue = new Vue({ let floatRatio = thisObj.floatPosition.PayDirection == 1 ? 1 : -1; let TradingFee = thisObj.floatPosition.TradingFee == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFee); let TradingFeePending = thisObj.floatPosition.TradingFeePending == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFeePending); - thisObj.floatPosition.MarkClosePnl = thisObj.deal.CloseNotionalValue * (thisObj.floatPosition.TradingAmountAvg - thisObj.initPosiNetPrice) * floatRatio; + thisObj.floatPosition.MarkClosePnl = thisObj.deal.CloseNotionalValue * (thisObj.floatPosition.TradingAmountAvg*0.01 - thisObj.initPosiNetPrice) * floatRatio; thisObj.floatPosition.MarkClosePnl = thisObj.floatPosition.MarkClosePnl + TradingFee + TradingFeePending + parseFloat(thisObj.floatPosition.DividendIn); thisObj.floatPosition.MarkClosePnl = otcformat.trading.StockEqvNotional(thisObj.floatPosition.MarkClosePnl); thisObj.calcCloseAmount(); @@ -144,12 +142,12 @@ const vue = new Vue({ thisObj.deal.SwapRealizedPnL = pnl; thisObj.deal.SwapMarginRebatePnl = 0; thisObj.deal.SwapMarginAmount = 0; - thisObj.floatPosition.TradingAmount = parseFloat(thisObj.floatPosition.TradingAmountAvg) * parseFloat(thisObj.deal.CloseNotionalValue); + thisObj.floatPosition.TradingAmount = parseFloat(thisObj.floatPosition.TradingAmountAvg) * parseFloat(thisObj.deal.CloseNotionalValue) * 0.01; thisObj.floatPosition.CloseFee = TradingFee; if (thisObj.deal.PositionQty == 0) { thisObj.floatPosition.TradingAmountFeeAvg = 0; } else { - thisObj.floatPosition.TradingAmountFeeAvg = parseFloat(thisObj.floatPosition.TradingAmountAvg) + (TradingFee / thisObj.deal.CloseQty) * ratio; + thisObj.floatPosition.TradingAmountFeeAvg = parseFloat(thisObj.floatPosition.TradingAmountAvg) * 0.01 + (TradingFee / thisObj.deal.CloseQty) * ratio; } this.interestList.forEach(x => { //let interestRatio = x.InterestDirection == 1 ? 1 : -1; @@ -196,6 +194,7 @@ const vue = new Vue({ thisObj.floatPosition.EventDate = thisObj.deal.ValueDate; let floatPosition = _.cloneDeep(thisObj.floatPosition); floatPosition.Quantity = 0; + floatPosition.TradingAmountAvg = floatPosition.TradingAmountAvg * 0.01; reqObj.FlowEvents.push(floatPosition); var postData = { unwindData: reqObj }; var msg = "确认提交收益结算?"; diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js index 9d5f79d8..e7aa1633 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js @@ -181,9 +181,7 @@ const vue = new Vue({ main.post("/underlying_manager/GetUnderlyingPriceByCode", { code: thisObj.floatPosition.UnderlyingCode, valuedate: thisObj.deal.ValueDate }) .done(function (res) { - if (thisObj.deal.StructureType != '普通收益互换') { - res.obj = res.obj * 1; - } + res.obj = res.obj * 100; thisObj.floatPosition.TradingAmountAvg = otcformat.trading.tradeSinglePrice(res.obj); thisObj.calcFloatClosePnl(); }); @@ -194,7 +192,7 @@ const vue = new Vue({ let longRatio = thisObj.floatPosition.PositionType == 1 ? 1 : -1; let TradingFee = thisObj.floatPosition.TradingFee == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFee); let TradingFeePending = thisObj.floatPosition.TradingFeePending == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFeePending); - thisObj.floatPosition.MarkClosePnl = Math.round(thisObj.deal.CloseQty * (thisObj.floatPosition.TradingAmountAvg - thisObj.initPosiNetPrice) * floatRatio * longRatio * 10000) / 10000; + thisObj.floatPosition.MarkClosePnl = Math.round(thisObj.deal.CloseQty * (thisObj.floatPosition.TradingAmountAvg*0.01 - thisObj.initPosiNetPrice) * floatRatio * longRatio * 10000) / 10000; thisObj.floatPosition.MarkClosePnl = Number(thisObj.floatPosition.MarkClosePnl.toFixed(2)); thisObj.floatPosition.MarkClosePnl = thisObj.floatPosition.MarkClosePnl + (TradingFee + TradingFeePending) * floatRatio * -1 + parseFloat(thisObj.floatPosition.DividendIn); thisObj.floatPosition.MarkClosePnl = otcformat.trading.StockEqvNotional(thisObj.floatPosition.MarkClosePnl); @@ -224,12 +222,12 @@ const vue = new Vue({ thisObj.deal.SwapRealizedPnL = pnl; thisObj.deal.SwapMarginRebatePnl = 0; thisObj.deal.SwapMarginAmount = 0; - thisObj.floatPosition.TradingAmount = parseFloat(thisObj.floatPosition.TradingAmountAvg) * parseFloat(thisObj.deal.CloseNotionalValue); + thisObj.floatPosition.TradingAmount = parseFloat(thisObj.floatPosition.TradingAmountAvg) * parseFloat(thisObj.deal.CloseNotionalValue) * 0.01; thisObj.floatPosition.CloseFee = TradingFee; if (thisObj.deal.CloseQty == 0) { thisObj.floatPosition.TradingAmountFeeAvg = 0; } else { - thisObj.floatPosition.TradingAmountFeeAvg = parseFloat(thisObj.floatPosition.TradingAmountAvg) + (TradingFee / thisObj.deal.CloseQty) * ratio; + thisObj.floatPosition.TradingAmountFeeAvg = parseFloat(thisObj.floatPosition.TradingAmountAvg) * 0.01 + (TradingFee / thisObj.deal.CloseQty) * ratio; } this.interestList.forEach(x => { /*let interestRatio = x.InterestDirection == 1 ? 1 : -1;*/ @@ -304,6 +302,7 @@ const vue = new Vue({ thisObj.floatPosition.EventDate = thisObj.deal.ValueDate; let floatPosition = _.cloneDeep(thisObj.floatPosition); floatPosition.Quantity = reqObj.CloseQty; + floatPosition.TradingAmountAvg = floatPosition.TradingAmountAvg * 0.01; reqObj.FlowEvents.push(floatPosition); var postData = { unwindData: reqObj }; var msg = "确认提交平仓?";