using Marathon.Application.Abstractions;
using Marathon.Application.Storage;
using Marathon.Domain.Backtesting;
using Microsoft.Extensions.Logging;
namespace Marathon.Application.UseCases;
/// One saved strategy preset paired with its backtest result over a shared window.
public sealed record StrategyComparison(Guid StrategyId, string Name, BacktestResult Result);
///
/// Runs every saved strategy preset over the same anomaly window and returns their
/// backtest results side by side, so the user can see which staking configuration wins.
///
///
/// Delegates to once per preset — the anomaly set is
/// re-loaded per run, which is fine for the handful of presets a user keeps. Keeping the
/// composition at the use-case level (rather than re-implementing candidate loading) means
/// the comparison stays bug-for-bug identical to a single backtest run.
///
public sealed class CompareStrategiesUseCase
{
private readonly ISavedStrategyRepository _strategies;
private readonly RunBacktestUseCase _backtest;
private readonly ILogger _logger;
public CompareStrategiesUseCase(
ISavedStrategyRepository strategies,
RunBacktestUseCase backtest,
ILogger logger)
{
_strategies = strategies ?? throw new ArgumentNullException(nameof(strategies));
_backtest = backtest ?? throw new ArgumentNullException(nameof(backtest));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
///
/// Backtests each saved preset over (null = all graded
/// anomalies). Returns one row per preset in saved (name-ascending) order; empty when
/// the user has saved no strategies.
///
public async Task> ExecuteAsync(
DateRange? dateRange, CancellationToken ct = default)
{
var presets = await _strategies.ListAsync(ct).ConfigureAwait(false);
if (presets.Count == 0)
return Array.Empty();
var rows = new List(presets.Count);
foreach (var preset in presets)
{
ct.ThrowIfCancellationRequested();
var result = await _backtest.ExecuteAsync(preset.Strategy, dateRange, ct).ConfigureAwait(false);
rows.Add(new StrategyComparison(preset.Id, preset.Name, result));
}
_logger.LogInformation("CompareStrategiesUseCase: compared {Count} preset(s)", rows.Count);
return rows;
}
}