From c0accdc903d91cdffe138c81c689bef79c51c703 Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Tue, 24 Mar 2026 06:22:28 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=94=A8=E6=88=B7=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E6=97=B6=E8=87=AA=E5=8A=A8=E8=A7=A6=E5=8F=91=E5=BD=93=E6=97=A5?= =?UTF-8?q?=E5=87=80=E5=80=BC=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改 GetNavHistoryAsync: - 检查是否存在今日净值记录 - 如果不存在,自动调用 CalculateAndSaveDailyNavAsync - 捕获异常避免影响历史数据查询 收益: - 用户每次访问收益曲线都能获取最新数据 - 无需手动触发或定时任务 --- AssetManager.Services/PortfolioNavService.cs | 60 +++++++------------- 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/AssetManager.Services/PortfolioNavService.cs b/AssetManager.Services/PortfolioNavService.cs index 9baf287..7c71547 100644 --- a/AssetManager.Services/PortfolioNavService.cs +++ b/AssetManager.Services/PortfolioNavService.cs @@ -54,6 +54,27 @@ public class PortfolioNavService : IPortfolioNavService _logger.LogInformation("组合 {PortfolioId} 无净值历史数据,自动开始回填", portfolioId); await BackfillNavHistoryInternalAsync(portfolioId, portfolio); } + else + { + // 有历史数据,检查是否需要计算今日净值 + var today = DateTime.Today; + var todayNavExists = await _db.Queryable() + .Where(n => n.PortfolioId == portfolioId && n.NavDate == today) + .AnyAsync(); + + if (!todayNavExists) + { + _logger.LogInformation("组合 {PortfolioId} 今日净值不存在,自动计算", portfolioId); + try + { + await CalculateAndSaveDailyNavAsync(portfolioId); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "组合 {PortfolioId} 今日净值计算失败,将使用历史数据", portfolioId); + } + } + } // 查询净值历史 var navHistory = await _db.Queryable() @@ -77,45 +98,6 @@ public class PortfolioNavService : IPortfolioNavService // 计算统计指标 var returns = navHistory.Select(n => (double)n.DailyReturn).Where(r => r != 0).ToList(); var statistics = CalculateStatistics(returns, navHistory); - - // 如果净值历史的最后一条不是今天,实时计算当前累计收益率 - var lastNavDate = navHistory.Last().NavDate; - if (lastNavDate < DateTime.Today) - { - // 获取当前持仓数据 - var positions = await _db.Queryable() - .Where(p => p.PortfolioId == portfolioId) - .ToListAsync(); - - if (positions.Any()) - { - // 计算当前总市值和总成本 - decimal totalValue = 0; - decimal totalCost = 0; - - foreach (var pos in positions) - { - var currentValue = pos.Shares * pos.CurrentPrice; - var cost = pos.Shares * pos.AverageCost; - - // 汇率转换 - var currentInTarget = await _exchangeRateService.ConvertAmountAsync(currentValue, pos.Currency, portfolio.Currency); - var costInTarget = await _exchangeRateService.ConvertAmountAsync(cost, pos.Currency, portfolio.Currency); - - totalValue += currentInTarget; - totalCost += costInTarget; - } - - // 计算实时累计收益率 - if (totalCost > 0) - { - var realTimeReturn = (double)((totalValue - totalCost) / totalCost * 100); - statistics.TotalReturn = Math.Round(realTimeReturn, 2); - _logger.LogDebug("实时计算累计收益率: {RealTimeReturn}%, 总市值: {TotalValue}, 总成本: {TotalCost}", - realTimeReturn, totalValue, totalCost); - } - } - } return new NavHistoryResponse {