From a2962cfc4bef30ae2c346dbe25bb1779dda0c9c4 Mon Sep 17 00:00:00 2001 From: gongpei Date: Sat, 11 Oct 2025 15:07:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=88=90=E4=BA=A4?= =?UTF-8?q?=E6=94=B6=E7=9B=8A=E7=8E=87=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YLErp.Core/DBModels/EodSwapPosition.cs | 3 ++ .../YLErp.Core/DBModels/SwapFlowMerge.cs | 5 ++ Framework/YLErp.Core/DBModels/SwapPosition.cs | 4 ++ YLErpDAL/Model/Trade.cs | 3 ++ .../SwapModule/SwapTradeAutoService.cs | 51 ++++++++++++++++++- .../Modules/SwapModule/SwapTradeService.cs | 4 +- YLErpWeb/Hubs/SwapFlowCombookingHub.cs | 2 +- YLErpWeb/Views/SwapTrade2/TradeView.cshtml | 5 ++ .../TradeMarketReport_EodPosition.js | 9 ++++ ...MarketReport_HistoricalPositionSwapFlow.js | 8 +++ .../Scripts/app/swaptrade/eventlist.js | 7 +++ 11 files changed, 98 insertions(+), 3 deletions(-) diff --git a/Framework/YLErp.Core/DBModels/EodSwapPosition.cs b/Framework/YLErp.Core/DBModels/EodSwapPosition.cs index 97439fe9..1a2944e9 100644 --- a/Framework/YLErp.Core/DBModels/EodSwapPosition.cs +++ b/Framework/YLErp.Core/DBModels/EodSwapPosition.cs @@ -119,6 +119,9 @@ namespace YLErp.DBModels [DisplayName("期初标的价格-不含费")] [DataChange] public decimal PosiGrossPrice { get; set; } + + /// 收益率 + /// /// 剩余持仓数量 /// diff --git a/Framework/YLErp.Core/DBModels/SwapFlowMerge.cs b/Framework/YLErp.Core/DBModels/SwapFlowMerge.cs index 12971f62..97aadf38 100644 --- a/Framework/YLErp.Core/DBModels/SwapFlowMerge.cs +++ b/Framework/YLErp.Core/DBModels/SwapFlowMerge.cs @@ -155,6 +155,11 @@ namespace YLErp.DBModels /// public decimal? TradingAmountNetFeeAvg { get; set; } + /// + /// 计算后的成交收益率 + /// + public decimal? InitYtm { get; set; } + /// /// 交易费用后付 /// diff --git a/Framework/YLErp.Core/DBModels/SwapPosition.cs b/Framework/YLErp.Core/DBModels/SwapPosition.cs index 5ba144d3..f9e1a8a8 100644 --- a/Framework/YLErp.Core/DBModels/SwapPosition.cs +++ b/Framework/YLErp.Core/DBModels/SwapPosition.cs @@ -230,6 +230,10 @@ namespace YLErp.DBModels /// public string UnderlyingInstrumentType { get; set; } /// + /// 期初收益率 + /// + public decimal InitYtm { get; set; } + /// /// 是否无效 /// public bool Invalid { get; set; } diff --git a/YLErpDAL/Model/Trade.cs b/YLErpDAL/Model/Trade.cs index 33fb6783..d0ae332e 100644 --- a/YLErpDAL/Model/Trade.cs +++ b/YLErpDAL/Model/Trade.cs @@ -335,6 +335,9 @@ namespace YLErp.DBModels [DisplayName("除权除息系数")] public double DividendRatio { get; internal set; } + [DisplayName("簿记后生成的成交收益率")] + public decimal InitYtm { get; set; } + public string GetDataTraceKeyInfo() { return "场外交易:" + TradeNumber; diff --git a/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs b/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs index b3966c9a..5e3d1a9b 100644 --- a/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapTradeAutoService.cs @@ -15,6 +15,8 @@ using Qdp.Pricing.Base.Implementations; using System.Linq; using System.Linq.Expressions; using System.Reflection; +using System.Text.Json; +using System.Text; using YLErp.BLL; using YLErp.BLL.Calculation; using YLErp.BLL.Eod; @@ -303,6 +305,51 @@ namespace YLErp.Modules.SwapModule var swapFlows = DbContext.swap_flow.Where(x => ids.Contains(x.id) && x.DataState == (int)SwapFlowDateStateEnum.等待完成 && x.ClientId > 0).ToList(); return swapFlows; } + + /// + /// 使用不含费全价(加权平均全精度)+日期 来计算 + /// + /// + public async Task CalcInitYtm(string symbol, DateTime valueDate, decimal tradingAmountAvg) + { + + using var client = new HttpClient(); + + var payload = new Dictionary + { + { "bondKey", symbol }, + { "settlementDate", valueDate }, + { "fullPrice", tradingAmountAvg } + }; + + string json = System.Text.Json.JsonSerializer.Serialize(payload); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + try + { + HttpResponseMessage response = await client.PostAsync("http://localhost:8080/v1/bond/", content); + response.EnsureSuccessStatusCode(); + + string responseBody = await response.Content.ReadAsStringAsync(); + using var doc = JsonDocument.Parse(responseBody); + if (doc.RootElement.TryGetProperty("yield", out var yieldElement)) + { + if (yieldElement.ValueKind == JsonValueKind.Number) + { + double d = yieldElement.GetDouble(); + return (decimal)d; + } + } + return null; + } + catch (Exception ex) + { + Console.WriteLine("请求失败: " + ex.Message); + return null; + } + } + + /// /// 簿记前自动校验 /// @@ -347,7 +394,7 @@ namespace YLErp.Modules.SwapModule /// 汇总流水 /// /// - public List SummaryFlow(List swapFlows, bool save = true) + public async Task> SummaryFlow(List swapFlows, DateTime valueDate, bool save = true) { var swapFlowGroup = swapFlows.GroupBy(g => new { g.ClientId, g.OccurTime, g.UnderlyingCode, g.BsType }).ToList(); List list = new List(); @@ -382,6 +429,8 @@ namespace YLErp.Modules.SwapModule swap_flow_summary.TradingAmountNetAvg = Math.Round(swap_flow_summary.TradingAmountNetAvg ?? 0, 10); swap_flow_summary.TradingAmountNetFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountNetAvg : swap_flow_summary.TradingAmountNetAvg + swap_flow_summary.TradingFeePending * tradeSide / swap_flow_summary.TradingQty; swap_flow_summary.TradingAmountNetFeeAvg = Math.Round(swap_flow_summary.TradingAmountNetFeeAvg ?? 0, 10); + // 计算收益率 + swap_flow_summary.InitYtm = await CalcInitYtm(gourpItem.Key.UnderlyingCode, valueDate, swap_flow_summary.TradingAmountAvg); swap_flow_summary.SetOpt(UserInfo); if (save) { diff --git a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs index a89b3414..e2d6fc5e 100644 --- a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs @@ -350,6 +350,7 @@ namespace YLErp.Modules.SwapModule td.ValidState = "Valid"; td.TradeSource = "系统交易"; td.TradeStatus = ConsTrade.确认成交; + td.InitYtm = flowMerge.InitYtm ?? 0; return td; } /// @@ -384,7 +385,8 @@ namespace YLErp.Modules.SwapModule OptTime = DateTime.Now, OptId = UserInfo.UserId, OptName = UserInfo.UserName, - UnderlyingInstrumentType = underlying.UnderlyingInstrumentType + UnderlyingInstrumentType = underlying.UnderlyingInstrumentType, + InitYtm = flowMerge.InitYtm ?? 0 }; td.swap_positions.Add(floatPosition); swap_position interestPosition = new swap_position() diff --git a/YLErpWeb/Hubs/SwapFlowCombookingHub.cs b/YLErpWeb/Hubs/SwapFlowCombookingHub.cs index 3183b55b..ed506b2a 100644 --- a/YLErpWeb/Hubs/SwapFlowCombookingHub.cs +++ b/YLErpWeb/Hubs/SwapFlowCombookingHub.cs @@ -57,7 +57,7 @@ namespace YLErp.Web.Hubs } currentStep = "正在合成流水"; await client.SendAsync("ReceiveMessage", currentStep); - var mergeList = service.SummaryFlow(swapFlows); + var mergeList = await service.SummaryFlow(swapFlows, req.tradeDate); // 数据校验逻辑 currentStep = "校验上一日是否收盘"; await client.SendAsync("ReceiveMessage", currentStep); diff --git a/YLErpWeb/Views/SwapTrade2/TradeView.cshtml b/YLErpWeb/Views/SwapTrade2/TradeView.cshtml index 037ecd37..03c2ce3d 100644 --- a/YLErpWeb/Views/SwapTrade2/TradeView.cshtml +++ b/YLErpWeb/Views/SwapTrade2/TradeView.cshtml @@ -24,6 +24,7 @@ bool isBond = trade.StructureType == "普通债券类收益互换"; string spotPriceTitle = "期初标的交割全价%"; string netSportPriceTitle = "期初标的交割净价%"; + string initYtmTitle = "期初标的成交收益率%"; var positions = trade.swap_positions.Where(x=>x.PosiDirection>0&&x.IsInitial).ToList(); var realPositions = trade.swap_positions.Where(x => x.PosiDirection > 0 && !x.IsInitial).ToList(); var sr = trade.trade_extend.ExtendObj.SettlementRules; @@ -364,6 +365,7 @@ 标的代码 @spotPriceTitle @netSportPriceTitle + @initYtmTitle 数量 交易费用后付 @@ -381,6 +383,9 @@ @(((item.PosiNetNoFeePrice ?? 0) * multiplier).OtcFormat(OtcFormatFlag.umprice)) + + @(((item.PosiNetNoFeePrice ?? 0) * multiplier).OtcFormat(OtcFormatFlag.umprice)) + @item.PosiQuantity.OtcFormat(OtcFormatFlag.StockEqvNotional) diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_EodPosition.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_EodPosition.js index 9d9142df..bf7e2f0f 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_EodPosition.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_EodPosition.js @@ -257,6 +257,15 @@ var colModelGrid = [ sortable: false, formatter: PriceFormat }, { + name: 'position.InitYtm', + label: '期初标的成交收益率', + index: 'position.InitYtm', + width: 100, + align: 'center', + sortable: false, + formatter: otcformat.trading.premiumRateP + }, + { name: 'position.UnderlyingPrice', label: '期末标的交割全价', index: 'position.UnderlyingPrice', diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_HistoricalPositionSwapFlow.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_HistoricalPositionSwapFlow.js index 2bf64007..4e86d688 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_HistoricalPositionSwapFlow.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/TradeMarketReport_HistoricalPositionSwapFlow.js @@ -225,6 +225,14 @@ var colModelGrid = [ align: 'center', formatter: PriceFormat }, { + name: 'FlowEvent.InitYtm', + label: '成交收益率', + index: 'FlowEvent.InitYtm', + width: 90, + align: 'center', + formatter: otcformat.trading.premiumRateP + }, + { name: 'FlowEvent.Quantity', label: '成交数量', index: 'FlowEvent.Quantity', diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/eventlist.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/eventlist.js index 50071c79..1838596e 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/eventlist.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/eventlist.js @@ -190,6 +190,13 @@ var getColModelGrid = function () { align: 'center', formatter: otcformat.trading.umprice }, { + name: 'InitYtm', + label: '成交收益率', + width: 90, + align: 'center', + formatter: otcformat.trading.premiumRateP + }, + { name: 'TradingAmountNetFeeAvg', label: '成交净价(含费)', width: 90,