diff --git a/src/Managing.Api/Controllers/BacktestController.cs b/src/Managing.Api/Controllers/BacktestController.cs index 3e621aff..e11d45d1 100644 --- a/src/Managing.Api/Controllers/BacktestController.cs +++ b/src/Managing.Api/Controllers/BacktestController.cs @@ -104,52 +104,6 @@ public class BacktestController : BaseController return Ok(backtest); } - /// - /// Retrieves only the statistical information for a specific backtest by ID. - /// This endpoint returns only the performance metrics without positions, signals, or candles. - /// Useful for displaying backtest stats when starting a bot from a backtest. - /// - /// The ID of the backtest to retrieve stats for. - /// The backtest statistics without detailed position/signal data. - [HttpGet("{id}/stats")] - public async Task> GetBacktestStats(int id) - { - var user = await GetUser(); - var backtest = await _backtester.GetBacktestByIdForUserAsync(user, id.ToString()); - - if (backtest == null) - { - return NotFound($"Backtest with ID {id} not found or doesn't belong to the current user."); - } - - // Return only the statistical information - var stats = new - { - id = backtest.Id, - name = backtest.Config.Name, - ticker = backtest.Config.Ticker, - timeframe = backtest.Config.Timeframe, - tradingType = backtest.Config.TradingType, - startDate = backtest.StartDate, - endDate = backtest.EndDate, - initialBalance = backtest.InitialBalance, - finalPnl = backtest.FinalPnl, - netPnl = backtest.NetPnl, - growthPercentage = backtest.GrowthPercentage, - hodlPercentage = backtest.HodlPercentage, - winRate = backtest.WinRate, - sharpeRatio = backtest.Statistics?.SharpeRatio ?? 0, - maxDrawdown = backtest.Statistics?.MaxDrawdown ?? 0, - maxDrawdownRecoveryTime = backtest.Statistics?.MaxDrawdownRecoveryTime ?? TimeSpan.Zero, - fees = backtest.Fees, - score = backtest.Score, - scoreMessage = backtest.ScoreMessage, - positionCount = backtest.PositionCount - }; - - return Ok(stats); - } - /// /// Deletes a specific backtest by ID for the authenticated user. /// diff --git a/src/Managing.Api/Controllers/DataController.cs b/src/Managing.Api/Controllers/DataController.cs index 2f6edce9..e78a4fc8 100644 --- a/src/Managing.Api/Controllers/DataController.cs +++ b/src/Managing.Api/Controllers/DataController.cs @@ -42,6 +42,7 @@ public class DataController : ControllerBase private readonly IServiceScopeFactory _serviceScopeFactory; private readonly IBotService _botService; private readonly IConfiguration _configuration; + private readonly IBacktester _backtester; /// /// Initializes a new instance of the class. @@ -57,6 +58,7 @@ public class DataController : ControllerBase /// Service scope factory for creating scoped services. /// Service for bot operations. /// Configuration for accessing environment variables. + /// Service for backtest operations. public DataController( IExchangeService exchangeService, IAccountService accountService, @@ -68,7 +70,8 @@ public class DataController : ControllerBase IGrainFactory grainFactory, IServiceScopeFactory serviceScopeFactory, IBotService botService, - IConfiguration configuration) + IConfiguration configuration, + IBacktester backtester) { _exchangeService = exchangeService; _accountService = accountService; @@ -81,6 +84,7 @@ public class DataController : ControllerBase _serviceScopeFactory = serviceScopeFactory; _botService = botService; _configuration = configuration; + _backtester = backtester; } /// @@ -1048,4 +1052,50 @@ public class DataController : ControllerBase return list; } + + /// + /// Retrieves only the statistical information for a specific backtest by ID. + /// This endpoint returns only the performance metrics without positions, signals, or candles. + /// Useful for displaying backtest stats when starting a bot from a backtest. + /// No authentication required. + /// + /// The ID of the backtest to retrieve stats for. + /// The backtest statistics without detailed position/signal data. + [HttpGet("GetBacktestStats/{id}")] + public async Task> GetBacktestStats(int id) + { + var backtest = await _backtester.GetBacktestByIdAsync(id.ToString()); + + if (backtest == null) + { + return NotFound($"Backtest with ID {id} not found."); + } + + // Return only the statistical information + var stats = new + { + id = backtest.Id, + name = backtest.Config.Name, + ticker = backtest.Config.Ticker, + timeframe = backtest.Config.Timeframe, + tradingType = backtest.Config.TradingType, + startDate = backtest.StartDate, + endDate = backtest.EndDate, + initialBalance = backtest.InitialBalance, + finalPnl = backtest.FinalPnl, + netPnl = backtest.NetPnl, + growthPercentage = backtest.GrowthPercentage, + hodlPercentage = backtest.HodlPercentage, + winRate = backtest.WinRate, + sharpeRatio = backtest.Statistics?.SharpeRatio ?? 0, + maxDrawdown = backtest.Statistics?.MaxDrawdown ?? 0, + maxDrawdownRecoveryTime = backtest.Statistics?.MaxDrawdownRecoveryTime ?? TimeSpan.Zero, + fees = backtest.Fees, + score = backtest.Score, + scoreMessage = backtest.ScoreMessage, + positionCount = backtest.PositionCount + }; + + return Ok(stats); + } } \ No newline at end of file diff --git a/src/Managing.Application.Abstractions/Repositories/IBacktestRepository.cs b/src/Managing.Application.Abstractions/Repositories/IBacktestRepository.cs index abc6386b..bd479b56 100644 --- a/src/Managing.Application.Abstractions/Repositories/IBacktestRepository.cs +++ b/src/Managing.Application.Abstractions/Repositories/IBacktestRepository.cs @@ -38,6 +38,7 @@ public interface IBacktestRepository BacktestsFilter? filter = null); Task GetBacktestByIdForUserAsync(User user, string id); + Task GetBacktestByIdAsync(string id); Task DeleteBacktestByIdForUserAsync(User user, string id); Task DeleteBacktestsByIdsForUserAsync(User user, IEnumerable ids); void DeleteAllBacktestsForUser(User user); diff --git a/src/Managing.Application.Abstractions/Services/IBacktester.cs b/src/Managing.Application.Abstractions/Services/IBacktester.cs index 2809db2a..c3058226 100644 --- a/src/Managing.Application.Abstractions/Services/IBacktester.cs +++ b/src/Managing.Application.Abstractions/Services/IBacktester.cs @@ -64,6 +64,7 @@ namespace Managing.Application.Abstractions.Services (IEnumerable Backtests, int TotalCount) GetBacktestsByRequestIdPaginated(Guid requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); Task<(IEnumerable Backtests, int TotalCount)> GetBacktestsByRequestIdPaginatedAsync(Guid requestId, int page, int pageSize, string sortBy = "score", string sortOrder = "desc"); Task GetBacktestByIdForUserAsync(User user, string id); + Task GetBacktestByIdAsync(string id); Task DeleteBacktestByUserAsync(User user, string id); Task DeleteBacktestsByIdsForUserAsync(User user, IEnumerable ids); bool DeleteBacktestsByUser(User user); diff --git a/src/Managing.Application/Backtests/Backtester.cs b/src/Managing.Application/Backtests/Backtester.cs index 98f0140f..8455fbd3 100644 --- a/src/Managing.Application/Backtests/Backtester.cs +++ b/src/Managing.Application/Backtests/Backtester.cs @@ -218,6 +218,16 @@ namespace Managing.Application.Backtests return backtest; } + public async Task GetBacktestByIdAsync(string id) + { + var backtest = await _backtestRepository.GetBacktestByIdAsync(id); + + if (backtest == null) + return null; + + return backtest; + } + public async Task DeleteBacktestByUserAsync(User user, string id) { try diff --git a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlBacktestRepository.cs b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlBacktestRepository.cs index c3580e05..8dcb94f1 100644 --- a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlBacktestRepository.cs +++ b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlBacktestRepository.cs @@ -298,6 +298,17 @@ public class PostgreSqlBacktestRepository : IBacktestRepository return entity != null ? PostgreSqlMappers.Map(entity) : null; } + public async Task GetBacktestByIdAsync(string id) + { + var entity = await _context.Backtests + .AsNoTracking() + .Include(b => b.User) + .FirstOrDefaultAsync(b => b.Identifier == id) + .ConfigureAwait(false); + + return entity != null ? PostgreSqlMappers.Map(entity) : null; + } + public void DeleteBacktestByIdForUser(User user, string id) { var entity = _context.Backtests