From cebbeff887f60e6dd8f246b8a47b0d0f9e56a338 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Fri, 11 Jul 2025 23:38:22 +0700 Subject: [PATCH] Add progression and new method of selection/mutation/crossover --- .../Controllers/BacktestController.cs | 2 + .../Models/Requests/RunGeneticRequest.cs | 10 + .../Services/IGeneticService.cs | 4 + .../Services/IMessengerService.cs | 1 + src/Managing.Application/GeneticService.cs | 96 +++++--- .../Shared/MessengerService.cs | 51 +++++ src/Managing.Common/Enums.cs | 39 +++- .../Backtests/GeneticRequest.cs | 12 + .../MongoDb/Collections/GeneticRequestDto.cs | 2 + .../MongoDb/MongoMappers.cs | 14 +- .../src/generated/ManagingApi.ts | 35 ++- .../src/generated/ManagingApiTypes.ts | 35 ++- .../backtestPage/backtestGeneticBundle.tsx | 212 +++++++++++++++--- 13 files changed, 444 insertions(+), 69 deletions(-) diff --git a/src/Managing.Api/Controllers/BacktestController.cs b/src/Managing.Api/Controllers/BacktestController.cs index 68320c9..8475deb 100644 --- a/src/Managing.Api/Controllers/BacktestController.cs +++ b/src/Managing.Api/Controllers/BacktestController.cs @@ -314,6 +314,8 @@ public class BacktestController : BaseController request.Generations, request.MutationRate, request.SelectionMethod, + request.CrossoverMethod, + request.MutationMethod, request.ElitismPercentage, request.MaxTakeProfit, request.EligibleIndicators); diff --git a/src/Managing.Api/Models/Requests/RunGeneticRequest.cs b/src/Managing.Api/Models/Requests/RunGeneticRequest.cs index 84b2cd9..9808158 100644 --- a/src/Managing.Api/Models/Requests/RunGeneticRequest.cs +++ b/src/Managing.Api/Models/Requests/RunGeneticRequest.cs @@ -52,6 +52,16 @@ public class RunGeneticRequest /// public GeneticSelectionMethod SelectionMethod { get; set; } + /// + /// The crossover method to use + /// + public GeneticCrossoverMethod CrossoverMethod { get; set; } + + /// + /// The mutation method to use + /// + public GeneticMutationMethod MutationMethod { get; set; } + /// /// The percentage of elite individuals to preserve (1-50) /// diff --git a/src/Managing.Application.Abstractions/Services/IGeneticService.cs b/src/Managing.Application.Abstractions/Services/IGeneticService.cs index 754e943..6b6950d 100644 --- a/src/Managing.Application.Abstractions/Services/IGeneticService.cs +++ b/src/Managing.Application.Abstractions/Services/IGeneticService.cs @@ -22,6 +22,8 @@ public interface IGeneticService /// The number of generations to evolve /// The mutation rate (0.0 - 1.0) /// The selection method to use + /// The crossover method to use + /// The mutation method to use /// The percentage of elite individuals to preserve /// The maximum take profit percentage /// The list of eligible indicators @@ -37,6 +39,8 @@ public interface IGeneticService int generations, double mutationRate, GeneticSelectionMethod selectionMethod, + GeneticCrossoverMethod crossoverMethod, + GeneticMutationMethod mutationMethod, int elitismPercentage, double maxTakeProfit, List eligibleIndicators); diff --git a/src/Managing.Application.Abstractions/Services/IMessengerService.cs b/src/Managing.Application.Abstractions/Services/IMessengerService.cs index 98dc5d6..40040c6 100644 --- a/src/Managing.Application.Abstractions/Services/IMessengerService.cs +++ b/src/Managing.Application.Abstractions/Services/IMessengerService.cs @@ -24,4 +24,5 @@ public interface IMessengerService Task SendNewTopFundingRate(FundingRate newRate); Task SendFundingRateUpdate(FundingRate oldRate, FundingRate newRate); Task SendBacktestNotification(Backtest backtest); + Task SendGeneticAlgorithmNotification(GeneticRequest request, double bestFitness, object? bestChromosome); } \ No newline at end of file diff --git a/src/Managing.Application/GeneticService.cs b/src/Managing.Application/GeneticService.cs index a8533af..dad691c 100644 --- a/src/Managing.Application/GeneticService.cs +++ b/src/Managing.Application/GeneticService.cs @@ -21,6 +21,7 @@ public class GeneticService : IGeneticService private readonly IGeneticRepository _geneticRepository; private readonly IBacktester _backtester; private readonly ILogger _logger; + private readonly IMessengerService _messengerService; // Predefined parameter ranges for each indicator (matching backtestGenetic.tsx) public static readonly Dictionary ParameterRanges = new() @@ -186,11 +187,13 @@ public class GeneticService : IGeneticService public GeneticService( IGeneticRepository geneticRepository, IBacktester backtester, - ILogger logger) + ILogger logger, + IMessengerService messengerService) { _geneticRepository = geneticRepository; _backtester = backtester; _logger = logger; + _messengerService = messengerService; } public GeneticRequest CreateGeneticRequest( @@ -204,6 +207,8 @@ public class GeneticService : IGeneticService int generations, double mutationRate, GeneticSelectionMethod selectionMethod, + GeneticCrossoverMethod crossoverMethod, + GeneticMutationMethod mutationMethod, int elitismPercentage, double maxTakeProfit, List eligibleIndicators) @@ -220,6 +225,8 @@ public class GeneticService : IGeneticService Generations = generations, MutationRate = mutationRate, SelectionMethod = selectionMethod, + CrossoverMethod = crossoverMethod, + MutationMethod = mutationMethod, ElitismPercentage = elitismPercentage, MaxTakeProfit = maxTakeProfit, EligibleIndicators = eligibleIndicators, @@ -307,8 +314,8 @@ public class GeneticService : IGeneticService population, fitness, GetSelection(request.SelectionMethod), - new UniformCrossover(), - GetMutation(request.MutationRate)) + GetCrossover(request.CrossoverMethod), + GetMutation(request.MutationMethod)) { Termination = new GenerationNumberTermination(request.Generations), MutationProbability = (float)request.MutationRate, @@ -330,28 +337,25 @@ public class GeneticService : IGeneticService { generationCount = ga.GenerationsNumber; - // Update progress every 5 generations - if (generationCount % 5 == 0) + // Update progress every generation + var bestFitness = ga.BestChromosome?.Fitness ?? 0; + request.CurrentGeneration = generationCount; + request.BestFitnessSoFar = bestFitness; + + if (ga.BestChromosome is TradingBotChromosome bestChromosome) { - var bestFitness = ga.BestChromosome?.Fitness ?? 0; - request.CurrentGeneration = generationCount; - request.BestFitnessSoFar = bestFitness; - - if (ga.BestChromosome is TradingBotChromosome bestChromosome) + var genes = bestChromosome.GetGenes(); + var geneValues = genes.Select(g => { - var genes = bestChromosome.GetGenes(); - var geneValues = genes.Select(g => - { - if (g.Value is double doubleValue) return doubleValue; - if (g.Value is int intValue) return (double)intValue; - return Convert.ToDouble(g.Value.ToString()); - }).ToArray(); - request.BestChromosome = JsonSerializer.Serialize(geneValues); - } - - UpdateGeneticRequest(request); + if (g.Value is double doubleValue) return doubleValue; + if (g.Value is int intValue) return (double)intValue; + return Convert.ToDouble(g.Value.ToString()); + }).ToArray(); + request.BestChromosome = JsonSerializer.Serialize(geneValues); } + UpdateGeneticRequest(request); + // Check for cancellation if (cancellationToken.IsCancellationRequested) { @@ -403,6 +407,16 @@ public class GeneticService : IGeneticService UpdateGeneticRequest(request); + // Send notification about the completed genetic algorithm + try + { + await _messengerService.SendGeneticAlgorithmNotification(request, bestFitness, bestChromosome); + } + catch (Exception notificationEx) + { + _logger.LogWarning(notificationEx, "Failed to send genetic algorithm notification for request {RequestId}", request.RequestId); + } + return new GeneticAlgorithmResult { BestFitness = bestFitness, @@ -429,16 +443,48 @@ public class GeneticService : IGeneticService { return selectionMethod switch { - GeneticSelectionMethod.Tournament => new TournamentSelection(), + GeneticSelectionMethod.Elite => new EliteSelection(), GeneticSelectionMethod.Roulette => new RouletteWheelSelection(), - GeneticSelectionMethod.FitnessWeighted => new RankSelection(), // Use rank selection as approximation + GeneticSelectionMethod.StochasticUniversalSampling => new StochasticUniversalSamplingSelection(), + GeneticSelectionMethod.Tournament => new TournamentSelection(), + GeneticSelectionMethod.Truncation => new TruncationSelection(), _ => new TournamentSelection() }; } - private IMutation GetMutation(double mutationRate) + private ICrossover GetCrossover(GeneticCrossoverMethod crossoverMethod) { - return new UniformMutation(true); + return crossoverMethod switch + { + GeneticCrossoverMethod.AlternatingPosition => new AlternatingPositionCrossover(), + GeneticCrossoverMethod.CutAndSplice => new CutAndSpliceCrossover(), + GeneticCrossoverMethod.Cycle => new CycleCrossover(), + GeneticCrossoverMethod.OnePoint => new OnePointCrossover(), + GeneticCrossoverMethod.OrderBased => new OrderBasedCrossover(), + GeneticCrossoverMethod.Ordered => new OrderedCrossover(), + GeneticCrossoverMethod.PartiallyMapped => new PartiallyMappedCrossover(), + GeneticCrossoverMethod.PositionBased => new PositionBasedCrossover(), + GeneticCrossoverMethod.ThreeParent => new ThreeParentCrossover(), + GeneticCrossoverMethod.TwoPoint => new TwoPointCrossover(), + GeneticCrossoverMethod.Uniform => new UniformCrossover(), + GeneticCrossoverMethod.VotingRecombination => new VotingRecombinationCrossover(), + _ => new UniformCrossover() + }; + } + + private IMutation GetMutation(GeneticMutationMethod mutationMethod) + { + return mutationMethod switch + { + GeneticMutationMethod.Displacement => new DisplacementMutation(), + GeneticMutationMethod.FlipBit => new FlipBitMutation(), + GeneticMutationMethod.Insertion => new InsertionMutation(), + GeneticMutationMethod.PartialShuffle => new PartialShuffleMutation(), + GeneticMutationMethod.ReverseSequence => new ReverseSequenceMutation(), + GeneticMutationMethod.Twors => new TworsMutation(), + GeneticMutationMethod.Uniform => new UniformMutation(true), + _ => new UniformMutation(true) + }; } } diff --git a/src/Managing.Application/Shared/MessengerService.cs b/src/Managing.Application/Shared/MessengerService.cs index 6e2c60b..09a53b1 100644 --- a/src/Managing.Application/Shared/MessengerService.cs +++ b/src/Managing.Application/Shared/MessengerService.cs @@ -176,6 +176,19 @@ public class MessengerService : IMessengerService } } + public async Task SendGeneticAlgorithmNotification(GeneticRequest request, double bestFitness, object? bestChromosome) + { + try + { + var message = BuildGeneticAlgorithmMessage(request, bestFitness, bestChromosome); + await _webhookService.SendMessage(message, "2775292276"); + } + catch (Exception e) + { + Console.WriteLine($"Failed to send genetic algorithm notification: {e.Message}"); + } + } + private string BuildBacktestConfigMessage(Backtest backtest) { var config = backtest.Config; @@ -263,4 +276,42 @@ public class MessengerService : IMessengerService return message; } + + private string BuildGeneticAlgorithmMessage(GeneticRequest request, double bestFitness, object? bestChromosome) + { + var duration = request.CompletedAt.HasValue + ? request.CompletedAt.Value - request.CreatedAt + : TimeSpan.Zero; + + var indicators = request.EligibleIndicators.Any() + ? string.Join(", ", request.EligibleIndicators.Select(i => i.ToString())) + : "N/A"; + + if (request.EligibleIndicators.Count > 5) + { + indicators += $" (+{request.EligibleIndicators.Count - 5} more)"; + } + + var message = $"🧬 Genetic Algorithm Completed! 🧬\n\n" + + $"šŸ”¹ Symbol: {request.Ticker}\n" + + $"ā±ļø Timeframe: {request.Timeframe}\n" + + $"šŸ‘„ Population: {request.PopulationSize}\n" + + $"šŸ”„ Generations: {request.Generations}\n" + + $"šŸŽÆ Selection: {request.SelectionMethod}\n" + + $"šŸ”€ Crossover: {request.CrossoverMethod}\n" + + $"🧬 Mutation: {request.MutationMethod}\n" + + $"🧩 Indicators: {indicators}\n" + + $"šŸ“… Period: {request.StartDate:yyyy-MM-dd} to {request.EndDate:yyyy-MM-dd}\n" + + $"šŸ“ˆ Results:\n" + + $"⭐ Best Fitness: {bestFitness:F4}\n" + + $"ā±ļø Duration: {duration.TotalMinutes:F1} minutes\n" + + $"šŸ†” Request ID: {request.RequestId[..8]}..."; + + if (request.BestFitnessSoFar.HasValue && request.BestFitnessSoFar.Value > 0) + { + message += $"\nšŸ† Best Fitness So Far: {request.BestFitnessSoFar.Value:F4}"; + } + + return message; + } } \ No newline at end of file diff --git a/src/Managing.Common/Enums.cs b/src/Managing.Common/Enums.cs index 075a64f..0cfc47f 100644 --- a/src/Managing.Common/Enums.cs +++ b/src/Managing.Common/Enums.cs @@ -422,8 +422,43 @@ public static class Enums /// public enum GeneticSelectionMethod { - Tournament, + Elite, Roulette, - FitnessWeighted + StochasticUniversalSampling, + Tournament, + Truncation + } + + /// + /// Crossover methods for genetic algorithm optimization + /// + public enum GeneticCrossoverMethod + { + AlternatingPosition, + CutAndSplice, + Cycle, + OnePoint, + OrderBased, + Ordered, + PartiallyMapped, + PositionBased, + ThreeParent, + TwoPoint, + Uniform, + VotingRecombination + } + + /// + /// Mutation methods for genetic algorithm optimization + /// + public enum GeneticMutationMethod + { + Displacement, + FlipBit, + Insertion, + PartialShuffle, + ReverseSequence, + Twors, + Uniform } } \ No newline at end of file diff --git a/src/Managing.Domain/Backtests/GeneticRequest.cs b/src/Managing.Domain/Backtests/GeneticRequest.cs index 751c501..1d4bdcb 100644 --- a/src/Managing.Domain/Backtests/GeneticRequest.cs +++ b/src/Managing.Domain/Backtests/GeneticRequest.cs @@ -112,6 +112,18 @@ public class GeneticRequest [Required] public GeneticSelectionMethod SelectionMethod { get; set; } = GeneticSelectionMethod.Tournament; + /// + /// The crossover method to use + /// + [Required] + public GeneticCrossoverMethod CrossoverMethod { get; set; } = GeneticCrossoverMethod.Uniform; + + /// + /// The mutation method to use + /// + [Required] + public GeneticMutationMethod MutationMethod { get; set; } = GeneticMutationMethod.Uniform; + /// /// The percentage of elite individuals to preserve (1-50) /// diff --git a/src/Managing.Infrastructure.Database/MongoDb/Collections/GeneticRequestDto.cs b/src/Managing.Infrastructure.Database/MongoDb/Collections/GeneticRequestDto.cs index c14b085..c9f9921 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/Collections/GeneticRequestDto.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/Collections/GeneticRequestDto.cs @@ -20,6 +20,8 @@ namespace Managing.Infrastructure.Databases.MongoDb.Collections public int Generations { get; set; } public double MutationRate { get; set; } public GeneticSelectionMethod SelectionMethod { get; set; } + public GeneticCrossoverMethod CrossoverMethod { get; set; } + public GeneticMutationMethod MutationMethod { get; set; } public int ElitismPercentage { get; set; } public double MaxTakeProfit { get; set; } public List EligibleIndicators { get; set; } = new(); diff --git a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs index 162d86a..bf83d92 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs @@ -209,13 +209,18 @@ public static class MongoMappers Generations = dto.Generations, MutationRate = dto.MutationRate, SelectionMethod = dto.SelectionMethod, + CrossoverMethod = dto.CrossoverMethod, + MutationMethod = dto.MutationMethod, ElitismPercentage = dto.ElitismPercentage, MaxTakeProfit = dto.MaxTakeProfit, EligibleIndicators = dto.EligibleIndicators, BestFitness = dto.BestFitness, BestIndividual = dto.BestIndividual, ErrorMessage = dto.ErrorMessage, - ProgressInfo = dto.ProgressInfo + ProgressInfo = dto.ProgressInfo, + BestChromosome = dto.BestChromosome, + BestFitnessSoFar = dto.BestFitnessSoFar, + CurrentGeneration = dto.CurrentGeneration }; } @@ -239,13 +244,18 @@ public static class MongoMappers Generations = geneticRequest.Generations, MutationRate = geneticRequest.MutationRate, SelectionMethod = geneticRequest.SelectionMethod, + CrossoverMethod = geneticRequest.CrossoverMethod, + MutationMethod = geneticRequest.MutationMethod, ElitismPercentage = geneticRequest.ElitismPercentage, MaxTakeProfit = geneticRequest.MaxTakeProfit, EligibleIndicators = geneticRequest.EligibleIndicators, BestFitness = geneticRequest.BestFitness, BestIndividual = geneticRequest.BestIndividual, ErrorMessage = geneticRequest.ErrorMessage, - ProgressInfo = geneticRequest.ProgressInfo + ProgressInfo = geneticRequest.ProgressInfo, + BestChromosome = geneticRequest.BestChromosome, + BestFitnessSoFar = geneticRequest.BestFitnessSoFar, + CurrentGeneration = geneticRequest.CurrentGeneration }; } diff --git a/src/Managing.WebApp/src/generated/ManagingApi.ts b/src/Managing.WebApp/src/generated/ManagingApi.ts index 758122f..620c8b0 100644 --- a/src/Managing.WebApp/src/generated/ManagingApi.ts +++ b/src/Managing.WebApp/src/generated/ManagingApi.ts @@ -3771,6 +3771,8 @@ export interface GeneticRequest { generations: number; mutationRate: number; selectionMethod: GeneticSelectionMethod; + crossoverMethod: GeneticCrossoverMethod; + mutationMethod: GeneticMutationMethod; elitismPercentage: number; maxTakeProfit: number; eligibleIndicators: IndicatorType[]; @@ -3793,9 +3795,36 @@ export enum GeneticRequestStatus { } export enum GeneticSelectionMethod { - Tournament = "Tournament", + Elite = "Elite", Roulette = "Roulette", - FitnessWeighted = "FitnessWeighted", + StochasticUniversalSampling = "StochasticUniversalSampling", + Tournament = "Tournament", + Truncation = "Truncation", +} + +export enum GeneticCrossoverMethod { + AlternatingPosition = "AlternatingPosition", + CutAndSplice = "CutAndSplice", + Cycle = "Cycle", + OnePoint = "OnePoint", + OrderBased = "OrderBased", + Ordered = "Ordered", + PartiallyMapped = "PartiallyMapped", + PositionBased = "PositionBased", + ThreeParent = "ThreeParent", + TwoPoint = "TwoPoint", + Uniform = "Uniform", + VotingRecombination = "VotingRecombination", +} + +export enum GeneticMutationMethod { + Displacement = "Displacement", + FlipBit = "FlipBit", + Insertion = "Insertion", + PartialShuffle = "PartialShuffle", + ReverseSequence = "ReverseSequence", + Twors = "Twors", + Uniform = "Uniform", } export interface RunGeneticRequest { @@ -3808,6 +3837,8 @@ export interface RunGeneticRequest { generations?: number; mutationRate?: number; selectionMethod?: GeneticSelectionMethod; + crossoverMethod?: GeneticCrossoverMethod; + mutationMethod?: GeneticMutationMethod; elitismPercentage?: number; maxTakeProfit?: number; eligibleIndicators?: IndicatorType[] | null; diff --git a/src/Managing.WebApp/src/generated/ManagingApiTypes.ts b/src/Managing.WebApp/src/generated/ManagingApiTypes.ts index 4947818..ca7f14c 100644 --- a/src/Managing.WebApp/src/generated/ManagingApiTypes.ts +++ b/src/Managing.WebApp/src/generated/ManagingApiTypes.ts @@ -674,6 +674,8 @@ export interface GeneticRequest { generations: number; mutationRate: number; selectionMethod: GeneticSelectionMethod; + crossoverMethod: GeneticCrossoverMethod; + mutationMethod: GeneticMutationMethod; elitismPercentage: number; maxTakeProfit: number; eligibleIndicators: IndicatorType[]; @@ -696,9 +698,36 @@ export enum GeneticRequestStatus { } export enum GeneticSelectionMethod { - Tournament = "Tournament", + Elite = "Elite", Roulette = "Roulette", - FitnessWeighted = "FitnessWeighted", + StochasticUniversalSampling = "StochasticUniversalSampling", + Tournament = "Tournament", + Truncation = "Truncation", +} + +export enum GeneticCrossoverMethod { + AlternatingPosition = "AlternatingPosition", + CutAndSplice = "CutAndSplice", + Cycle = "Cycle", + OnePoint = "OnePoint", + OrderBased = "OrderBased", + Ordered = "Ordered", + PartiallyMapped = "PartiallyMapped", + PositionBased = "PositionBased", + ThreeParent = "ThreeParent", + TwoPoint = "TwoPoint", + Uniform = "Uniform", + VotingRecombination = "VotingRecombination", +} + +export enum GeneticMutationMethod { + Displacement = "Displacement", + FlipBit = "FlipBit", + Insertion = "Insertion", + PartialShuffle = "PartialShuffle", + ReverseSequence = "ReverseSequence", + Twors = "Twors", + Uniform = "Uniform", } export interface RunGeneticRequest { @@ -711,6 +740,8 @@ export interface RunGeneticRequest { generations?: number; mutationRate?: number; selectionMethod?: GeneticSelectionMethod; + crossoverMethod?: GeneticCrossoverMethod; + mutationMethod?: GeneticMutationMethod; elitismPercentage?: number; maxTakeProfit?: number; eligibleIndicators?: IndicatorType[] | null; diff --git a/src/Managing.WebApp/src/pages/backtestPage/backtestGeneticBundle.tsx b/src/Managing.WebApp/src/pages/backtestPage/backtestGeneticBundle.tsx index 5181d4a..7e42502 100644 --- a/src/Managing.WebApp/src/pages/backtestPage/backtestGeneticBundle.tsx +++ b/src/Managing.WebApp/src/pages/backtestPage/backtestGeneticBundle.tsx @@ -6,6 +6,8 @@ import useApiUrlStore from '../../app/store/apiStore' import { type Backtest, BacktestClient, + GeneticCrossoverMethod, + GeneticMutationMethod, type GeneticRequest, GeneticSelectionMethod, IndicatorType, @@ -52,6 +54,8 @@ interface GeneticBundleFormData { generations: number mutationRate: number selectionMethod: GeneticSelectionMethod + crossoverMethod: GeneticCrossoverMethod + mutationMethod: GeneticMutationMethod elitismPercentage: number maxTakeProfit: number eligibleIndicators: IndicatorType[] @@ -70,6 +74,7 @@ const BacktestGeneticBundle: React.FC = () => { const [isViewModalOpen, setIsViewModalOpen] = useState(false) const [backtests, setBacktests] = useState([]) const [isLoadingBacktests, setIsLoadingBacktests] = useState(false) + const [isFormCollapsed, setIsFormCollapsed] = useState(false) // Form setup const {register, handleSubmit, watch, setValue, formState: {errors}} = useForm({ @@ -83,6 +88,8 @@ const BacktestGeneticBundle: React.FC = () => { generations: 5, mutationRate: 0.3, selectionMethod: GeneticSelectionMethod.Tournament, + crossoverMethod: GeneticCrossoverMethod.Uniform, + mutationMethod: GeneticMutationMethod.Uniform, elitismPercentage: 10, maxTakeProfit: 2.0, eligibleIndicators: ALL_INDICATORS, @@ -139,6 +146,8 @@ const BacktestGeneticBundle: React.FC = () => { generations: data.generations, mutationRate: data.mutationRate, selectionMethod: data.selectionMethod, + crossoverMethod: data.crossoverMethod, + mutationMethod: data.mutationMethod, elitismPercentage: data.elitismPercentage, maxTakeProfit: data.maxTakeProfit, eligibleIndicators: selectedIndicators, @@ -161,6 +170,8 @@ const BacktestGeneticBundle: React.FC = () => { setValue('generations', 5) setValue('mutationRate', 0.3) setValue('selectionMethod', GeneticSelectionMethod.Tournament) + setValue('crossoverMethod', GeneticCrossoverMethod.Uniform) + setValue('mutationMethod', GeneticMutationMethod.Uniform) setValue('elitismPercentage', 10) setValue('maxTakeProfit', 2.0) setSelectedIndicators(ALL_INDICATORS) @@ -228,13 +239,6 @@ const BacktestGeneticBundle: React.FC = () => { // Table columns for genetic requests const geneticRequestsColumns = useMemo(() => [ - { - Header: 'ID', - accessor: 'requestId', - Cell: ({value}: { value: string }) => ( - {value.slice(0, 8)}... - ), - }, { Header: 'Ticker', accessor: 'ticker', @@ -243,6 +247,49 @@ const BacktestGeneticBundle: React.FC = () => { Header: 'Timeframe', accessor: 'timeframe', }, + { + Header: 'Progress', + accessor: 'currentGeneration', + Cell: ({value, row}: { value: number, row: any }) => { + const generations = row.original.generations + const currentGen = value || 0 + const percentage = generations > 0 ? Math.round((currentGen / generations) * 100) : 0 + + return ( +
+
+ {currentGen} / {generations} +
+ +
+ ) + }, + }, + { + Header: 'Selection', + accessor: 'selectionMethod', + Cell: ({value}: { value: string }) => ( + {value} + ), + }, + { + Header: 'Crossover', + accessor: 'crossoverMethod', + Cell: ({value}: { value: string }) => ( + {value} + ), + }, + { + Header: 'Mutation', + accessor: 'mutationMethod', + Cell: ({value}: { value: string }) => ( + {value} + ), + }, { Header: 'Status', accessor: 'status', @@ -252,20 +299,6 @@ const BacktestGeneticBundle: React.FC = () => { ), }, - { - Header: 'Created', - accessor: 'createdAt', - Cell: ({value}: { value: string }) => ( - {new Date(value).toLocaleDateString()} - ), - }, - { - Header: 'Completed', - accessor: 'completedAt', - Cell: ({value}: { value: string | null }) => ( - {value ? new Date(value).toLocaleDateString() : '-'} - ), - }, { Header: 'Actions', accessor: 'actions', @@ -301,14 +334,52 @@ const BacktestGeneticBundle: React.FC = () => {
-

Genetic Algorithm Bundle

-

- Create a genetic algorithm request that will be processed in the background. - The algorithm will optimize trading parameters and indicator combinations. -

+
+
+

Genetic Algorithm Bundle

+

+ Create a genetic algorithm request that will be processed in the background. + The algorithm will optimize trading parameters and indicator combinations. +

+
+ +
-
-
+ + {isFormCollapsed && ( +
+
+

Current Settings

+
+
Ticker: {formValues.ticker}
+
Timeframe: {formValues.timeframe}
+
Population: {formValues.populationSize}
+
Generations: {formValues.generations}
+
Selection: {formValues.selectionMethod}
+
Crossover: {formValues.crossoverMethod}
+
Mutation: {formValues.mutationMethod}
+
Indicators: {selectedIndicators.length}
+
+
+
+ +
+
+ )} +
+ +
+ + +
+ +
+ +
@@ -535,6 +649,15 @@ const BacktestGeneticBundle: React.FC = () => {
Timeframe: {selectedRequest.timeframe}
+
+ Selection Method: {selectedRequest.selectionMethod} +
+
+ Crossover Method: {selectedRequest.crossoverMethod} +
+
+ Mutation Method: {selectedRequest.mutationMethod} +
Status: @@ -549,6 +672,23 @@ const BacktestGeneticBundle: React.FC = () => { Completed: {new Date(selectedRequest.completedAt).toLocaleString()}
)} +
+ Progress: {selectedRequest.currentGeneration || 0} / {selectedRequest.generations} + {selectedRequest.currentGeneration && selectedRequest.generations > 0 && ( +
+ +
+ )} +
+ {selectedRequest.bestFitnessSoFar && ( +
+ Best Fitness: {selectedRequest.bestFitnessSoFar.toFixed(4)} +
+ )}