diff --git a/AssetManager.Services/PortfolioNavService.cs b/AssetManager.Services/PortfolioNavService.cs index cd1b1bf..dba62cc 100644 --- a/AssetManager.Services/PortfolioNavService.cs +++ b/AssetManager.Services/PortfolioNavService.cs @@ -469,22 +469,37 @@ public class PortfolioNavService : IPortfolioNavService } /// - /// 获取历史价格 + /// 获取历史价格(优先从缓存读取) /// private async Task GetHistoricalPriceAsync(string symbol, string assetType, DateTime date) { try { - // 先尝试获取历史数据 - var historicalData = await _marketDataService.GetHistoricalDataAsync(symbol, assetType, "1d", 365); + // 1. 先从缓存表查特定日期的价格 + var cachedPrice = await _db.Queryable() + .Where(k => k.Symbol == symbol.ToUpper() + && k.AssetType == assetType.ToUpper() + && k.Timeframe == "1D" + && k.Timestamp.Date == date.Date) + .FirstAsync(); + + if (cachedPrice != null && cachedPrice.Close > 0) + { + _logger.LogDebug("缓存命中: {Symbol} {Date}, 价格: {Price}", symbol, date.ToString("yyyy-MM-dd"), cachedPrice.Close); + return cachedPrice.Close; + } + + // 2. 缓存未命中,尝试获取该日期附近的历史数据 + var historicalData = await _marketDataService.GetHistoricalDataAsync(symbol, assetType, "1d", 30); + // 精确匹配日期 var priceOnDate = historicalData.FirstOrDefault(d => d.Timestamp.Date == date.Date); if (priceOnDate != null && priceOnDate.Close > 0) { return priceOnDate.Close; } - // 如果找不到当天数据,找最近的 + // 找最近的交易日价格 var nearestPrice = historicalData .Where(d => d.Timestamp.Date <= date.Date) .OrderByDescending(d => d.Timestamp) @@ -492,17 +507,18 @@ public class PortfolioNavService : IPortfolioNavService if (nearestPrice != null && nearestPrice.Close > 0) { + _logger.LogDebug("使用最近交易日价格: {Symbol} {Date} → {ActualDate}", + symbol, date.ToString("yyyy-MM-dd"), nearestPrice.Timestamp.ToString("yyyy-MM-dd")); return nearestPrice.Close; } - // 最后尝试获取实时价格 + // 3. 最后尝试获取实时价格 var currentPrice = await _marketDataService.GetPriceAsync(symbol, assetType); if (currentPrice != null && currentPrice.Price > 0) { return currentPrice.Price; } - // 无法获取有效价格 _logger.LogWarning("无法获取有效价格: {Symbol}, {Date}", symbol, date); return null; }