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;
}