diff --git a/src/Managing.Application.Abstractions/Services/IBacktester.cs b/src/Managing.Application.Abstractions/Services/IBacktester.cs index d50b2f4..6fb0a47 100644 --- a/src/Managing.Application.Abstractions/Services/IBacktester.cs +++ b/src/Managing.Application.Abstractions/Services/IBacktester.cs @@ -18,6 +18,7 @@ namespace Managing.Application.Abstractions.Services /// Whether to save the backtest results /// Whether to include candles and indicators values in the response /// The request ID to associate with this backtest (optional) + /// Additional metadata to associate with this backtest (optional) /// The backtest results Task RunTradingBotBacktest( TradingBotConfig config, @@ -26,7 +27,8 @@ namespace Managing.Application.Abstractions.Services User user = null, bool save = false, bool withCandles = false, - string requestId = null); + string requestId = null, + object metadata = null); /// /// Runs a trading bot backtest with pre-loaded candles. @@ -37,13 +39,15 @@ namespace Managing.Application.Abstractions.Services /// The user running the backtest (optional) /// Whether to include candles and indicators values in the response /// The request ID to associate with this backtest (optional) + /// Additional metadata to associate with this backtest (optional) /// The backtest results Task RunTradingBotBacktest( TradingBotConfig config, List candles, User user = null, bool withCandles = false, - string requestId = null); + string requestId = null, + object metadata = null); // Additional methods for backtest management bool DeleteBacktest(string id); diff --git a/src/Managing.Application/Backtesting/Backtester.cs b/src/Managing.Application/Backtesting/Backtester.cs index eb6f473..f1de13c 100644 --- a/src/Managing.Application/Backtesting/Backtester.cs +++ b/src/Managing.Application/Backtesting/Backtester.cs @@ -70,6 +70,7 @@ namespace Managing.Application.Backtesting /// Whether to save the backtest results /// Whether to include candles and indicators values in the response /// The request ID to associate with this backtest (optional) + /// Additional metadata to associate with this backtest (optional) /// The backtest results public async Task RunTradingBotBacktest( TradingBotConfig config, @@ -78,11 +79,12 @@ namespace Managing.Application.Backtesting User user = null, bool save = false, bool withCandles = false, - string requestId = null) + string requestId = null, + object metadata = null) { var candles = GetCandles(config.Ticker, config.Timeframe, startDate, endDate); - var result = await RunBacktestWithCandles(config, candles, user, withCandles, requestId); + var result = await RunBacktestWithCandles(config, candles, user, withCandles, requestId, metadata); // Set start and end dates result.StartDate = startDate; @@ -110,9 +112,10 @@ namespace Managing.Application.Backtesting List candles, User user = null, bool withCandles = false, - string requestId = null) + string requestId = null, + object metadata = null) { - return await RunBacktestWithCandles(config, candles, user, withCandles, requestId); + return await RunBacktestWithCandles(config, candles, user, withCandles, requestId, metadata); } /// @@ -123,7 +126,8 @@ namespace Managing.Application.Backtesting List candles, User user = null, bool withCandles = false, - string requestId = null) + string requestId = null, + object metadata = null) { var tradingBot = _botFactory.CreateBacktestTradingBot(config); @@ -139,7 +143,7 @@ namespace Managing.Application.Backtesting tradingBot.User = user; await tradingBot.LoadAccount(); - var result = await GetBacktestingResult(config, tradingBot, candles, user, withCandles, requestId); + var result = await GetBacktestingResult(config, tradingBot, candles, user, withCandles, requestId, metadata); if (user != null) { @@ -182,7 +186,8 @@ namespace Managing.Application.Backtesting List candles, User user = null, bool withCandles = false, - string requestId = null) + string requestId = null, + object metadata = null) { if (candles == null || candles.Count == 0) { @@ -272,7 +277,8 @@ namespace Managing.Application.Backtesting : new Dictionary(), Score = score, Id = Guid.NewGuid().ToString(), - RequestId = requestId + RequestId = requestId, + Metadata = metadata }; // Send notification if backtest meets criteria diff --git a/src/Managing.Application/GeneticService.cs b/src/Managing.Application/GeneticService.cs index 50802b2..d467f01 100644 --- a/src/Managing.Application/GeneticService.cs +++ b/src/Managing.Application/GeneticService.cs @@ -299,7 +299,7 @@ public class GeneticService : IGeneticService _logger.LogInformation("Starting fresh genetic algorithm for request {RequestId}", request.RequestId); } - // Create fitness function + // Create fitness function first var fitness = new TradingBotFitness(_backtester, request); // Create genetic algorithm with better configuration @@ -315,6 +315,9 @@ public class GeneticService : IGeneticService CrossoverProbability = 0.7f // Fixed crossover rate as in frontend }; + // Set the genetic algorithm reference in the fitness function + fitness.SetGeneticAlgorithm(ga); + // Custom termination condition that checks for cancellation var originalTermination = ga.Termination; ga.Termination = new GenerationNumberTermination(request.Generations); @@ -768,6 +771,7 @@ public class TradingBotFitness : IFitness { private readonly IBacktester _backtester; private readonly GeneticRequest _request; + private GeneticAlgorithm _geneticAlgorithm; public TradingBotFitness(IBacktester backtester, GeneticRequest request) { @@ -775,6 +779,11 @@ public class TradingBotFitness : IFitness _request = request; } + public void SetGeneticAlgorithm(GeneticAlgorithm geneticAlgorithm) + { + _geneticAlgorithm = geneticAlgorithm; + } + public double Evaluate(IChromosome chromosome) { try @@ -785,15 +794,22 @@ public class TradingBotFitness : IFitness var config = tradingBotChromosome.GetTradingBotConfig(_request); + // Get current generation number (default to 0 if not available) + var currentGeneration = _geneticAlgorithm?.GenerationsNumber ?? 0; + // Run backtest var backtest = _backtester.RunTradingBotBacktest( config, _request.StartDate, _request.EndDate, _request.User, - true, // Don't save individual backtests + true, false, // Don't include candles - _request.RequestId + _request.RequestId, + new + { + generation = currentGeneration + } ).Result; // Calculate multi-objective fitness based on backtest results diff --git a/src/Managing.Domain/Backtests/Backtest.cs b/src/Managing.Domain/Backtests/Backtest.cs index cd270e8..1430034 100644 --- a/src/Managing.Domain/Backtests/Backtest.cs +++ b/src/Managing.Domain/Backtests/Backtest.cs @@ -1,4 +1,5 @@ -using System.ComponentModel.DataAnnotations; +#nullable enable +using System.ComponentModel.DataAnnotations; using Exilion.TradingAtomics; using Managing.Domain.Bots; using Managing.Domain.Candles; @@ -58,6 +59,7 @@ public class Backtest [Required] public Dictionary IndicatorsValues { get; set; } [Required] public double Score { get; set; } public string RequestId { get; set; } + public object? Metadata { get; set; } /// /// Creates a new TradingBotConfig based on this backtest's configuration for starting a live bot. diff --git a/src/Managing.Infrastructure.Database/MongoDb/Collections/BacktestDto.cs b/src/Managing.Infrastructure.Database/MongoDb/Collections/BacktestDto.cs index 6237a6d..e850e2e 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/Collections/BacktestDto.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/Collections/BacktestDto.cs @@ -23,5 +23,6 @@ namespace Managing.Infrastructure.Databases.MongoDb.Collections public double Score { get; set; } public string Identifier { get; set; } public string RequestId { get; set; } + public string? Metadata { get; set; } } } \ No newline at end of file diff --git a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs index a54395d..162d86a 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs @@ -150,7 +150,8 @@ public static class MongoMappers StartDate = b.StartDate, EndDate = b.EndDate, Score = b.Score, - RequestId = b.RequestId + RequestId = b.RequestId, + Metadata = string.IsNullOrEmpty(b.Metadata) ? null : JsonSerializer.Deserialize(b.Metadata) }; return bTest; @@ -178,7 +179,8 @@ public static class MongoMappers StartDate = result.StartDate, EndDate = result.EndDate, Score = result.Score, - RequestId = result.RequestId + RequestId = result.RequestId, + Metadata = result.Metadata == null ? null : JsonSerializer.Serialize(result.Metadata) }; } diff --git a/src/Managing.WebApp/src/generated/ManagingApi.ts b/src/Managing.WebApp/src/generated/ManagingApi.ts index 060dedc..0161a53 100644 --- a/src/Managing.WebApp/src/generated/ManagingApi.ts +++ b/src/Managing.WebApp/src/generated/ManagingApi.ts @@ -3290,6 +3290,7 @@ export interface Backtest { indicatorsValues: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; }; score: number; requestId?: string | null; + metadata?: any | null; } export interface TradingBotConfig { diff --git a/src/Managing.WebApp/src/generated/ManagingApiTypes.ts b/src/Managing.WebApp/src/generated/ManagingApiTypes.ts index 75bfb08..6d4b31e 100644 --- a/src/Managing.WebApp/src/generated/ManagingApiTypes.ts +++ b/src/Managing.WebApp/src/generated/ManagingApiTypes.ts @@ -237,6 +237,7 @@ export interface Backtest { indicatorsValues: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; }; score: number; requestId?: string | null; + metadata?: any | null; } export interface TradingBotConfig {