fix: 修复 PortfolioService 和 PortfolioNavService 变量命名

- 统一局部变量使用 camelCase(C# 规范)
- 修复 DTO 属性名引用
- NavItem -> NavHistoryItem
- 修复 for 循环变量名
This commit is contained in:
OpenClaw Agent 2026-03-15 13:31:49 +00:00
parent da12f6d163
commit 60f3b487ff
3 changed files with 53 additions and 41 deletions

View File

@ -110,7 +110,19 @@ public class PortfolioFacade : IPortfolioFacade
// 计算信号 // 计算信号
var positions = _databaseService.GetPositionsByPortfolioId(portfolioId); var positions = _databaseService.GetPositionsByPortfolioId(portfolioId);
return await _strategyEngine.GenerateSignalAsync(strategy, positions); var signal = await _strategyEngine.CalculateSignalAsync(strategy, positions);
return new StrategySignalResponse
{
Signal = signal.Signal?.ToLower() ?? "hold",
Reason = signal.Reason,
Actions = signal.PositionSignals?.Select(p => new SignalAction
{
Symbol = p.Symbol,
Action = p.Signal?.ToLower(),
Target = (double?)p.TargetWeight
}).ToList()
};
} }
public async Task<bool> DeletePortfolioAsync(string portfolioId, string userId) public async Task<bool> DeletePortfolioAsync(string portfolioId, string userId)

View File

