From ce636c99f4c8ac141d2581ecf0565021dacb698f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=96=B9=E6=B5=B7?= Date: Wed, 13 Aug 2025 17:15:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8E=A5=E5=8F=A3=E9=87=8D?= =?UTF-8?q?=E6=96=B0=E8=AE=A1=E7=AE=97eod=5Ftrade=5Fposition?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Base/EodSettleDataQueryService.cs | 4 +- .../Controllers/eod_trade_valueController.cs | 193 +++++++++++++++++- 2 files changed, 194 insertions(+), 3 deletions(-) diff --git a/YLErpDAL/Modules/EodModule/SettlementModule/Base/EodSettleDataQueryService.cs b/YLErpDAL/Modules/EodModule/SettlementModule/Base/EodSettleDataQueryService.cs index 95729907..3cfa824b 100644 --- a/YLErpDAL/Modules/EodModule/SettlementModule/Base/EodSettleDataQueryService.cs +++ b/YLErpDAL/Modules/EodModule/SettlementModule/Base/EodSettleDataQueryService.cs @@ -56,9 +56,9 @@ namespace YLErp.Modules.EodModule.SettlementModule t.TradeType }; - var etList = etQuery.ToArray(); + var etList = etQuery.ToList(); List structProductTradeMetaList = null; - if (etList != null && etList.Length > 0) + if (etList != null && etList.Count() > 0) { var structProductTradeIds = etList.Where(p => "结构化产品".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList(); if (structProductTradeIds != null && structProductTradeIds.Count > 0) diff --git a/YLErpWeb/Controllers/eod_trade_valueController.cs b/YLErpWeb/Controllers/eod_trade_valueController.cs index 3db34847..c72a3275 100644 --- a/YLErpWeb/Controllers/eod_trade_valueController.cs +++ b/YLErpWeb/Controllers/eod_trade_valueController.cs @@ -1,4 +1,9 @@ -using YLErp.Model.Enum; +using Microsoft.AspNetCore.Authorization; +using System.Collections.Concurrent; +using System.Threading; +using YLErp.BLL.Eod; +using YLErp.DBModels; +using YLErp.Model.Enum; using YLErp.Modules.ClientModule; using YLErp.Modules.EodModule; using YLErp.Modules.EodModule.QueryModule; @@ -12,6 +17,7 @@ namespace YLErp.Web.Controllers { public class eod_trade_valueController : BaseController { + [MyAuthorize("结算管理-收盘操作")] public ActionResult eodExec() { @@ -629,5 +635,190 @@ namespace YLErp.Web.Controllers } #endregion + + #region 历史标的交易收盘 + [HttpGet] + [AllowAnonymous] + public JsonResult ExecuteEodPositionSettle() + { + try + { + string volType = "持仓"; + bool useClosePrice = true; + + // 1. 创建用户信息对象 + var userInfo = OptUserInfo.SystemUser; + + // 2. 获取 exchange_trade 表的最早和最晚交易日期 + var valueDate = valuedateBLL.ValueDate; + var earliestTradeDate = yldb.ExchangeTrade.Where(et => et.IsValid) + .Min(et => (DateTime?)et.TradeDate) ?? valueDate; + var latestTradeDate = EodOperationBase.GetLastSettlementDate(valueDate); + + // 计算预计处理的交易日数量 + var estimatedDays = 0; + var tempDate = earliestTradeDate; + while (tempDate <= latestTradeDate) + { + estimatedDays++; + tempDate = BLL.valuedateBLL.GetNonHoliday(tempDate.AddDays(1)); + } + + // 3. 异步执行结算任务 + var taskId = Guid.NewGuid().ToString(); + + // 初始化任务状态 + var cancellationTokenSource = new CancellationTokenSource(); + + Task.Run(async () => + { + try + { + await ExecuteEodPositionSettleAsync(userInfo, volType, useClosePrice, earliestTradeDate, latestTradeDate, taskId); + } + catch (OperationCanceledException) + { + Console.WriteLine($"异步日终持仓结算任务 {taskId} 已被取消"); + } + catch (Exception ex) + { + Console.WriteLine($"异步日终持仓结算任务 {taskId} 执行失败: {ex.Message}"); + } + }); + + return JsonSuccess($"日终持仓结算任务已启动,任务ID: {taskId},预计处理 {estimatedDays} 个交易日,从 {earliestTradeDate:yyyy-MM-dd} 到 {latestTradeDate:yyyy-MM-dd}。任务将在后台异步执行。"); + } + catch (Exception ex) + { + return JsonError($"启动任务失败: {ex.Message}"); + } + } + + + /// + /// 异步执行日终持仓结算 + /// + /// 用户信息 + /// 波动率类型 + /// 是否使用收盘价 + /// 开始日期 + /// 结束日期 + /// 任务ID + /// + private async Task ExecuteEodPositionSettleAsync(OptUserInfo userInfo, string volType, bool useClosePrice, + DateTime startDate, DateTime endDate, string taskId) + { + var processedDates = new List(); + var currentDate = startDate; + + Console.WriteLine($"开始执行异步日终持仓结算任务 {taskId},从 {startDate:yyyy-MM-dd} 到 {endDate:yyyy-MM-dd}"); + + try + { + while (currentDate <= endDate) + { + + Console.WriteLine($"任务 {taskId}: 正在处理日期 {currentDate:yyyy-MM-dd}"); + + + // 创建结算请求对象 + var request = new EodSettlementRequest(userInfo) + { + VolType = volType, + UseClosePrice = useClosePrice, + SettleDate = currentDate, + ClientIds = null, + DelayUnderlyIds = new List() + }; + + // 获取结算配置 + var settlementConfig = PS.Config.GetSettlementConfig(); + + // 获取取消令牌 + CancellationToken cancellationToken = CancellationToken.None; + + // 创建任务管理器 + var taskManager = new SimpleTaskManager(); + + // 在Task.Run中执行CPU密集型操作 + await Task.Run(() => + { + // 创建结算上下文 + var currentContext = new EodSettlementContextV2(request, settlementConfig, cancellationToken); + + // 创建服务实例 + var currentEodPositionService = new EodPositionSettleService(currentContext); + + // 执行当前日期的结算 + currentEodPositionService.Execute(volType, useClosePrice, taskManager); + }); + + processedDates.Add(currentDate); + currentDate = BLL.valuedateBLL.GetNonHoliday(currentDate.AddDays(1)); + + // 每处理一个日期后稍作延迟,避免过度占用系统资源 + await Task.Delay(100); + } + Console.WriteLine($"异步日终持仓结算任务 {taskId} 执行完成,共处理了 {processedDates.Count} 个交易日"); + } + catch (Exception ex) + { + Console.WriteLine($"异步日终持仓结算任务 {taskId} 在处理日期 {currentDate:yyyy-MM-dd} 时发生错误: {ex.Message}"); + throw; + } + } + #endregion + } + /// + /// 简单的任务管理器实现 + /// + public class SimpleTaskManager : IAsyncTaskManager + { + /// + /// 设置任务步骤 + /// + /// 步骤描述 + public void SetTaskStep(string step) + { + // 可以在这里记录日志或更新进度 + Console.WriteLine($"任务步骤: {step}"); + } + + /// + /// 等待任务完成 + /// + /// 要等待的任务数组 + public void WaitTasks(params Task[] tasks) + { + if (tasks is null || tasks.Length < 1) + { + return; + } + + if (tasks.Any(n => n == null)) + { + tasks = tasks.Where(n => n != null).ToArray(); + + if (tasks.Length < 1) + { + return; + } + } + + foreach (var task in tasks) + { + task.ContinueWith(t => + { + //!t.Exception.InnerExceptions.All(n => n is OperationCanceledException) + if (t.Exception != null) + { + LogFactory.GetLogger("日终结算").Error(t.Exception, ""); + } + + }); + } + + Task.WaitAll(tasks); + } } }