Setup bundle for backtest

This commit is contained in:
2025-07-21 00:01:13 +07:00
parent 4c07d7323f
commit 0870edee61
8 changed files with 543 additions and 72 deletions

View File

@@ -0,0 +1,156 @@
using System.Text.Json;
using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services;
using Managing.Application.Workers.Abstractions;
using Managing.Domain.Backtests;
using Microsoft.Extensions.Logging;
using static Managing.Common.Enums;
namespace Managing.Application.Workers;
/// <summary>
/// Worker for processing bundle backtest requests
/// </summary>
public class BundleBacktestWorker : BaseWorker<BundleBacktestWorker>
{
private readonly IBacktestRepository _backtestRepository;
private readonly IBacktester _backtester;
private static readonly WorkerType _workerType = WorkerType.BundleBacktest;
public BundleBacktestWorker(
IBacktestRepository backtestRepository,
IBacktester backtester,
ILogger<BundleBacktestWorker> logger,
IWorkerService workerService) : base(
_workerType,
logger,
TimeSpan.FromMinutes(1),
workerService)
{
_backtestRepository = backtestRepository;
_backtester = backtester;
}
protected override async Task Run(CancellationToken cancellationToken)
{
try
{
// Get pending bundle backtest requests
var pendingRequests = _backtestRepository.GetPendingBundleBacktestRequests();
foreach (var bundleRequest in pendingRequests)
{
if (cancellationToken.IsCancellationRequested)
break;
await ProcessBundleRequest(bundleRequest, cancellationToken);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in BundleBacktestWorker");
throw;
}
}
private async Task ProcessBundleRequest(BundleBacktestRequest bundleRequest, CancellationToken cancellationToken)
{
try
{
_logger.LogInformation("Starting to process bundle backtest request {RequestId}", bundleRequest.RequestId);
// Update status to running
bundleRequest.Status = BundleBacktestRequestStatus.Running;
_backtestRepository.UpdateBundleBacktestRequest(bundleRequest);
// Deserialize the backtest requests as dynamic objects
var backtestRequests = JsonSerializer.Deserialize<List<JsonElement>>(bundleRequest.BacktestRequestsJson);
if (backtestRequests == null)
{
throw new InvalidOperationException("Failed to deserialize backtest requests");
}
// Process each backtest request
for (int i = 0; i < backtestRequests.Count; i++)
{
if (cancellationToken.IsCancellationRequested)
break;
try
{
var requestElement = backtestRequests[i];
// Update current backtest being processed
bundleRequest.CurrentBacktest = $"Backtest {i + 1} of {backtestRequests.Count}";
_backtestRepository.UpdateBundleBacktestRequest(bundleRequest);
// Convert JSON element to domain model and run backtest
await RunSingleBacktest(requestElement, bundleRequest.RequestId, cancellationToken);
// Update progress
bundleRequest.CompletedBacktests++;
_backtestRepository.UpdateBundleBacktestRequest(bundleRequest);
_logger.LogInformation("Completed backtest {Index} for bundle request {RequestId}",
i + 1, bundleRequest.RequestId);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing backtest {Index} for bundle request {RequestId}",
i + 1, bundleRequest.RequestId);
bundleRequest.FailedBacktests++;
_backtestRepository.UpdateBundleBacktestRequest(bundleRequest);
}
}
// Update final status
if (bundleRequest.FailedBacktests == 0)
{
bundleRequest.Status = BundleBacktestRequestStatus.Completed;
}
else if (bundleRequest.CompletedBacktests == 0)
{
bundleRequest.Status = BundleBacktestRequestStatus.Failed;
bundleRequest.ErrorMessage = "All backtests failed";
}
else
{
bundleRequest.Status = BundleBacktestRequestStatus.Completed;
bundleRequest.ErrorMessage = $"{bundleRequest.FailedBacktests} backtests failed";
}
bundleRequest.CompletedAt = DateTime.UtcNow;
bundleRequest.CurrentBacktest = null;
_backtestRepository.UpdateBundleBacktestRequest(bundleRequest);
_logger.LogInformation("Completed processing bundle backtest request {RequestId} with status {Status}",
bundleRequest.RequestId, bundleRequest.Status);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing bundle backtest request {RequestId}", bundleRequest.RequestId);
bundleRequest.Status = BundleBacktestRequestStatus.Failed;
bundleRequest.ErrorMessage = ex.Message;
bundleRequest.CompletedAt = DateTime.UtcNow;
_backtestRepository.UpdateBundleBacktestRequest(bundleRequest);
}
}
private async Task RunSingleBacktest(JsonElement requestElement, string bundleRequestId, CancellationToken cancellationToken)
{
// For now, we'll use a simplified approach that simulates backtest execution
// In a real implementation, you would parse the JSON and convert to domain models
// Simulate backtest processing time
await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken);
_logger.LogInformation("Processed backtest for bundle request {RequestId}", bundleRequestId);
// TODO: Implement actual backtest execution by:
// 1. Parsing the JSON request element
// 2. Converting to TradingBotConfig domain model
// 3. Calling _backtester.RunTradingBotBacktest with proper parameters
// 4. Handling the results and saving to database if needed
}
}