@ -41,8 +41,8 @@ public class PortfolioNavService : IPortfolioNavService
} }
// 设置默认日期范围最近30天 // 设置默认日期范围最近30天
var EndDate = request.EndDate ?? DateTime.Today; var endDate = request.EndDate ?? DateTime.Today;
var StartDate = request.StartDate ?? endDate.AddDays(-30); var startDate = request.StartDate ?? endDate.AddDays(-30);
// 检查是否有历史数据,没有则自动回填 // 检查是否有历史数据,没有则自动回填
var existingCount = await _db.Queryable<PortfolioNavHistory>() var existingCount = await _db.Queryable<PortfolioNavHistory>()
@ -56,7 +56,7 @@ public class PortfolioNavService : IPortfolioNavService
} }
// 查询净值历史 // 查询净值历史
var NavHistory = await _db.Queryable<PortfolioNavHistory>() var navHistory = await _db.Queryable<PortfolioNavHistory>()
.Where(n => n.PortfolioId == portfolioId) .Where(n => n.PortfolioId == portfolioId)
.Where(n => n.NavDate >= startDate && n.NavDate <= endDate) .Where(n => n.NavDate >= startDate && n.NavDate <= endDate)
.OrderBy(n => n.NavDate) .OrderBy(n => n.NavDate)
@ -69,20 +69,20 @@ public class PortfolioNavService : IPortfolioNavService
{ {
PortfolioId = portfolioId, PortfolioId = portfolioId,
Currency = portfolio.Currency, Currency = portfolio.Currency,
NavHistory = new List<NavItem>(), NavHistory = new List<NavHistoryItem>(),
Statistics = new NavStatistics() Statistics = new NavStatistics()
}; };
} }
// 计算统计指标 // 计算统计指标
var returns = navHistory.Select(n => (double)n.DailyReturn).Where(r => r != 0).ToList(); var returns = navHistory.Select(n => (double)n.DailyReturn).Where(r => r != 0).ToList();
var Statistics = CalculateStatistics(returns, navHistory); var statistics = CalculateStatistics(returns, navHistory);
return new NavHistoryResponse return new NavHistoryResponse
{ {
PortfolioId = portfolioId, PortfolioId = portfolioId,
Currency = portfolio.Currency, Currency = portfolio.Currency,
NavHistory = navHistory.Select(n => new NavItem NavHistory = navHistory.Select(n => new NavHistoryItem
{ {
Date = n.NavDate.ToString("yyyy-MM-dd"), Date = n.NavDate.ToString("yyyy-MM-dd"),
Nav = (double)n.Nav, Nav = (double)n.Nav,
@ -128,7 +128,7 @@ public class PortfolioNavService : IPortfolioNavService
} }
string targetCurrency = portfolio.Currency ?? "CNY"; string targetCurrency = portfolio.Currency ?? "CNY";
decimal TotalValue = 0; decimal totalValue = 0;
// 计算总市值 // 计算总市值
foreach (var pos in positions) foreach (var pos in positions)
@ -166,7 +166,7 @@ public class PortfolioNavService : IPortfolioNavService
.Where(t => t.PortfolioId == portfolioId && t.TransactionTime.Date <= today) .Where(t => t.PortfolioId == portfolioId && t.TransactionTime.Date <= today)
.ToListAsync(); .ToListAsync();
decimal TotalCost = 0; decimal totalCost = 0;
foreach (var tx in transactions) foreach (var tx in transactions)
{ {
if (tx.Type == "buy") if (tx.Type == "buy")
@ -186,13 +186,13 @@ public class PortfolioNavService : IPortfolioNavService
} }
// 计算净值 // 计算净值
decimal Nav = totalCost > 0 ? totalValue / totalCost : 1.0m; decimal nav = totalCost > 0 ? totalValue / totalCost : 1.0m;
decimal DailyReturn = 0; decimal dailyReturn = 0;
decimal CumulativeReturn = totalCost > 0 ? (totalValue - totalCost) / totalCost * 100 : 0; decimal cumulativeReturn = totalCost > 0 ? (totalValue - totalCost) / totalCost * 100 : 0;
if (yesterdayNav != null && yesterdayNav.TotalValue > 0) if (yesterdayNav != null && yesterdayNav.TotalValue > 0)
{ {
DailyReturn = (totalValue - yesterdayNav.TotalValue) / yesterdayNav.TotalValue * 100; dailyReturn = (totalValue - yesterdayNav.TotalValue) / yesterdayNav.TotalValue * 100;
} }
// 保存净值记录 // 保存净值记录
@ -280,8 +280,8 @@ public class PortfolioNavService : IPortfolioNavService
} }
// 确定起始日期(最早交易日期) // 确定起始日期(最早交易日期)
var StartDate = transactions.Min(t => t.TransactionTime).Date; var startDate = transactions.Min(t => t.TransactionTime).Date;
var EndDate = DateTime.Today; var endDate = DateTime.Today;
string targetCurrency = portfolio.Currency ?? "CNY"; string targetCurrency = portfolio.Currency ?? "CNY";
_logger.LogInformation("开始回填净值历史: {PortfolioId}, 日期范围: {StartDate} ~ {EndDate}", _logger.LogInformation("开始回填净值历史: {PortfolioId}, 日期范围: {StartDate} ~ {EndDate}",
@ -302,10 +302,10 @@ public class PortfolioNavService : IPortfolioNavService
decimal cumulativeCost = 0; decimal cumulativeCost = 0;
// 记录创建数量 // 记录创建数量
int RecordsCreated = 0; int recordsCreated = 0;
// 遍历每个交易日 // 遍历每个交易日
for (var Date = startDate; date <= endDate; Date = date.AddDays(1)) for (var date = startDate; date <= endDate; date = date.AddDays(1))
{ {
// 检查是否已存在该日期的净值记录(非强制模式) // 检查是否已存在该日期的净值记录(非强制模式)
if (!force) if (!force)
@ -372,7 +372,7 @@ public class PortfolioNavService : IPortfolioNavService
if (!holdings.Any()) continue; if (!holdings.Any()) continue;
// 计算当日市值 // 计算当日市值
decimal TotalValue = 0; decimal totalValue = 0;
bool hasValidPrice = true; bool hasValidPrice = true;
List<string> failedSymbols = new List<string>(); List<string> failedSymbols = new List<string>();
@ -402,8 +402,8 @@ public class PortfolioNavService : IPortfolioNavService
} }
// 计算净值 // 计算净值
decimal Nav = cumulativeCost > 0 ? totalValue / cumulativeCost : 1.0m; decimal nav = cumulativeCost > 0 ? totalValue / cumulativeCost : 1.0m;
decimal CumulativeReturn = cumulativeCost > 0 ? (totalValue - cumulativeCost) / cumulativeCost * 100 : 0; decimal cumulativeReturn = cumulativeCost > 0 ? (totalValue - cumulativeCost) / cumulativeCost * 100 : 0;
// 获取昨日净值以计算日收益率 // 获取昨日净值以计算日收益率
var yesterdayNav = await _db.Queryable<PortfolioNavHistory>() var yesterdayNav = await _db.Queryable<PortfolioNavHistory>()
@ -411,10 +411,10 @@ public class PortfolioNavService : IPortfolioNavService
.OrderByDescending(n => n.NavDate) .OrderByDescending(n => n.NavDate)
.FirstAsync(); .FirstAsync();
decimal DailyReturn = 0; decimal dailyReturn = 0;
if (yesterdayNav != null && yesterdayNav.TotalValue > 0) if (yesterdayNav != null && yesterdayNav.TotalValue > 0)
{ {
DailyReturn = (totalValue - yesterdayNav.TotalValue) / yesterdayNav.TotalValue * 100; dailyReturn = (totalValue - yesterdayNav.TotalValue) / yesterdayNav.TotalValue * 100;
} }
// 保存净值记录 // 保存净值记录
@ -536,33 +536,33 @@ public class PortfolioNavService : IPortfolioNavService
{ {
if (!history.Any()) return new NavStatistics(); if (!history.Any()) return new NavStatistics();
var MaxReturn = returns.Any() ? returns.Max() : 0; var maxReturn = returns.Any() ? returns.Max() : 0;
var MinReturn = returns.Any() ? returns.Min() : 0; var minReturn = returns.Any() ? returns.Min() : 0;
// 计算最大回撤 // 计算最大回撤
double MaxDrawdown = 0; double maxDrawdown = 0;
double peak = 1.0; double peak = 1.0;
foreach (var item in history.OrderBy(h => h.NavDate)) foreach (var item in history.OrderBy(h => h.NavDate))
{ {
var Nav = (double)item.Nav; var nav = (double)item.Nav;
if (nav > peak) peak = nav; if (nav > peak) peak = nav;
var drawdown = (peak - nav) / peak * 100; var drawdown = (peak - nav) / peak * 100;
if (drawdown > maxDrawdown) MaxDrawdown = drawdown; if (drawdown > maxDrawdown) maxDrawdown = drawdown;
} }
// 计算夏普比率(简化版,假设无风险利率=3%年化) // 计算夏普比率(简化版,假设无风险利率=3%年化)
double SharpeRatio = 0; double sharpeRatio = 0;
double Volatility = 0; double volatility = 0;
if (returns.Any()) if (returns.Any())
{ {
var avgReturn = returns.Average(); var avgReturn = returns.Average();
var stdDev = Math.Sqrt(returns.Sum(r => Math.Pow(r - avgReturn, 2)) / returns.Count); var stdDev = Math.Sqrt(returns.Sum(r => Math.Pow(r - avgReturn, 2)) / returns.Count);
Volatility = stdDev * Math.Sqrt(252); // 年化波动率 volatility = stdDev * Math.Sqrt(252); // 年化波动率
SharpeRatio = stdDev > 0 ? (avgReturn * 252 - 3) / (stdDev * Math.Sqrt(252)) : 0; sharpeRatio = stdDev > 0 ? (avgReturn * 252 - 3) / (stdDev * Math.Sqrt(252)) : 0;
} }
// 总收益率 // 总收益率
var TotalReturn = history.Any() var totalReturn = history.Any()
? (double)(history.Last().CumulativeReturn) ? (double)(history.Last().CumulativeReturn)
: 0; : 0;

View File

@ -159,7 +159,7 @@ public class PortfolioService : IPortfolioService
return new CreatePortfolioResponse return new CreatePortfolioResponse
{ {
Id = portfolio.Id, Id = portfolio.Id,
totalValue = (double)portfolio.TotalValue, TotalValue = (double)portfolio.TotalValue,
ReturnRate = 0, ReturnRate = 0,
Currency = portfolio.Currency, Currency = portfolio.Currency,
CreatedAt = portfolio.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss") CreatedAt = portfolio.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss")
@ -266,11 +266,11 @@ public class PortfolioService : IPortfolioService
return new TotalAssetsResponse return new TotalAssetsResponse
{ {
totalValue = (double)totalValueInTargetCurrency, TotalValue = (double)totalValueInTargetCurrency,
Currency = targetCurrency, Currency = targetCurrency,
TodayProfit = (double)totalTodayProfitInTargetCurrency, TodayProfit = (double)totalTodayProfitInTargetCurrency,
TodayProfitCurrency = targetCurrency, TodayProfitCurrency = targetCurrency,
totalReturnRate = Math.Round(totalReturnRate, 2) TotalReturnRate = Math.Round(totalReturnRate, 2)
}; };
} }
@ -350,7 +350,7 @@ public class PortfolioService : IPortfolioService
Amount = (int)pos.Shares, Amount = (int)pos.Shares,
AveragePrice = (double)pos.AvgPrice, AveragePrice = (double)pos.AvgPrice,
CurrentPrice = (double)currentPrice, CurrentPrice = (double)currentPrice,
totalValue = (double)positionValueInTarget, TotalValue = (double)positionValueInTarget,
Profit = (double)(positionValueInTarget - costInTarget), Profit = (double)(positionValueInTarget - costInTarget),
ProfitRate = profitRate, ProfitRate = profitRate,
ChangeAmount = (double)todayProfitInTarget, ChangeAmount = (double)todayProfitInTarget,
@ -379,7 +379,7 @@ public class PortfolioService : IPortfolioService
{ {
Id = portfolio.StrategyId, Id = portfolio.StrategyId,
Name = "策略名称", Name = "策略名称",
description = "策略描述" Description = "策略描述"
}, },
PortfolioValue = (double)totalPortfolioValue, PortfolioValue = (double)totalPortfolioValue,
TotalReturn = (double)totalReturn, TotalReturn = (double)totalReturn,
@ -427,7 +427,7 @@ public class PortfolioService : IPortfolioService
return new GetTransactionsResponse return new GetTransactionsResponse
{ {
items = transactions.Select(t => new TransactionItem Items = transactions.Select(t => new TransactionItem
{ {
Id = t.Id, Id = t.Id,
PortfolioId = t.PortfolioId, PortfolioId = t.PortfolioId,
@ -441,9 +441,9 @@ public class PortfolioService : IPortfolioService
Status = t.Status, Status = t.Status,
Remark = t.Remark Remark = t.Remark
}).ToList(), }).ToList(),
total = total, Total = total,
page = offset / limit + 1, Page = offset / limit + 1,
pageSize = limit PageSize = limit
}; };
} }