diff --git a/AssetManager.Services/PortfolioNavService.cs b/AssetManager.Services/PortfolioNavService.cs index e8f6b95..94b0682 100644 --- a/AssetManager.Services/PortfolioNavService.cs +++ b/AssetManager.Services/PortfolioNavService.cs @@ -189,7 +189,9 @@ public class PortfolioNavService : IPortfolioNavService .ToListAsync(); decimal totalCost = 0; - var holdingsCost = new Dictionary(); // 每个标的的累计成本 + // 每个标的的累计成本和数量(用于准确计算卖出比例) + var holdingsCost = new Dictionary(); + var holdingsShares = new Dictionary(); foreach (var tx in transactions) { @@ -202,33 +204,30 @@ public class PortfolioNavService : IPortfolioNavService txAmount, tx.Currency, targetCurrency); totalCost += txAmountInTarget; - // 更新该标的的累计成本 + // 更新该标的的累计成本和数量 if (holdingsCost.ContainsKey(tx.StockCode)) { holdingsCost[tx.StockCode] += txAmountInTarget; + holdingsShares[tx.StockCode] += tx.Amount; } else { holdingsCost[tx.StockCode] = txAmountInTarget; + holdingsShares[tx.StockCode] = tx.Amount; } } else if (tx.Type == "sell") { // 卖出时按比例减少该标的的累计成本 - if (holdingsCost.ContainsKey(tx.StockCode) && tx.Amount > 0) + if (holdingsCost.ContainsKey(tx.StockCode) && holdingsShares[tx.StockCode] > 0) { - // 需要知道当时该标的的总数量来计算比例 - // 从 Position 表获取当前持仓数量(不精确,但作为近似) - var position = positions.FirstOrDefault(p => p.StockCode == tx.StockCode); - if (position != null && position.Shares > 0) - { - // 近似:用当前持仓数量 + 卖出数量 作为原来数量 - decimal originalShares = position.Shares + tx.Amount; - decimal soldRatio = tx.Amount / originalShares; - decimal costToReduce = holdingsCost[tx.StockCode] * soldRatio; - holdingsCost[tx.StockCode] -= costToReduce; - totalCost -= costToReduce; - } + decimal currentShares = holdingsShares[tx.StockCode]; + decimal soldRatio = tx.Amount / currentShares; + decimal costToReduce = holdingsCost[tx.StockCode] * soldRatio; + + holdingsCost[tx.StockCode] -= costToReduce; + holdingsShares[tx.StockCode] -= tx.Amount; + totalCost -= costToReduce; } } } diff --git a/AssetManager.Services/PortfolioService.cs b/AssetManager.Services/PortfolioService.cs index 9920bc7..74c928a 100755 --- a/AssetManager.Services/PortfolioService.cs +++ b/AssetManager.Services/PortfolioService.cs @@ -496,15 +496,17 @@ public class PortfolioService : IPortfolioService decimal positionValue = pos.Shares * CurrentPrice; decimal cost = pos.Shares * pos.AvgPrice; - decimal Profit = positionValue - cost; - double ProfitRate = cost > 0 ? (double)(Profit / cost * 100) : 0; decimal TodayProfit = previousClose > 0 ? pos.Shares * (CurrentPrice - previousClose) : 0; - // 转换为组合本位币 + // 转换为组合本位币(先转换,再计算盈亏率,避免汇率变化影响) decimal positionValueInTarget = await _exchangeRateService.ConvertAmountAsync(positionValue, pos.Currency, targetCurrency); decimal costInTarget = await _exchangeRateService.ConvertAmountAsync(cost, pos.Currency, targetCurrency); decimal todayProfitInTarget = await _exchangeRateService.ConvertAmountAsync(TodayProfit, pos.Currency, targetCurrency); + // 用目标币种计算盈亏率(正确处理汇率变化) + decimal ProfitInTarget = positionValueInTarget - costInTarget; + double ProfitRate = costInTarget > 0 ? (double)(ProfitInTarget / costInTarget * 100) : 0; + totalPortfolioValue += positionValueInTarget; totalCost += costInTarget; totalTodayProfit += todayProfitInTarget;