fix: 请求收益曲线时自动回填历史数据

- GetNavHistoryAsync现在会自动检查是否有历史数据
- 无历史数据时自动调用BackfillNavHistoryInternalAsync
- 拆分内部回填方法,避免重复验证权限
This commit is contained in:
OpenClaw Agent 2026-03-13 16:21:31 +00:00
parent 05ca501f40
commit 1977dd609d
68 changed files with 19 additions and 4 deletions

0
.dockerignore Normal file → Executable file
View File

0
.env.example Normal file → Executable file
View File

0
.gitignore vendored Normal file → Executable file
View File

0
AssetManager.API/AssetManager.API.csproj Normal file → Executable file
View File

0
AssetManager.API/AssetManager.API.http Normal file → Executable file
View File

0
AssetManager.API/Controllers/AuthController.cs Normal file → Executable file
View File

0
AssetManager.API/Controllers/StrategyController.cs Normal file → Executable file
View File

0
AssetManager.API/Controllers/TickerController.cs Normal file → Executable file
View File

0
AssetManager.API/Controllers/UserController.cs Normal file → Executable file
View File

View File

0
AssetManager.API/Middleware/RateLimitMiddleware.cs Normal file → Executable file
View File

View File

0
AssetManager.API/Properties/launchSettings.json Normal file → Executable file
View File

0
AssetManager.API/appsettings.Development.json Normal file → Executable file
View File

0
AssetManager.Data/AssetManager.Data.csproj Normal file → Executable file
View File

0
AssetManager.Data/DatabaseExtensions.cs Normal file → Executable file
View File

0
AssetManager.Data/DatabaseService.cs Normal file → Executable file
View File

0
AssetManager.Data/MarketKlineCache.cs Normal file → Executable file
View File

0
AssetManager.Data/MarketPriceCache.cs Normal file → Executable file
View File

0
AssetManager.Data/Portfolio.cs Normal file → Executable file
View File

0
AssetManager.Data/README.md Normal file → Executable file
View File

0
AssetManager.Data/SqlSugarConfig.cs Normal file → Executable file
View File

0
AssetManager.Data/Strategy.cs Normal file → Executable file
View File

0
AssetManager.Data/TiingoTicker.cs Normal file → Executable file
View File

0
AssetManager.Data/User.cs Normal file → Executable file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

0
AssetManager.Models/ApiResponse.cs Normal file → Executable file
View File

0
AssetManager.Models/AssetManager.Models.csproj Normal file → Executable file
View File

0
AssetManager.Models/Currency.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/AuthDTO.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/ChandelierExitConfig.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/MaTrendConfig.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/MarketDTO.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/RiskParityConfig.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/StrategyDTO.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/StrategySignal.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/StrategyType.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/TickerDTO.cs Normal file → Executable file
View File

0
AssetManager.Models/DTOs/UserDTO.cs Normal file → Executable file
View File

0
AssetManager.Services/AssetManager.Services.csproj Normal file → Executable file
View File

0
AssetManager.Services/IPortfolioService.cs Normal file → Executable file
View File

0
AssetManager.Services/IStrategyService.cs Normal file → Executable file
View File

0
AssetManager.Services/ITickerService.cs Normal file → Executable file
View File

View File

@ -44,6 +44,17 @@ public class PortfolioNavService : IPortfolioNavService
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>()
.Where(n => n.PortfolioId == portfolioId)
.CountAsync();
if (existingCount == 0)
{
_logger.LogInformation("组合 {PortfolioId} 无净值历史数据,自动开始回填", portfolioId);
await BackfillNavHistoryInternalAsync(portfolioId, portfolio);
}
// 查询净值历史 // 查询净值历史
var navHistory = await _db.Queryable<PortfolioNavHistory>() var navHistory = await _db.Queryable<PortfolioNavHistory>()
.Where(n => n.PortfolioId == portfolioId) .Where(n => n.PortfolioId == portfolioId)
@ -244,6 +255,14 @@ public class PortfolioNavService : IPortfolioNavService
throw new Exception("Portfolio not found or access denied"); throw new Exception("Portfolio not found or access denied");
} }
return await BackfillNavHistoryInternalAsync(portfolioId, portfolio, force);
}
/// <summary>
/// 内部回填方法(已验证权限)
/// </summary>
private async Task<BackfillNavResponse> BackfillNavHistoryInternalAsync(string portfolioId, Portfolio portfolio, bool force = false)
{
// 获取所有交易记录,按时间排序 // 获取所有交易记录,按时间排序
var transactions = await _db.Queryable<Transaction>() var transactions = await _db.Queryable<Transaction>()
.Where(t => t.PortfolioId == portfolioId) .Where(t => t.PortfolioId == portfolioId)
@ -288,10 +307,6 @@ public class PortfolioNavService : IPortfolioNavService
// 遍历每个交易日 // 遍历每个交易日
for (var date = startDate; date <= endDate; date = date.AddDays(1)) for (var date = startDate; date <= endDate; date = date.AddDays(1))
{ {
// 跳过周末(可选,美股周末无交易)
// if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
// continue;
// 检查是否已存在该日期的净值记录(非强制模式) // 检查是否已存在该日期的净值记录(非强制模式)
if (!force) if (!force)
{ {

0
AssetManager.Services/PortfolioService.cs Normal file → Executable file
View File

0
AssetManager.Services/Services/JwtService.cs Normal file → Executable file
View File

0
AssetManager.Services/Services/WechatService.cs Normal file → Executable file
View File

0
AssetManager.Services/StrategyService.cs Normal file → Executable file
View File

0
AssetManager.Services/TickerService.cs Normal file → Executable file
View File

0
AssetManager.sln Normal file → Executable file
View File

0
DEPLOY.md Normal file → Executable file
View File

0
Dockerfile Normal file → Executable file
View File

0
README.md Normal file → Executable file
View File

0
docker-compose.yml Normal file → Executable file
View File