Test strategy combo

This commit is contained in:
2025-06-15 18:46:41 +07:00
parent 3f34c56968
commit e4f4d078b2
8 changed files with 1024 additions and 157 deletions

View File

@@ -56,47 +56,32 @@ namespace Managing.Application.Backtesting
}
/// <summary>
/// Runs a unified trading bot backtest with the specified configuration and date range.
/// Automatically handles ScalpingBot and FlippingBot behavior based on config.BotType.
/// Runs a trading bot backtest with the specified configuration and date range.
/// Automatically handles different bot types based on config.BotType.
/// </summary>
/// <param name="config">The trading bot configuration</param>
/// <param name="config">The trading bot configuration (must include Scenario object or ScenarioName)</param>
/// <param name="startDate">The start date for the backtest</param>
/// <param name="endDate">The end date for the backtest</param>
/// <param name="user">The user running the backtest</param>
/// <param name="user">The user running the backtest (optional)</param>
/// <param name="save">Whether to save the backtest results</param>
/// <param name="initialCandles">Optional pre-loaded candles</param>
/// <returns>The backtest results</returns>
public async Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config,
DateTime startDate,
DateTime endDate,
User user = null,
bool save = false,
List<Candle>? initialCandles = null)
bool save = false)
{
var account = await GetAccountFromConfig(config);
var candles = GetCandles(account, config.Ticker, config.Timeframe, startDate, endDate);
// Set FlipPosition based on BotType
config.FlipPosition = config.BotType == BotType.FlippingBot;
var result = await RunBacktestWithCandles(config, candles, user);
var tradingBot = _botFactory.CreateBacktestTradingBot(config);
tradingBot.LoadScenario(config.ScenarioName);
tradingBot.User = user;
await tradingBot.LoadAccount();
var candles = initialCandles ?? GetCandles(account, config.Ticker, config.Timeframe, startDate, endDate);
var result = GetBacktestingResult(config, tradingBot, candles);
if (user != null)
{
result.User = user;
}
// Set start and end dates
result.StartDate = startDate;
result.EndDate = endDate;
if (save)
if (save && user != null)
{
_backtestRepository.InsertBacktestForUser(user, result);
}
@@ -105,25 +90,48 @@ namespace Managing.Application.Backtesting
}
/// <summary>
/// Runs a unified trading bot backtest with pre-loaded candles.
/// Automatically handles ScalpingBot and FlippingBot behavior based on config.BotType.
/// Runs a trading bot backtest with pre-loaded candles.
/// Automatically handles different bot types based on config.BotType.
/// </summary>
/// <param name="config">The trading bot configuration</param>
/// <param name="config">The trading bot configuration (must include Scenario object or ScenarioName)</param>
/// <param name="candles">The candles to use for backtesting</param>
/// <param name="user">The user running the backtest</param>
/// <param name="user">The user running the backtest (optional)</param>
/// <returns>The backtest results</returns>
public async Task<Backtest> RunTradingBotBacktest(
TradingBotConfig config,
List<Candle> candles,
User user = null)
{
var account = await GetAccountFromConfig(config);
return await RunBacktestWithCandles(config, candles, user);
}
/// <summary>
/// Core backtesting logic - handles the actual backtest execution with pre-loaded candles
/// </summary>
private async Task<Backtest> RunBacktestWithCandles(
TradingBotConfig config,
List<Candle> candles,
User user = null)
{
// Set FlipPosition based on BotType
config.FlipPosition = config.BotType == BotType.FlippingBot;
var tradingBot = _botFactory.CreateBacktestTradingBot(config);
tradingBot.LoadScenario(config.ScenarioName);
// Load scenario - prefer Scenario object over ScenarioName
if (config.Scenario != null)
{
tradingBot.LoadScenario(config.Scenario);
}
else if (!string.IsNullOrEmpty(config.ScenarioName))
{
tradingBot.LoadScenario(config.ScenarioName);
}
else
{
throw new ArgumentException("Either Scenario object or ScenarioName must be provided in TradingBotConfig");
}
tradingBot.User = user;
await tradingBot.LoadAccount();
@@ -137,73 +145,25 @@ namespace Managing.Application.Backtesting
return result;
}
// Legacy methods - maintained for backward compatibility
public async Task<Backtest> RunScalpingBotBacktest(
TradingBotConfig config,
DateTime startDate,
DateTime endDate,
User user = null,
bool save = false,
List<Candle>? initialCandles = null)
{
config.BotType = BotType.ScalpingBot; // Ensure correct type
return await RunTradingBotBacktest(config, startDate, endDate, user, save, initialCandles);
}
public async Task<Backtest> RunFlippingBotBacktest(
TradingBotConfig config,
DateTime startDate,
DateTime endDate,
User user = null,
bool save = false,
List<Candle>? initialCandles = null)
{
config.BotType = BotType.FlippingBot; // Ensure correct type
return await RunTradingBotBacktest(config, startDate, endDate, user, save, initialCandles);
}
public async Task<Backtest> RunScalpingBotBacktest(
TradingBotConfig config,
List<Candle> candles,
User user = null)
{
config.BotType = BotType.ScalpingBot; // Ensure correct type
return await RunTradingBotBacktest(config, candles, user);
}
public async Task<Backtest> RunFlippingBotBacktest(
TradingBotConfig config,
List<Candle> candles,
User user = null)
{
config.BotType = BotType.FlippingBot; // Ensure correct type
return await RunTradingBotBacktest(config, candles, user);
}
private async Task<Account> GetAccountFromConfig(TradingBotConfig config)
{
// Use the account service to get the actual account
var account = await _accountService.GetAccount(config.AccountName, false, false);
if (account != null)
{
return account;
}
// Fallback: create a basic account structure if not found
return new Account
{
Name = config.AccountName,
Exchange = TradingExchanges.GmxV2 // Default exchange, should be configurable
Exchange = TradingExchanges.GmxV2
};
}
private List<Candle> GetCandles(Account account, Ticker ticker, Timeframe timeframe,
DateTime startDate, DateTime endDate)
{
List<Candle> candles;
// Use specific date range
candles = _exchangeService.GetCandlesInflux(account.Exchange, ticker,
var candles = _exchangeService.GetCandlesInflux(account.Exchange, ticker,
startDate, timeframe, endDate).Result;
if (candles == null || candles.Count == 0)
@@ -326,13 +286,10 @@ namespace Managing.Application.Backtesting
return strategiesValues;
}
public bool DeleteBacktest(string id)
{
try
{
// Since we no longer have a general DeleteBacktestById method in the repository,
// this should be implemented using DeleteBacktestByIdForUser with null
_backtestRepository.DeleteBacktestByIdForUser(null, id);
return true;
}
@@ -347,8 +304,6 @@ namespace Managing.Application.Backtesting
{
try
{
// Since we no longer have a general DeleteAllBacktests method in the repository,
// this should be implemented using DeleteAllBacktestsForUser with null
_backtestRepository.DeleteAllBacktestsForUser(null);
return true;
}
@@ -363,10 +318,8 @@ namespace Managing.Application.Backtesting
{
var backtests = _backtestRepository.GetBacktestsByUser(user).ToList();
// For each backtest, ensure candles are loaded
foreach (var backtest in backtests)
{
// If the backtest has no candles or only a few sample candles, retrieve them
if (backtest.Candles == null || backtest.Candles.Count == 0 || backtest.Candles.Count < 10)
{
try
@@ -386,7 +339,6 @@ namespace Managing.Application.Backtesting
catch (Exception ex)
{
_logger.LogError(ex, "Failed to retrieve candles for backtest {Id}", backtest.Id);
// Continue with the next backtest if there's an error
}
}
}
@@ -396,22 +348,18 @@ namespace Managing.Application.Backtesting
public Backtest GetBacktestByIdForUser(User user, string id)
{
// Get the backtest from the repository
var backtest = _backtestRepository.GetBacktestByIdForUser(user, id);
if (backtest == null)
return null;
// If the backtest has no candles or only a few sample candles, retrieve them
if (backtest.Candles == null || backtest.Candles.Count == 0 || backtest.Candles.Count < 10)
{
try
{
// Get the account
var account = new Account
{ Name = backtest.Config.AccountName, Exchange = TradingExchanges.Evm };
// Use the stored start and end dates to retrieve candles
var candles = _exchangeService.GetCandlesInflux(
account.Exchange,
backtest.Config.Ticker,
@@ -427,7 +375,6 @@ namespace Managing.Application.Backtesting
catch (Exception ex)
{
_logger.LogError(ex, "Failed to retrieve candles for backtest {Id}", id);
// Return the backtest without candles if there's an error
}
}