feat: 用户访问时自动触发当日净值计算
修改 GetNavHistoryAsync: - 检查是否存在今日净值记录 - 如果不存在,自动调用 CalculateAndSaveDailyNavAsync - 捕获异常避免影响历史数据查询 收益: - 用户每次访问收益曲线都能获取最新数据 - 无需手动触发或定时任务
This commit is contained in:
parent
1c3add27ef
commit
c0accdc903
@ -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<PortfolioNavHistory>()
|
||||
.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<PortfolioNavHistory>()
|
||||
@ -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<PortfolioPosition>()
|
||||
.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
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user