fix: 首页组合收益率实时计算
This commit is contained in:
parent
c7712e57bb
commit
71aa7211d6
@ -176,30 +176,60 @@ public class PortfolioService : IPortfolioService
|
||||
|
||||
foreach (var p in portfolios)
|
||||
{
|
||||
// 获取持仓数量
|
||||
var positionCount = _db.Queryable<Position>()
|
||||
// 获取该组合的所有持仓
|
||||
var positions = _db.Queryable<Position>()
|
||||
.Where(pos => pos.PortfolioId == p.Id)
|
||||
.Count();
|
||||
.ToList();
|
||||
|
||||
// 获取今日盈亏(从净值历史)
|
||||
var todayNav = _db.Queryable<PortfolioNavHistory>()
|
||||
.Where(n => n.PortfolioId == p.Id && n.NavDate == DateTime.Today)
|
||||
.First();
|
||||
int positionCount = positions.Count;
|
||||
|
||||
double todayProfit = 0;
|
||||
if (todayNav != null && p.TotalValue > 0)
|
||||
// 实时计算当前市值和总成本
|
||||
decimal totalValue = 0;
|
||||
decimal totalCost = 0;
|
||||
decimal todayProfit = 0;
|
||||
string portfolioCurrency = p.Currency ?? "CNY";
|
||||
|
||||
foreach (var pos in positions)
|
||||
{
|
||||
// 今日盈亏 = 今日市值 - 昨日市值
|
||||
var yesterdayNav = _db.Queryable<PortfolioNavHistory>()
|
||||
.Where(n => n.PortfolioId == p.Id && n.NavDate < DateTime.Today)
|
||||
.OrderByDescending(n => n.NavDate)
|
||||
.First();
|
||||
|
||||
if (yesterdayNav != null)
|
||||
if (pos.StockCode == null || pos.Currency == null)
|
||||
{
|
||||
todayProfit = (double)(todayNav.TotalValue - yesterdayNav.TotalValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 获取实时价格
|
||||
decimal currentPrice = pos.AvgPrice;
|
||||
decimal previousClose = pos.AvgPrice;
|
||||
try
|
||||
{
|
||||
var priceResponse = _marketDataService.GetPriceAsync(pos.StockCode, pos.AssetType ?? "Stock").GetAwaiter().GetResult();
|
||||
if (priceResponse.Price > 0)
|
||||
{
|
||||
currentPrice = priceResponse.Price;
|
||||
previousClose = priceResponse.PreviousClose > 0 ? priceResponse.PreviousClose : currentPrice;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "获取标的 {StockCode} 实时价格失败,使用成本价", pos.StockCode);
|
||||
}
|
||||
|
||||
decimal positionValue = pos.Shares * currentPrice;
|
||||
decimal positionCost = pos.Shares * pos.AvgPrice;
|
||||
decimal positionTodayProfit = previousClose > 0 ? pos.Shares * (currentPrice - previousClose) : 0;
|
||||
|
||||
// 汇率转换到组合本位币
|
||||
var valueInTarget = _exchangeRateService.ConvertAmountAsync(positionValue, pos.Currency, portfolioCurrency).GetAwaiter().GetResult();
|
||||
var costInTarget = _exchangeRateService.ConvertAmountAsync(positionCost, pos.Currency, portfolioCurrency).GetAwaiter().GetResult();
|
||||
var todayProfitInTarget = _exchangeRateService.ConvertAmountAsync(positionTodayProfit, pos.Currency, portfolioCurrency).GetAwaiter().GetResult();
|
||||
|
||||
totalValue += valueInTarget;
|
||||
totalCost += costInTarget;
|
||||
todayProfit += todayProfitInTarget;
|
||||
}
|
||||
|
||||
// 计算收益率
|
||||
double returnRate = totalCost > 0 ? (double)((totalValue - totalCost) / totalCost * 100) : 0;
|
||||
returnRate = Math.Round(returnRate, 2);
|
||||
|
||||
result.Add(new PortfolioListItem
|
||||
{
|
||||
@ -211,11 +241,11 @@ public class PortfolioService : IPortfolioService
|
||||
IconChar = p.Name?.Substring(0, 1).ToUpper() ?? "P",
|
||||
IconBgClass = "bg-blue-100",
|
||||
IconTextClass = "text-blue-700",
|
||||
Value = (double)p.TotalValue,
|
||||
Value = (double)totalValue,
|
||||
Currency = p.Currency,
|
||||
ReturnRate = (double)p.ReturnRate,
|
||||
ReturnType = p.ReturnRate >= 0 ? "positive" : "negative",
|
||||
TodayProfit = todayProfit,
|
||||
ReturnRate = returnRate,
|
||||
ReturnType = returnRate >= 0 ? "positive" : "negative",
|
||||
TodayProfit = (double)todayProfit,
|
||||
TodayProfitCurrency = p.Currency
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user