Add metadata to backtest

This commit is contained in:
2025-07-11 17:56:03 +07:00
parent c62570e15d
commit 47ef0cf2d5
8 changed files with 49 additions and 16 deletions

View File

@@ -18,6 +18,7 @@ namespace Managing.Application.Abstractions.Services
/// <param name="save">Whether to save the backtest results</param> /// <param name="save">Whether to save the backtest results</param>
/// <param name="withCandles">Whether to include candles and indicators values in the response</param> /// <param name="withCandles">Whether to include candles and indicators values in the response</param>
/// <param name="requestId">The request ID to associate with this backtest (optional)</param> /// <param name="requestId">The request ID to associate with this backtest (optional)</param>
/// <param name="metadata">Additional metadata to associate with this backtest (optional)</param>
/// <returns>The backtest results</returns> /// <returns>The backtest results</returns>
Task<Backtest> RunTradingBotBacktest( Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config, TradingBotConfig config,
@@ -26,7 +27,8 @@ namespace Managing.Application.Abstractions.Services
User user = null, User user = null,
bool save = false, bool save = false,
bool withCandles = false, bool withCandles = false,
string requestId = null); string requestId = null,
object metadata = null);
/// <summary> /// <summary>
/// Runs a trading bot backtest with pre-loaded candles. /// Runs a trading bot backtest with pre-loaded candles.
@@ -37,13 +39,15 @@ namespace Managing.Application.Abstractions.Services
/// <param name="user">The user running the backtest (optional)</param> /// <param name="user">The user running the backtest (optional)</param>
/// <param name="withCandles">Whether to include candles and indicators values in the response</param> /// <param name="withCandles">Whether to include candles and indicators values in the response</param>
/// <param name="requestId">The request ID to associate with this backtest (optional)</param> /// <param name="requestId">The request ID to associate with this backtest (optional)</param>
/// <param name="metadata">Additional metadata to associate with this backtest (optional)</param>
/// <returns>The backtest results</returns> /// <returns>The backtest results</returns>
Task<Backtest> RunTradingBotBacktest( Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config, TradingBotConfig config,
List<Candle> candles, List<Candle> candles,
User user = null, User user = null,
bool withCandles = false, bool withCandles = false,
string requestId = null); string requestId = null,
object metadata = null);
// Additional methods for backtest management // Additional methods for backtest management
bool DeleteBacktest(string id); bool DeleteBacktest(string id);

View File

