Fix front and backtest
This commit is contained in:
@@ -30,7 +30,6 @@ namespace Managing.Application.Abstractions
|
||||
int GetWinRate();
|
||||
decimal GetProfitAndLoss();
|
||||
decimal GetTotalFees();
|
||||
void LoadScenario(string scenarioName);
|
||||
void LoadScenario(Scenario scenario);
|
||||
void UpdateIndicatorsValues();
|
||||
Task LoadAccount();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Repositories;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Bots;
|
||||
using Managing.Core.FixedSizedQueue;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Backtests;
|
||||
@@ -113,24 +114,15 @@ namespace Managing.Application.Backtesting
|
||||
List<Candle> candles,
|
||||
User user = null)
|
||||
{
|
||||
// Set FlipPosition based on BotType
|
||||
config.FlipPosition = config.FlipPosition;
|
||||
|
||||
var tradingBot = _botFactory.CreateBacktestTradingBot(config);
|
||||
|
||||
// Load scenario - prefer Scenario object over ScenarioName
|
||||
if (config.Scenario != null)
|
||||
// Scenario and indicators should already be loaded in constructor by BotService
|
||||
// This is just a validation check to ensure everything loaded properly
|
||||
if (tradingBot is TradingBot bot && !bot.Indicators.Any())
|
||||
{
|
||||
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");
|
||||
throw new InvalidOperationException(
|
||||
$"No indicators were loaded for scenario '{config.ScenarioName ?? config.Scenario?.Name}'. " +
|
||||
"This indicates a problem with scenario loading.");
|
||||
}
|
||||
|
||||
tradingBot.User = user;
|
||||
@@ -218,7 +210,6 @@ namespace Managing.Application.Backtesting
|
||||
_logger.LogInformation("Backtest processing completed. Calculating final results...");
|
||||
|
||||
bot.Candles = new HashSet<Candle>(candles);
|
||||
// bot.UpdateIndicatorsValues();
|
||||
|
||||
var indicatorsValues = GetIndicatorsValues(bot.Config.Scenario.Indicators, candles);
|
||||
|
||||
@@ -256,7 +247,8 @@ namespace Managing.Application.Backtesting
|
||||
Statistics = stats,
|
||||
OptimizedMoneyManagement = optimizedMoneyManagement,
|
||||
IndicatorsValues = AggregateValues(indicatorsValues, bot.IndicatorsValues),
|
||||
Score = score
|
||||
Score = score,
|
||||
Id = Guid.NewGuid().ToString()
|
||||
};
|
||||
|
||||
return result;
|
||||
|
||||
@@ -38,27 +38,14 @@ namespace Managing.Application.Bots.Base
|
||||
|
||||
ITradingBot IBotFactory.CreateTradingBot(TradingBotConfig config)
|
||||
{
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
_tradingService,
|
||||
_accountService,
|
||||
_messengerService,
|
||||
_botService,
|
||||
config);
|
||||
// Delegate to BotService which handles scenario loading properly
|
||||
return _botService.CreateTradingBot(config);
|
||||
}
|
||||
|
||||
ITradingBot IBotFactory.CreateBacktestTradingBot(TradingBotConfig config)
|
||||
{
|
||||
config.IsForBacktest = true;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
_tradingService,
|
||||
_accountService,
|
||||
_messengerService,
|
||||
_botService,
|
||||
config);
|
||||
// Delegate to BotService which handles scenario loading properly
|
||||
return _botService.CreateBacktestTradingBot(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,16 @@ public class TradingBot : Bot, ITradingBot
|
||||
WalletBalances = new Dictionary<DateTime, decimal>();
|
||||
IndicatorsValues = new Dictionary<IndicatorType, IndicatorsResultBase>();
|
||||
|
||||
// Load indicators if scenario is provided in config
|
||||
if (Config.Scenario != null)
|
||||
{
|
||||
LoadIndicators(Config.Scenario);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided in TradingBotConfig. ScenarioName alone is not sufficient.");
|
||||
}
|
||||
|
||||
if (!Config.IsForBacktest)
|
||||
{
|
||||
Interval = CandleExtensions.GetIntervalFromTimeframe(Config.Timeframe);
|
||||
@@ -91,7 +101,13 @@ public class TradingBot : Bot, ITradingBot
|
||||
|
||||
if (!Config.IsForBacktest)
|
||||
{
|
||||
LoadScenario(Config.ScenarioName);
|
||||
// Scenario and indicators should already be loaded in constructor
|
||||
// This is just a safety check
|
||||
if (Config.Scenario == null || !Indicators.Any())
|
||||
{
|
||||
throw new InvalidOperationException("Scenario or indicators not loaded properly in constructor. This indicates a configuration error.");
|
||||
}
|
||||
|
||||
PreloadCandles().GetAwaiter().GetResult();
|
||||
CancelAllOrders().GetAwaiter().GetResult();
|
||||
|
||||
@@ -127,33 +143,32 @@ public class TradingBot : Bot, ITradingBot
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadScenario(string scenarioName)
|
||||
{
|
||||
if (Config.Scenario != null)
|
||||
return;
|
||||
|
||||
var scenario = TradingService.GetScenarioByName(scenarioName);
|
||||
if (scenario == null)
|
||||
{
|
||||
Logger.LogWarning("No scenario found for this scenario name");
|
||||
Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadIndicators(ScenarioHelpers.GetIndicatorsFromScenario(scenario));
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadScenario(Scenario scenario)
|
||||
{
|
||||
if (scenario == null)
|
||||
{
|
||||
Logger.LogWarning("Null scenario provided");
|
||||
Stop();
|
||||
var errorMessage = "Null scenario provided";
|
||||
Logger.LogWarning(errorMessage);
|
||||
|
||||
// If called during construction, throw exception instead of Stop()
|
||||
if (Status == BotStatus.Down)
|
||||
{
|
||||
throw new ArgumentException(errorMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Store the scenario in config and load indicators
|
||||
Config.Scenario = scenario;
|
||||
LoadIndicators(ScenarioHelpers.GetIndicatorsFromScenario(scenario));
|
||||
|
||||
Logger.LogInformation($"Loaded scenario '{scenario.Name}' with {Indicators.Count} indicators");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,10 +179,15 @@ public class TradingBot : Bot, ITradingBot
|
||||
|
||||
public void LoadIndicators(IEnumerable<IIndicator> indicators)
|
||||
{
|
||||
foreach (var strategy in indicators)
|
||||
// Clear existing indicators to prevent duplicates
|
||||
Indicators.Clear();
|
||||
|
||||
foreach (var indicator in indicators)
|
||||
{
|
||||
Indicators.Add(strategy);
|
||||
Indicators.Add(indicator);
|
||||
}
|
||||
|
||||
Logger.LogInformation($"Loaded {Indicators.Count} indicators for bot '{Name}'");
|
||||
}
|
||||
|
||||
public async Task Run()
|
||||
@@ -1444,9 +1464,9 @@ public class TradingBot : Bot, ITradingBot
|
||||
throw new ArgumentException("Account name cannot be null or empty");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(newConfig.ScenarioName))
|
||||
if (newConfig.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario name cannot be null or empty");
|
||||
throw new ArgumentException("Scenario object must be provided in configuration");
|
||||
}
|
||||
|
||||
// Protect critical properties that shouldn't change for running bots
|
||||
@@ -1487,9 +1507,17 @@ public class TradingBot : Bot, ITradingBot
|
||||
|
||||
// If scenario changed, reload it
|
||||
var currentScenario = Config.Scenario?.Name;
|
||||
if (Config.ScenarioName != currentScenario)
|
||||
var newScenario = newConfig.Scenario?.Name;
|
||||
if (newScenario != currentScenario)
|
||||
{
|
||||
LoadScenario(Config.ScenarioName);
|
||||
if (newConfig.Scenario != null)
|
||||
{
|
||||
LoadScenario(newConfig.Scenario);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("New scenario object must be provided when updating configuration.");
|
||||
}
|
||||
}
|
||||
|
||||
await LogInformation("✅ **Configuration Applied**\n" +
|
||||
|
||||
@@ -134,6 +134,25 @@ namespace Managing.Application.ManageBot
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (scalpingConfig.Scenario == null && !string.IsNullOrEmpty(scalpingConfig.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(scalpingConfig.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
scalpingConfig.Scenario = scenario;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Scenario '{scalpingConfig.ScenarioName}' not found in database when loading backup");
|
||||
}
|
||||
}
|
||||
|
||||
if (scalpingConfig.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid when loading backup");
|
||||
}
|
||||
|
||||
// Ensure critical properties are set correctly for restored bots
|
||||
scalpingConfig.IsForBacktest = false;
|
||||
|
||||
@@ -235,6 +254,25 @@ namespace Managing.Application.ManageBot
|
||||
if (_botTasks.TryGetValue(identifier, out var botTaskWrapper) &&
|
||||
botTaskWrapper.BotInstance is TradingBot tradingBot)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (newConfig.Scenario == null && !string.IsNullOrEmpty(newConfig.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(newConfig.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
newConfig.Scenario = scenario;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Scenario '{newConfig.ScenarioName}' not found in database when updating configuration");
|
||||
}
|
||||
}
|
||||
|
||||
if (newConfig.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid when updating configuration");
|
||||
}
|
||||
|
||||
// Check if the bot name is changing
|
||||
if (newConfig.Name != identifier && !string.IsNullOrEmpty(newConfig.Name))
|
||||
{
|
||||
@@ -279,6 +317,25 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
public ITradingBot CreateTradingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Scenario '{config.ScenarioName}' not found in database");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid");
|
||||
}
|
||||
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
_tradingBotLogger,
|
||||
@@ -291,6 +348,25 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
public ITradingBot CreateBacktestTradingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Scenario '{config.ScenarioName}' not found in database");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid");
|
||||
}
|
||||
|
||||
config.IsForBacktest = true;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
@@ -304,6 +380,25 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
public ITradingBot CreateScalpingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Scenario '{config.ScenarioName}' not found in database");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid");
|
||||
}
|
||||
|
||||
config.FlipPosition = false;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
@@ -317,6 +412,25 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
public ITradingBot CreateBacktestScalpingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Scenario '{config.ScenarioName}' not found in database");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid");
|
||||
}
|
||||
|
||||
config.IsForBacktest = true;
|
||||
config.FlipPosition = false;
|
||||
return new TradingBot(
|
||||
@@ -331,6 +445,25 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
public ITradingBot CreateFlippingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Scenario '{config.ScenarioName}' not found in database");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid");
|
||||
}
|
||||
|
||||
config.FlipPosition = true;
|
||||
return new TradingBot(
|
||||
_exchangeService,
|
||||
@@ -344,6 +477,25 @@ namespace Managing.Application.ManageBot
|
||||
|
||||
public ITradingBot CreateBacktestFlippingBot(TradingBotConfig config)
|
||||
{
|
||||
// Ensure the scenario is properly loaded from database if needed
|
||||
if (config.Scenario == null && !string.IsNullOrEmpty(config.ScenarioName))
|
||||
{
|
||||
var scenario = _tradingService.GetScenarioByName(config.ScenarioName);
|
||||
if (scenario != null)
|
||||
{
|
||||
config.Scenario = scenario;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Scenario '{config.ScenarioName}' not found in database");
|
||||
}
|
||||
}
|
||||
|
||||
if (config.Scenario == null)
|
||||
{
|
||||
throw new ArgumentException("Scenario object must be provided or ScenarioName must be valid");
|
||||
}
|
||||
|
||||
config.IsForBacktest = true;
|
||||
config.FlipPosition = true;
|
||||
return new TradingBot(
|
||||
|
||||
Reference in New Issue
Block a user