Add bundle backtest

This commit is contained in:
2025-07-21 17:03:27 +07:00
parent 0870edee61
commit 6f49f2659f
20 changed files with 492 additions and 132 deletions

View File

@@ -1,7 +1,6 @@
using System.Text.Json;
using Managing.Api.Models.Requests;
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services;
using Managing.Application.Hubs;
using Managing.Domain.Backtests;
@@ -12,6 +11,7 @@ using Managing.Domain.Strategies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using MoneyManagementRequest = Managing.Domain.Backtests.MoneyManagementRequest;
namespace Managing.Api.Controllers;
@@ -33,7 +33,6 @@ public class BacktestController : BaseController
private readonly IAccountService _accountService;
private readonly IMoneyManagementService _moneyManagementService;
private readonly IGeneticService _geneticService;
private readonly IBacktestRepository _backtestRepository;
/// <summary>
/// Initializes a new instance of the <see cref="BacktestController"/> class.
@@ -52,7 +51,6 @@ public class BacktestController : BaseController
IAccountService accountService,
IMoneyManagementService moneyManagementService,
IGeneticService geneticService,
IBacktestRepository backtestRepository,
IUserService userService) : base(userService)
{
_hubContext = hubContext;
@@ -61,7 +59,6 @@ public class BacktestController : BaseController
_accountService = accountService;
_moneyManagementService = moneyManagementService;
_geneticService = geneticService;
_backtestRepository = backtestRepository;
}
/// <summary>
@@ -153,8 +150,8 @@ public class BacktestController : BaseController
[HttpGet]
[Route("ByRequestId/{requestId}/Paginated")]
public async Task<ActionResult<PaginatedBacktestsResponse>> GetBacktestsByRequestIdPaginated(
string requestId,
int page = 1,
string requestId,
int page = 1,
int pageSize = 50,
string sortBy = "score",
string sortOrder = "desc")
@@ -179,10 +176,11 @@ public class BacktestController : BaseController
return BadRequest("Sort order must be 'asc' or 'desc'");
}
var (backtests, totalCount) = _backtester.GetBacktestsByRequestIdPaginated(requestId, page, pageSize, sortBy, sortOrder);
var (backtests, totalCount) =
_backtester.GetBacktestsByRequestIdPaginated(requestId, page, pageSize, sortBy, sortOrder);
var totalPages = (int)Math.Ceiling(totalCount / (double)pageSize);
var response = new PaginatedBacktestsResponse
{
Backtests = backtests.Select(b => new LightBacktestResponse
@@ -410,10 +408,12 @@ public class BacktestController : BaseController
/// This endpoint creates a request that will be processed by a background worker.
/// </summary>
/// <param name="requests">The list of backtest requests to execute.</param>
/// <param name="name">Display name for the bundle (required).</param>
/// <returns>The bundle backtest request with ID for tracking progress.</returns>
[HttpPost]
[Route("Bundle")]
public async Task<ActionResult<BundleBacktestRequest>> RunBundle([FromBody] List<RunBacktestRequest> requests)
public async Task<ActionResult<BundleBacktestRequest>> RunBundle([FromBody] List<RunBacktestRequest> requests,
[FromQuery] string name)
{
if (requests == null || !requests.Any())
{
@@ -425,10 +425,15 @@ public class BacktestController : BaseController
return BadRequest("Maximum of 10 backtests allowed per bundle request");
}
if (string.IsNullOrWhiteSpace(name))
{
return BadRequest("Bundle name is required");
}
try
{
var user = await GetUser();
// Validate all requests before creating the bundle
foreach (var request in requests)
{
@@ -449,7 +454,8 @@ public class BacktestController : BaseController
if (string.IsNullOrEmpty(request.Config.MoneyManagementName) && request.Config.MoneyManagement == null)
{
return BadRequest("Invalid request: Either money management name or money management object is required");
return BadRequest(
"Invalid request: Either money management name or money management object is required");
}
}
@@ -461,10 +467,11 @@ public class BacktestController : BaseController
TotalBacktests = requests.Count,
CompletedBacktests = 0,
FailedBacktests = 0,
Status = BundleBacktestRequestStatus.Pending
Status = BundleBacktestRequestStatus.Pending,
Name = name
};
_backtestRepository.InsertBundleBacktestRequestForUser(user, bundleRequest);
_backtester.InsertBundleBacktestRequestForUser(user, bundleRequest);
return Ok(bundleRequest);
}
@@ -483,7 +490,7 @@ public class BacktestController : BaseController
public async Task<ActionResult<IEnumerable<BundleBacktestRequest>>> GetBundleBacktestRequests()
{
var user = await GetUser();
var bundleRequests = _backtestRepository.GetBundleBacktestRequestsByUser(user);
var bundleRequests = _backtester.GetBundleBacktestRequestsByUser(user);
return Ok(bundleRequests);
}
@@ -497,7 +504,7 @@ public class BacktestController : BaseController
public async Task<ActionResult<BundleBacktestRequest>> GetBundleBacktestRequest(string id)
{
var user = await GetUser();
var bundleRequest = _backtestRepository.GetBundleBacktestRequestByIdForUser(user, id);
var bundleRequest = _backtester.GetBundleBacktestRequestByIdForUser(user, id);
if (bundleRequest == null)
{
@@ -518,16 +525,17 @@ public class BacktestController : BaseController
public async Task<ActionResult> DeleteBundleBacktestRequest(string id)
{
var user = await GetUser();
// First, delete the bundle request
_backtestRepository.DeleteBundleBacktestRequestByIdForUser(user, id);
_backtester.DeleteBundleBacktestRequestByIdForUser(user, id);
// Then, delete all related backtests
var backtestsDeleted = _backtester.DeleteBacktestsByRequestId(id);
return Ok(new {
BundleRequestDeleted = true,
RelatedBacktestsDeleted = backtestsDeleted
return Ok(new
{
BundleRequestDeleted = true,
RelatedBacktestsDeleted = backtestsDeleted
});
}
@@ -641,21 +649,21 @@ public class BacktestController : BaseController
public async Task<ActionResult> DeleteGeneticRequest(string id)
{
var user = await GetUser();
// First, delete the genetic request
_geneticService.DeleteGeneticRequestByIdForUser(user, id);
// Then, delete all related backtests
var backtestsDeleted = _backtester.DeleteBacktestsByRequestId(id);
return Ok(new {
GeneticRequestDeleted = true,
RelatedBacktestsDeleted = backtestsDeleted
return Ok(new
{
GeneticRequestDeleted = true,
RelatedBacktestsDeleted = backtestsDeleted
});
}
/// <summary>
/// Notifies subscribers about the backtesting results via SignalR.
/// </summary>

View File

@@ -5,6 +5,7 @@ using Managing.Application.Abstractions.Services;
using Managing.Application.Hubs;
using Managing.Application.ManageBot.Commands;
using Managing.Common;
using Managing.Domain.Backtests;
using Managing.Domain.Bots;
using Managing.Domain.MoneyManagements;
using Managing.Domain.Scenarios;

View File

@@ -4,6 +4,7 @@ using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services;
using Managing.Application.Hubs;
using Managing.Application.ManageBot.Commands;
using Managing.Domain.Backtests;
using Managing.Domain.Bots;
using Managing.Domain.Candles;
using Managing.Domain.Scenarios;