Update genetic algo to select more indicators
This commit is contained in:
@@ -307,7 +307,7 @@ public class GeneticService : IGeneticService
|
||||
}
|
||||
|
||||
// Create fitness function first
|
||||
var fitness = new TradingBotFitness(_backtester, request);
|
||||
var fitness = new TradingBotFitness(_backtester, request, _logger);
|
||||
|
||||
// Create genetic algorithm with better configuration
|
||||
var ga = new GeneticAlgorithm(
|
||||
@@ -496,14 +496,16 @@ public class TradingBotChromosome : ChromosomeBase
|
||||
private readonly List<IndicatorType> _eligibleIndicators;
|
||||
private readonly double _maxTakeProfit;
|
||||
private readonly Random _random = new Random();
|
||||
private int[]? _indicatorSelectionPattern;
|
||||
|
||||
// Gene structure:
|
||||
// 0-2: Trading parameters (takeProfit, stopLoss, cooldownPeriod, maxLossStreak)
|
||||
// 3-6: Indicator selection (up to 4 indicators)
|
||||
// 7+: Indicator parameters (period, fastPeriods, etc.)
|
||||
// 0-3: Trading parameters (takeProfit, stopLoss, cooldownPeriod, maxLossStreak)
|
||||
// 4: Loopback period
|
||||
// 5-4+N: Indicator selection (N = number of eligible indicators)
|
||||
// 5+N+: Indicator parameters (period, fastPeriods, etc.)
|
||||
|
||||
public TradingBotChromosome(List<IndicatorType> eligibleIndicators, double maxTakeProfit)
|
||||
: base(4 + 1 + 4 +
|
||||
: base(4 + 1 + eligibleIndicators.Count +
|
||||
eligibleIndicators.Count * 8) // Trading params + loopback + indicator selection + indicator params
|
||||
{
|
||||
_eligibleIndicators = eligibleIndicators;
|
||||
@@ -535,16 +537,22 @@ public class TradingBotChromosome : ChromosomeBase
|
||||
// LoopbackPeriod gene (always between 5 and 20)
|
||||
return new Gene(GetRandomIntInRange((5, 20)));
|
||||
}
|
||||
else if (geneIndex < 9)
|
||||
else if (geneIndex < 5 + _eligibleIndicators.Count)
|
||||
{
|
||||
// Indicator selection (0 = not selected, 1 = selected)
|
||||
return new Gene(_random.Next(2));
|
||||
// Generate a random combination of up to 4 indicators
|
||||
if (_indicatorSelectionPattern == null)
|
||||
{
|
||||
GenerateIndicatorSelectionPattern();
|
||||
}
|
||||
|
||||
return new Gene(_indicatorSelectionPattern![geneIndex - 5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indicator parameters
|
||||
var indicatorIndex = (geneIndex - 9) / 8;
|
||||
var paramIndex = (geneIndex - 9) % 8;
|
||||
var indicatorIndex = (geneIndex - (5 + _eligibleIndicators.Count)) / 8;
|
||||
var paramIndex = (geneIndex - (5 + _eligibleIndicators.Count)) % 8;
|
||||
|
||||
if (indicatorIndex < _eligibleIndicators.Count)
|
||||
{
|
||||
@@ -596,6 +604,11 @@ public class TradingBotChromosome : ChromosomeBase
|
||||
{
|
||||
var clone = new TradingBotChromosome(_eligibleIndicators, _maxTakeProfit);
|
||||
clone.ReplaceGenes(0, GetGenes());
|
||||
// Copy the selection pattern to maintain consistency
|
||||
if (_indicatorSelectionPattern != null)
|
||||
{
|
||||
clone._indicatorSelectionPattern = (int[])_indicatorSelectionPattern.Clone();
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
@@ -604,9 +617,10 @@ public class TradingBotChromosome : ChromosomeBase
|
||||
var selected = new List<GeneticIndicator>();
|
||||
var genes = GetGenes();
|
||||
|
||||
for (int i = 0; i < 4; i++) // Check first 4 indicator slots
|
||||
// Check all indicator selection slots (genes 5 to 5+N-1 where N is number of eligible indicators)
|
||||
for (int i = 0; i < _eligibleIndicators.Count; i++)
|
||||
{
|
||||
if (genes[5 + i].Value.ToString() == "1" && i < _eligibleIndicators.Count)
|
||||
if (genes[5 + i].Value.ToString() == "1")
|
||||
{
|
||||
var indicator = new GeneticIndicator
|
||||
{
|
||||
@@ -614,7 +628,7 @@ public class TradingBotChromosome : ChromosomeBase
|
||||
};
|
||||
|
||||
// Add parameters for this indicator
|
||||
var baseIndex = 9 + i * 8;
|
||||
var baseIndex = 5 + _eligibleIndicators.Count + i * 8;
|
||||
var paramName = GetParameterName(0); // period
|
||||
if (paramName != null && HasParameter(_eligibleIndicators[i], paramName))
|
||||
{
|
||||
@@ -675,11 +689,8 @@ public class TradingBotChromosome : ChromosomeBase
|
||||
var genes = GetGenes();
|
||||
var selectedIndicators = GetSelectedIndicators();
|
||||
|
||||
// Ensure we have at least one indicator
|
||||
if (!selectedIndicators.Any())
|
||||
{
|
||||
selectedIndicators.Add(new GeneticIndicator { Type = _eligibleIndicators[0] });
|
||||
}
|
||||
// The selection pattern ensures at least one indicator is always selected
|
||||
// No need for fallback logic
|
||||
|
||||
// Get take profit from chromosome (gene 0)
|
||||
var takeProfit = Convert.ToDouble(genes[0].Value);
|
||||
@@ -792,6 +803,26 @@ public class TradingBotChromosome : ChromosomeBase
|
||||
return GeneticService.IndicatorParamMapping.ContainsKey(indicator) &&
|
||||
GeneticService.IndicatorParamMapping[indicator].Contains(paramName);
|
||||
}
|
||||
|
||||
private void GenerateIndicatorSelectionPattern()
|
||||
{
|
||||
// Generate a random combination of up to 4 indicators
|
||||
var selectedCount = _random.Next(1, Math.Min(5, _eligibleIndicators.Count + 1)); // 1 to 4 indicators
|
||||
var selectedIndices = new HashSet<int>();
|
||||
|
||||
// Randomly select indices
|
||||
while (selectedIndices.Count < selectedCount)
|
||||
{
|
||||
selectedIndices.Add(_random.Next(_eligibleIndicators.Count));
|
||||
}
|
||||
|
||||
// Create the selection pattern
|
||||
_indicatorSelectionPattern = new int[_eligibleIndicators.Count];
|
||||
for (int i = 0; i < _eligibleIndicators.Count; i++)
|
||||
{
|
||||
_indicatorSelectionPattern[i] = selectedIndices.Contains(i) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -818,11 +849,13 @@ public class TradingBotFitness : IFitness
|
||||
private readonly IBacktester _backtester;
|
||||
private readonly GeneticRequest _request;
|
||||
private GeneticAlgorithm _geneticAlgorithm;
|
||||
private readonly ILogger<GeneticService> _logger;
|
||||
|
||||
public TradingBotFitness(IBacktester backtester, GeneticRequest request)
|
||||
public TradingBotFitness(IBacktester backtester, GeneticRequest request, ILogger<GeneticService> logger)
|
||||
{
|
||||
_backtester = backtester;
|
||||
_request = request;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void SetGeneticAlgorithm(GeneticAlgorithm geneticAlgorithm)
|
||||
@@ -843,6 +876,15 @@ public class TradingBotFitness : IFitness
|
||||
// Get current generation number (default to 0 if not available)
|
||||
var currentGeneration = _geneticAlgorithm?.GenerationsNumber ?? 0;
|
||||
|
||||
// Log the indicators being tested (only in first few generations to avoid spam)
|
||||
if (currentGeneration < 5)
|
||||
{
|
||||
var selectedIndicators = tradingBotChromosome.GetSelectedIndicators();
|
||||
var indicatorNames = string.Join(", ", selectedIndicators.Select(i => i.Type.ToString()));
|
||||
_logger.LogDebug("Generation {Generation}: Testing indicators: {Indicators}",
|
||||
currentGeneration, indicatorNames);
|
||||
}
|
||||
|
||||
// Run backtest
|
||||
var backtest = _backtester.RunTradingBotBacktest(
|
||||
config,
|
||||
|
||||
Reference in New Issue
Block a user