Fix solution build

This commit is contained in:
2025-07-30 20:37:24 +07:00
parent 3de8b5e00e
commit 1071730978
7 changed files with 36 additions and 69 deletions

View File

@@ -8,7 +8,6 @@ using Managing.Application.Bots.Base;
using Managing.Application.Hubs; using Managing.Application.Hubs;
using Managing.Application.ManageBot; using Managing.Application.ManageBot;
using Managing.Core; using Managing.Core;
using Managing.Domain.Backtests;
using Managing.Domain.Bots; using Managing.Domain.Bots;
using Managing.Domain.Candles; using Managing.Domain.Candles;
using Managing.Domain.MoneyManagements; using Managing.Domain.MoneyManagements;
@@ -177,7 +176,7 @@ namespace Managing.Application.Tests
AccountName = _account.Name, AccountName = _account.Name,
MoneyManagement = moneyManagement, MoneyManagement = moneyManagement,
Ticker = ticker, Ticker = ticker,
Scenario = scenario, Scenario = LightScenario.FromScenario(scenario),
Timeframe = timeframe, Timeframe = timeframe,
IsForWatchingOnly = false, IsForWatchingOnly = false,
BotTradingBalance = 1000, BotTradingBalance = 1000,
@@ -194,7 +193,7 @@ namespace Managing.Application.Tests
// Act // Act
var backtestResult = await _backtester.RunTradingBotBacktest(config, DateTime.UtcNow.AddDays(-6), var backtestResult = await _backtester.RunTradingBotBacktest(config, DateTime.UtcNow.AddDays(-6),
DateTime.UtcNow, null, false, false); DateTime.UtcNow, null, false, false);
WriteCsvReport(backtestResult.GetStringReport()); // WriteCsvReport(backtestResult.GetStringReport());
// Assert // Assert
Assert.True(backtestResult.FinalPnl > 0); Assert.True(backtestResult.FinalPnl > 0);
@@ -234,10 +233,10 @@ namespace Managing.Application.Tests
if (candles == null || candles.Count == 0) if (candles == null || candles.Count == 0)
return; return;
Parallel.For(periodRange[0], periodRange[1], options, i => Parallel.For((long)periodRange[0], periodRange[1], options, i =>
{ {
var scenario = new Scenario("ScalpingScenario"); var scenario = new Scenario("ScalpingScenario");
var strategy = ScenarioHelpers.BuildIndicator(indicatorType, "RsiDiv", period: i); var strategy = ScenarioHelpers.BuildIndicator(indicatorType, "RsiDiv", period: (int)i);
scenario.AddIndicator(strategy); scenario.AddIndicator(strategy);
// -0.5 to -5 // -0.5 to -5
@@ -267,7 +266,7 @@ namespace Managing.Application.Tests
AccountName = _account.Name, AccountName = _account.Name,
MoneyManagement = moneyManagement, MoneyManagement = moneyManagement,
Ticker = ticker, Ticker = ticker,
Scenario = scenario, Scenario = LightScenario.FromScenario(scenario),
Timeframe = timeframe, Timeframe = timeframe,
IsForWatchingOnly = false, IsForWatchingOnly = false,
BotTradingBalance = 1000, BotTradingBalance = 1000,
@@ -285,7 +284,7 @@ namespace Managing.Application.Tests
AccountName = _account.Name, AccountName = _account.Name,
MoneyManagement = moneyManagement, MoneyManagement = moneyManagement,
Ticker = ticker, Ticker = ticker,
Scenario = scenario, Scenario = LightScenario.FromScenario(scenario),
Timeframe = timeframe, Timeframe = timeframe,
IsForWatchingOnly = false, IsForWatchingOnly = false,
BotTradingBalance = 1000, BotTradingBalance = 1000,
@@ -304,10 +303,10 @@ namespace Managing.Application.Tests
if (backtestResult.FinalPnl > 0 if (backtestResult.FinalPnl > 0
&& (backtestResult.GrowthPercentage - backtestResult.HodlPercentage) > 30 && (backtestResult.GrowthPercentage - backtestResult.HodlPercentage) > 30
&& backtestResult.Statistics.MaxDrawdown < 3) && backtestResult.Score < 3)
{ {
var currentResult = new Tuple<string, int, decimal, decimal, decimal, decimal>( var currentResult = new Tuple<string, int, decimal, decimal, decimal, decimal>(
ticker.ToString(), i, ticker.ToString(), (int)i,
backtestResult.FinalPnl, s, t, backtestResult.FinalPnl, s, t,
backtestResult.GrowthPercentage - backtestResult.HodlPercentage); backtestResult.GrowthPercentage - backtestResult.HodlPercentage);
result.Add(currentResult); result.Add(currentResult);
@@ -407,7 +406,7 @@ namespace Managing.Application.Tests
AccountName = _account.Name, AccountName = _account.Name,
MoneyManagement = moneyManagement, MoneyManagement = moneyManagement,
Ticker = ticker, Ticker = ticker,
Scenario = scenario, Scenario = LightScenario.FromScenario(scenario),
Timeframe = timeframe, Timeframe = timeframe,
IsForWatchingOnly = false, IsForWatchingOnly = false,
BotTradingBalance = 1000, BotTradingBalance = 1000,
@@ -425,7 +424,7 @@ namespace Managing.Application.Tests
AccountName = _account.Name, AccountName = _account.Name,
MoneyManagement = moneyManagement, MoneyManagement = moneyManagement,
Ticker = ticker, Ticker = ticker,
Scenario = scenario, Scenario = LightScenario.FromScenario(scenario),
Timeframe = timeframe, Timeframe = timeframe,
IsForWatchingOnly = false, IsForWatchingOnly = false,
BotTradingBalance = 1000, BotTradingBalance = 1000,
@@ -442,8 +441,7 @@ namespace Managing.Application.Tests
}; };
if (backtestResult.FinalPnl > 0 if (backtestResult.FinalPnl > 0
&& (backtestResult.GrowthPercentage - backtestResult.HodlPercentage) > 30 && (backtestResult.GrowthPercentage - backtestResult.HodlPercentage) > 30)
&& backtestResult.Statistics.MaxDrawdown < 3)
{ {
var currentResult = new Tuple<string, decimal, decimal, decimal, decimal>( var currentResult = new Tuple<string, decimal, decimal, decimal, decimal>(
ticker.ToString(), ticker.ToString(),
@@ -661,7 +659,7 @@ namespace Managing.Application.Tests
AccountName = _account.Name, AccountName = _account.Name,
MoneyManagement = standardMoneyManagement, MoneyManagement = standardMoneyManagement,
Ticker = ticker, Ticker = ticker,
Scenario = scenario, Scenario = LightScenario.FromScenario(scenario),
Timeframe = timeframe, Timeframe = timeframe,
IsForWatchingOnly = false, IsForWatchingOnly = false,
BotTradingBalance = 1000, BotTradingBalance = 1000,
@@ -679,24 +677,6 @@ namespace Managing.Application.Tests
timer.Stop(); timer.Stop();
var scoringParams = new BacktestScoringParams(
sharpeRatio: (double)(backtestResult.Statistics?.SharpeRatio ?? 0),
growthPercentage: (double)backtestResult.GrowthPercentage,
hodlPercentage: (double)backtestResult.HodlPercentage,
winRate: backtestResult.WinRate / 100.0, // Convert percentage to decimal
totalPnL: (double)backtestResult.FinalPnl,
fees: (double)backtestResult.Fees,
tradeCount: backtestResult.Positions?.Count ?? 0,
maxDrawdownRecoveryTime: backtestResult.Statistics?.MaxDrawdownRecoveryTime ?? TimeSpan.Zero,
maxDrawdown: backtestResult.Statistics?.MaxDrawdown ?? 0,
initialBalance: config.BotTradingBalance,
tradingBalance: config.BotTradingBalance,
startDate: backtestResult.StartDate,
endDate: backtestResult.EndDate,
timeframe: config.Timeframe,
moneyManagement: config.MoneyManagement
);
var scenarioResult = new ScenarioBacktestResult var scenarioResult = new ScenarioBacktestResult
{ {
ScenarioName = scenario.Name, ScenarioName = scenario.Name,
@@ -708,14 +688,13 @@ namespace Managing.Application.Tests
GrowthPercentage = backtestResult.GrowthPercentage, GrowthPercentage = backtestResult.GrowthPercentage,
HodlPercentage = backtestResult.HodlPercentage, HodlPercentage = backtestResult.HodlPercentage,
OutperformanceVsHodl = backtestResult.GrowthPercentage - backtestResult.HodlPercentage, OutperformanceVsHodl = backtestResult.GrowthPercentage - backtestResult.HodlPercentage,
MaxDrawdown = (double)(backtestResult.Statistics?.MaxDrawdown ?? 0), MaxDrawdown = (double)(backtestResult.MaxDrawdown ?? 0),
TotalTrades = backtestResult.Positions?.Count ?? 0, SharpeRatio = (double)(backtestResult.SharpeRatio ?? 0),
SharpeRatio = (double)(backtestResult.Statistics?.SharpeRatio ?? 0),
ExecutionTime = timer.Elapsed.TotalSeconds, ExecutionTime = timer.Elapsed.TotalSeconds,
StopLoss = standardMoneyManagement.StopLoss, StopLoss = standardMoneyManagement.StopLoss,
TakeProfit = standardMoneyManagement.TakeProfit, TakeProfit = standardMoneyManagement.TakeProfit,
Leverage = standardMoneyManagement.Leverage, Leverage = standardMoneyManagement.Leverage,
Score = BacktestScorer.CalculateTotalScore(scoringParams) Score = backtestResult.Score,
}; };
results.Add(scenarioResult); results.Add(scenarioResult);

View File

@@ -266,7 +266,8 @@ public class StatisticService : IStatisticService
await _statisticRepository.UpdateSpotlightOverviewAsync(overview); await _statisticRepository.UpdateSpotlightOverviewAsync(overview);
} }
private async Task<List<LightSignal>> GetSignals(Account account, Scenario scenario, Ticker ticker, Timeframe timeframe) private async Task<List<LightSignal>> GetSignals(Account account, Scenario scenario, Ticker ticker,
Timeframe timeframe)
{ {
try try
{ {
@@ -307,7 +308,8 @@ public class StatisticService : IStatisticService
// Note: LightBacktest doesn't contain signals data, so we return an empty list // Note: LightBacktest doesn't contain signals data, so we return an empty list
// The full signals data would need to be retrieved from the database using the backtest ID // The full signals data would need to be retrieved from the database using the backtest ID
_logger.LogWarning("GetSignals called but LightBacktest doesn't contain signals data. Returning empty list."); _logger.LogWarning(
"GetSignals called but LightBacktest doesn't contain signals data. Returning empty list.");
return new List<LightSignal>(); return new List<LightSignal>();
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -1,12 +1,9 @@
using Managing.Domain.Bots; using Managing.Domain.Bots;
using Managing.Domain.Workflows;
namespace Managing.Application.Abstractions namespace Managing.Application.Abstractions
{ {
public interface IBotFactory public interface IBotFactory
{ {
IBot CreateSimpleBot(string botName, Workflow workflow);
/// <summary> /// <summary>
/// Creates a trading bot using the unified TradingBot class /// Creates a trading bot using the unified TradingBot class
/// </summary> /// </summary>

View File

@@ -23,7 +23,8 @@ namespace Managing.Application.Abstractions
Task<bool> UpdateScenario(string name, List<string> strategies, int? loopbackPeriod); Task<bool> UpdateScenario(string name, List<string> strategies, int? loopbackPeriod);
Task<bool> UpdateStrategy(IndicatorType indicatorType, string name, int? period, int? fastPeriods, int? slowPeriods, Task<bool> UpdateStrategy(IndicatorType indicatorType, string name, int? period, int? fastPeriods,
int? slowPeriods,
int? signalPeriods, double? multiplier, int? stochPeriods, int? smoothPeriods, int? cyclePeriods); int? signalPeriods, double? multiplier, int? stochPeriods, int? smoothPeriods, int? cyclePeriods);
Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user); Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user);
@@ -49,9 +50,11 @@ namespace Managing.Application.Abstractions
Task<bool> DeleteScenariosByUser(User user); Task<bool> DeleteScenariosByUser(User user);
Task<bool> UpdateScenarioByUser(User user, string name, List<string> strategies, int? loopbackPeriod); Task<bool> UpdateScenarioByUser(User user, string name, List<string> strategies, int? loopbackPeriod);
Task<bool> UpdateIndicatorByUser(User user, IndicatorType indicatorType, string name, int? period, int? fastPeriods, Task<bool> UpdateIndicatorByUser(User user, IndicatorType indicatorType, string name, int? period,
int? fastPeriods,
int? slowPeriods, int? signalPeriods, double? multiplier, int? stochPeriods, int? smoothPeriods, int? slowPeriods, int? signalPeriods, double? multiplier, int? stochPeriods, int? smoothPeriods,
int? cyclePeriods); int? cyclePeriods);
Task<Scenario> GetScenarioByNameAndUserAsync(string scenarioName, User user); Task<Scenario> GetScenarioByNameAndUserAsync(string scenarioName, User user);
} }
} }

View File

@@ -9,7 +9,6 @@ using Managing.Domain.Bots;
using Managing.Domain.Candles; using Managing.Domain.Candles;
using Managing.Domain.Scenarios; using Managing.Domain.Scenarios;
using Managing.Domain.Users; using Managing.Domain.Users;
using Managing.Domain.Workflows;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using static Managing.Common.Enums; using static Managing.Common.Enums;
@@ -54,19 +53,6 @@ namespace Managing.Application.Backtesting
_grainFactory = grainFactory; _grainFactory = grainFactory;
} }
public Backtest RunSimpleBotBacktest(Workflow workflow, bool save = false)
{
var simplebot = _botFactory.CreateSimpleBot("scenario", workflow);
Backtest result = null;
if (save && result != null)
{
// Simple bot backtest not implemented yet, would need user
// _backtestRepository.InsertBacktestForUser(null, result);
}
return result;
}
/// <summary> /// <summary>
/// Runs a trading bot backtest with the specified configuration and date range. /// Runs a trading bot backtest with the specified configuration and date range.
/// Automatically handles different bot types based on config.BotType. /// Automatically handles different bot types based on config.BotType.
@@ -80,7 +66,7 @@ namespace Managing.Application.Backtesting
/// <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> /// <param name="metadata">Additional metadata to associate with this backtest (optional)</param>
/// <returns>The lightweight backtest results</returns> /// <returns>The lightweight backtest results</returns>
public async Task<LightBacktest> RunTradingBotBacktest( public async Task<LightBacktestResponse> RunTradingBotBacktest(
TradingBotConfig config, TradingBotConfig config,
DateTime startDate, DateTime startDate,
DateTime endDate, DateTime endDate,
@@ -156,7 +142,7 @@ namespace Managing.Application.Backtesting
/// <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> /// <param name="metadata">Additional metadata to associate with this backtest (optional)</param>
/// <returns>The lightweight backtest results</returns> /// <returns>The lightweight backtest results</returns>
public async Task<LightBacktest> RunTradingBotBacktest( public async Task<LightBacktestResponse> RunTradingBotBacktest(
TradingBotConfig config, TradingBotConfig config,
List<Candle> candles, List<Candle> candles,
User user = null, User user = null,
@@ -170,7 +156,7 @@ namespace Managing.Application.Backtesting
/// <summary> /// <summary>
/// Core backtesting logic - handles the actual backtest execution with pre-loaded candles /// Core backtesting logic - handles the actual backtest execution with pre-loaded candles
/// </summary> /// </summary>
private async Task<LightBacktest> RunBacktestWithCandles( private async Task<LightBacktestResponse> RunBacktestWithCandles(
TradingBotConfig config, TradingBotConfig config,
List<Candle> candles, List<Candle> candles,
User user = null, User user = null,

View File

@@ -2,7 +2,6 @@
using Managing.Application.Abstractions.Services; using Managing.Application.Abstractions.Services;
using Managing.Application.ManageBot; using Managing.Application.ManageBot;
using Managing.Domain.Bots; using Managing.Domain.Bots;
using Managing.Domain.Workflows;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Managing.Application.Bots.Base namespace Managing.Application.Bots.Base
@@ -35,11 +34,6 @@ namespace Managing.Application.Bots.Base
_backupBotService = backupBotService; _backupBotService = backupBotService;
} }
IBot IBotFactory.CreateSimpleBot(string botName, Workflow workflow)
{
return new SimpleBot(botName, _tradingBotLogger, workflow, _botService, _backupBotService);
}
public async Task<ITradingBot> CreateTradingBot(TradingBotConfig config) public async Task<ITradingBot> CreateTradingBot(TradingBotConfig config)
{ {
// Delegate to BotService which handles scenario loading properly // Delegate to BotService which handles scenario loading properly

View File

@@ -146,7 +146,8 @@ namespace Managing.Application.Scenarios
return scenarios.Where(s => s.User?.Name == user.Name); return scenarios.Where(s => s.User?.Name == user.Name);
} }
public async Task<Scenario> CreateScenarioForUser(User user, string name, List<string> strategies, int? loopbackPeriod = 1) public async Task<Scenario> CreateScenarioForUser(User user, string name, List<string> strategies,
int? loopbackPeriod = 1)
{ {
var scenario = new Scenario(name, loopbackPeriod ?? 1) var scenario = new Scenario(name, loopbackPeriod ?? 1)
{ {
@@ -193,6 +194,7 @@ namespace Managing.Application.Scenarios
{ {
await _tradingService.DeleteScenarioAsync(scenario.Name); await _tradingService.DeleteScenarioAsync(scenario.Name);
} }
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@@ -211,6 +213,7 @@ namespace Managing.Application.Scenarios
{ {
await _tradingService.DeleteScenarioAsync(scenario.Name); await _tradingService.DeleteScenarioAsync(scenario.Name);
} }
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@@ -226,7 +229,8 @@ namespace Managing.Application.Scenarios
return scenario != null && scenario.User?.Name == user.Name ? scenario : null; return scenario != null && scenario.User?.Name == user.Name ? scenario : null;
} }
public async Task<Indicator> CreateIndicatorForUser(User user, IndicatorType type, string name, int? period = null, public async Task<Indicator> CreateIndicatorForUser(User user, IndicatorType type, string name,
int? period = null,
int? fastPeriods = null, int? slowPeriods = null, int? signalPeriods = null, int? fastPeriods = null, int? slowPeriods = null, int? signalPeriods = null,
double? multiplier = null, int? stochPeriods = null, int? smoothPeriods = null, double? multiplier = null, int? stochPeriods = null, int? smoothPeriods = null,
int? cyclePeriods = null) int? cyclePeriods = null)
@@ -253,6 +257,7 @@ namespace Managing.Application.Scenarios
{ {
await _tradingService.DeleteStrategyAsync(strategy.Name); await _tradingService.DeleteStrategyAsync(strategy.Name);
} }
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@@ -262,7 +267,8 @@ namespace Managing.Application.Scenarios
} }
} }
public async Task<bool> UpdateScenarioByUser(User user, string name, List<string> strategies, int? loopbackPeriod) public async Task<bool> UpdateScenarioByUser(User user, string name, List<string> strategies,
int? loopbackPeriod)
{ {
var scenario = await _tradingService.GetScenarioByNameAsync(name); var scenario = await _tradingService.GetScenarioByNameAsync(name);
if (scenario == null || scenario.User?.Name != user.Name) if (scenario == null || scenario.User?.Name != user.Name)