using AssetManager.Data;
using AssetManager.Infrastructure.StrategyEngine;
using AssetManager.Models;
using AssetManager.Models.DTOs;
using Microsoft.Extensions.Logging;
using SqlSugar;
namespace AssetManager.Services;
///
/// 投资组合门面实现 - 整合多个服务
///
public class PortfolioFacade : IPortfolioFacade
{
private readonly ILogger _logger;
private readonly IPortfolioService _portfolioService;
private readonly IPortfolioNavService _navService;
private readonly IStrategyService _strategyService;
private readonly IStrategyEngine _strategyEngine;
private readonly DatabaseService _databaseService;
private readonly ISqlSugarClient _db;
public PortfolioFacade(
ILogger logger,
IPortfolioService portfolioService,
IPortfolioNavService navService,
IStrategyService strategyService,
IStrategyEngine strategyEngine,
DatabaseService databaseService,
ISqlSugarClient db)
{
_logger = logger;
_portfolioService = portfolioService;
_navService = navService;
_strategyService = strategyService;
_strategyEngine = strategyEngine;
_databaseService = databaseService;
_db = db;
}
public async Task CreatePortfolioAsync(CreatePortfolioRequest request, string userId)
{
_logger.LogInformation("创建投资组合: {Name}", request.Name);
return await _portfolioService.CreatePortfolioAsync(request, userId);
}
public async Task GetPortfolioDetailAsync(string portfolioId, string userId)
{
_logger.LogInformation("获取组合详情: {PortfolioId}", portfolioId);
return await _portfolioService.GetPortfolioDetailAsync(portfolioId, userId);
}
public async Task> GetPortfolioListAsync(string userId)
{
_logger.LogInformation("获取组合列表: {UserId}", userId);
return await _portfolioService.GetPortfolioListAsync(userId);
}
public async Task GetNavHistoryAsync(string portfolioId, NavHistoryRequest request, string userId)
{
_logger.LogInformation("获取净值历史: {PortfolioId}", portfolioId);
// 验证权限
var portfolio = _databaseService.GetPortfolioById(portfolioId, userId);
if (portfolio == null)
{
throw new UnauthorizedAccessException("组合不存在或无权访问");
}
return await _navService.GetNavHistoryAsync(portfolioId, userId, request);
}
public async Task CreateTransactionAsync(string portfolioId, CreateTransactionRequest request, string userId)
{
_logger.LogInformation("创建交易: {PortfolioId}, {Type}", portfolioId, request.Type);
// 验证权限
var portfolio = _databaseService.GetPortfolioById(portfolioId, userId);
if (portfolio == null)
{
throw new UnauthorizedAccessException("组合不存在或无权访问");
}
var transaction = await _portfolioService.CreateTransactionAsync(portfolioId, request, userId);
// 交易完成后,异步触发净值更新
_ = Task.Run(async () =>
{
try
{
await _navService.CalculateAndSaveDailyNavAsync(portfolioId);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "交易后净值更新失败: {PortfolioId}", portfolioId);
}
});
return transaction;
}
public async Task> GetTransactionsAsync(string portfolioId, GetTransactionsRequest request, string userId)
{
_logger.LogInformation("获取交易列表: {PortfolioId}", portfolioId);
return await _portfolioService.GetTransactionsAsync(portfolioId, request, userId);
}
public async Task GetStrategySignalAsync(string portfolioId, string userId)
{
_logger.LogInformation("获取策略信号: {PortfolioId}", portfolioId);
// 获取组合
var portfolio = _databaseService.GetPortfolioById(portfolioId, userId);
if (portfolio == null || string.IsNullOrEmpty(portfolio.StrategyId))
{
return new StrategySignalResponse { Signal = "hold", Reason = "未绑定策略" };
}
// 获取策略(同步调用)
var strategy = _strategyService.GetStrategyById(portfolio.StrategyId, userId);
if (strategy == null)
{
return new StrategySignalResponse { Signal = "hold", Reason = "策略不存在" };
}
// 计算信号
var positions = _databaseService.GetPositionsByPortfolioId(portfolioId);
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 DeletePortfolioAsync(string portfolioId, string userId)
{
_logger.LogInformation("删除组合: {PortfolioId}", portfolioId);
return await _portfolioService.DeletePortfolioAsync(portfolioId, userId);
}
///
/// 创建投资组合(含用户验证和币种校验)
///
public async Task CreatePortfolioWithValidationAsync(CreatePortfolioRequest request, string userId)
{
_logger.LogInformation("创建投资组合(含验证): {Name}", request.Name);
// 获取用户默认币种
var user = _db.Queryable().Where(u => u.Id == userId).First();
if (user == null)
{
throw new Exception("用户不存在");
}
// 校验组合币种
if (string.IsNullOrEmpty(request.Currency))
{
request.Currency = user.DefaultCurrency;
}
if (!CurrencyHelper.IsSupported(request.Currency))
{
throw new ArgumentException($"不支持的组合币种: {request.Currency}");
}
// 校验持仓币种
if (request.Stocks != null)
{
foreach (var stock in request.Stocks)
{
if (!string.IsNullOrEmpty(stock.Currency) && !CurrencyHelper.IsSupported(stock.Currency))
{
throw new ArgumentException($"不支持的持仓币种: {stock.Currency}");
}
}
}
var response = await _portfolioService.CreatePortfolioAsync(request, userId);
// 如果创建了持仓,自动触发净值计算
if (request.Stocks != null && request.Stocks.Any())
{
_logger.LogInformation("新组合包含持仓,触发净值计算: {PortfolioId}", response.Id);
_ = Task.Run(async () =>
{
try
{
await _navService.CalculateAndSaveDailyNavAsync(response.Id);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "新组合净值计算失败: {PortfolioId}", response.Id);
}
});
}
return response;
}
///
/// 回填净值历史
///
public async Task BackfillNavHistoryAsync(string portfolioId, string userId, bool force = false)
{
_logger.LogInformation("回填净值历史: {PortfolioId}, Force={Force}", portfolioId, force);
// 验证权限
var portfolio = _databaseService.GetPortfolioById(portfolioId, userId);
if (portfolio == null)
{
throw new UnauthorizedAccessException("组合不存在或无权访问");
}
return await _navService.BackfillNavHistoryAsync(portfolioId, userId, force);
}
///
/// 获取用户总资产
///
public async Task GetTotalAssetsAsync(string userId)
{
_logger.LogInformation("获取用户总资产: {UserId}", userId);
return await _portfolioService.GetTotalAssetsAsync(userId);
}
}