@@ -70,6 +70,7 @@ namespace Managing.Application.Backtesting
/// <param name="save">Whether to save the backtest results</param> /// <param name="save">Whether to save the backtest results</param>
/// <param name="withCandles">Whether to include candles and indicators values in the response</param> /// <param name="withCandles">Whether to include candles and indicators values in the response</param>
/// <param name="requestId">The request ID to associate with this backtest (optional)</param> /// <param name="requestId">The request ID to associate with this backtest (optional)</param>
/// <param name="metadata">Additional metadata to associate with this backtest (optional)</param>
/// <returns>The backtest results</returns> /// <returns>The backtest results</returns>
public async Task<Backtest> RunTradingBotBacktest( public async Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config, TradingBotConfig config,
@@ -78,11 +79,12 @@ namespace Managing.Application.Backtesting
User user = null, User user = null,
bool save = false, bool save = false,
bool withCandles = false, bool withCandles = false,
string requestId = null) string requestId = null,
object metadata = null)
{ {
var candles = GetCandles(config.Ticker, config.Timeframe, startDate, endDate); 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 // Set start and end dates
result.StartDate = startDate; result.StartDate = startDate;
@@ -110,9 +112,10 @@ namespace Managing.Application.Backtesting
List<Candle> candles, List<Candle> candles,
User user = null, User user = null,
bool withCandles = false, 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);
} }
/// <summary> /// <summary>
@@ -123,7 +126,8 @@ namespace Managing.Application.Backtesting
List<Candle> candles, List<Candle> candles,
User user = null, User user = null,
bool withCandles = false, bool withCandles = false,
string requestId = null) string requestId = null,
object metadata = null)
{ {
var tradingBot = _botFactory.CreateBacktestTradingBot(config); var tradingBot = _botFactory.CreateBacktestTradingBot(config);
@@ -139,7 +143,7 @@ namespace Managing.Application.Backtesting
tradingBot.User = user; tradingBot.User = user;
await tradingBot.LoadAccount(); 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) if (user != null)
{ {
@@ -182,7 +186,8 @@ namespace Managing.Application.Backtesting
List<Candle> candles, List<Candle> candles,
User user = null, User user = null,
bool withCandles = false, bool withCandles = false,
string requestId = null) string requestId = null,
object metadata = null)
{ {
if (candles == null || candles.Count == 0) if (candles == null || candles.Count == 0)
{ {
@@ -272,7 +277,8 @@ namespace Managing.Application.Backtesting
: new Dictionary<IndicatorType, IndicatorsResultBase>(), : new Dictionary<IndicatorType, IndicatorsResultBase>(),
Score = score, Score = score,
Id = Guid.NewGuid().ToString(), Id = Guid.NewGuid().ToString(),
RequestId = requestId RequestId = requestId,
Metadata = metadata
}; };
// Send notification if backtest meets criteria // Send notification if backtest meets criteria

View File

@@ -299,7 +299,7 @@ public class GeneticService : IGeneticService
_logger.LogInformation("Starting fresh genetic algorithm for request {RequestId}", request.RequestId); _logger.LogInformation("Starting fresh genetic algorithm for request {RequestId}", request.RequestId);
} }
// Create fitness function // Create fitness function first
var fitness = new TradingBotFitness(_backtester, request); var fitness = new TradingBotFitness(_backtester, request);
// Create genetic algorithm with better configuration // Create genetic algorithm with better configuration
@@ -315,6 +315,9 @@ public class GeneticService : IGeneticService
CrossoverProbability = 0.7f // Fixed crossover rate as in frontend 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 // Custom termination condition that checks for cancellation
var originalTermination = ga.Termination; var originalTermination = ga.Termination;
ga.Termination = new GenerationNumberTermination(request.Generations); ga.Termination = new GenerationNumberTermination(request.Generations);
@@ -768,6 +771,7 @@ public class TradingBotFitness : IFitness
{ {
private readonly IBacktester _backtester; private readonly IBacktester _backtester;
private readonly GeneticRequest _request; private readonly GeneticRequest _request;
private GeneticAlgorithm _geneticAlgorithm;
public TradingBotFitness(IBacktester backtester, GeneticRequest request) public TradingBotFitness(IBacktester backtester, GeneticRequest request)
{ {
@@ -775,6 +779,11 @@ public class TradingBotFitness : IFitness
_request = request; _request = request;
} }
public void SetGeneticAlgorithm(GeneticAlgorithm geneticAlgorithm)
{
_geneticAlgorithm = geneticAlgorithm;
}
public double Evaluate(IChromosome chromosome) public double Evaluate(IChromosome chromosome)
{ {
try try
@@ -785,15 +794,22 @@ public class TradingBotFitness : IFitness
var config = tradingBotChromosome.GetTradingBotConfig(_request); var config = tradingBotChromosome.GetTradingBotConfig(_request);
// Get current generation number (default to 0 if not available)
var currentGeneration = _geneticAlgorithm?.GenerationsNumber ?? 0;
// Run backtest // Run backtest
var backtest = _backtester.RunTradingBotBacktest( var backtest = _backtester.RunTradingBotBacktest(
config, config,
_request.StartDate, _request.StartDate,
_request.EndDate, _request.EndDate,
_request.User, _request.User,
true, // Don't save individual backtests true,
false, // Don't include candles false, // Don't include candles
_request.RequestId _request.RequestId,
new
{
generation = currentGeneration
}
).Result; ).Result;
// Calculate multi-objective fitness based on backtest results // Calculate multi-objective fitness based on backtest results

View File

@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; #nullable enable
using System.ComponentModel.DataAnnotations;
using Exilion.TradingAtomics; using Exilion.TradingAtomics;
using Managing.Domain.Bots; using Managing.Domain.Bots;
using Managing.Domain.Candles; using Managing.Domain.Candles;
@@ -58,6 +59,7 @@ public class Backtest
[Required] public Dictionary<IndicatorType, IndicatorsResultBase> IndicatorsValues { get; set; } [Required] public Dictionary<IndicatorType, IndicatorsResultBase> IndicatorsValues { get; set; }
[Required] public double Score { get; set; } [Required] public double Score { get; set; }
public string RequestId { get; set; } public string RequestId { get; set; }
public object? Metadata { get; set; }
/// <summary> /// <summary>
/// Creates a new TradingBotConfig based on this backtest's configuration for starting a live bot. /// Creates a new TradingBotConfig based on this backtest's configuration for starting a live bot.

View File

@@ -23,5 +23,6 @@ namespace Managing.Infrastructure.Databases.MongoDb.Collections
public double Score { get; set; } public double Score { get; set; }
public string Identifier { get; set; } public string Identifier { get; set; }
public string RequestId { get; set; } public string RequestId { get; set; }
public string? Metadata { get; set; }
} }
} }

View File

@@ -150,7 +150,8 @@ public static class MongoMappers
StartDate = b.StartDate, StartDate = b.StartDate,
EndDate = b.EndDate, EndDate = b.EndDate,
Score = b.Score, Score = b.Score,
RequestId = b.RequestId RequestId = b.RequestId,
Metadata = string.IsNullOrEmpty(b.Metadata) ? null : JsonSerializer.Deserialize<object>(b.Metadata)
}; };
return bTest; return bTest;
@@ -178,7 +179,8 @@ public static class MongoMappers
StartDate = result.StartDate, StartDate = result.StartDate,
EndDate = result.EndDate, EndDate = result.EndDate,
Score = result.Score, Score = result.Score,
RequestId = result.RequestId RequestId = result.RequestId,
Metadata = result.Metadata == null ? null : JsonSerializer.Serialize(result.Metadata)
}; };
} }

View File

@@ -3290,6 +3290,7 @@ export interface Backtest {
indicatorsValues: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; }; indicatorsValues: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; };
score: number; score: number;
requestId?: string | null; requestId?: string | null;
metadata?: any | null;
} }
export interface TradingBotConfig { export interface TradingBotConfig {

View File

@@ -237,6 +237,7 @@ export interface Backtest {
indicatorsValues: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; }; indicatorsValues: { [key in keyof typeof IndicatorType]?: IndicatorsResultBase; };
score: number; score: number;
requestId?: string | null; requestId?: string | null;
metadata?: any | null;
} }
export interface TradingBotConfig { export interface TradingBotConfig {