Remove candle from backtest return + fix message when good backtest

This commit is contained in:
2025-11-14 20:49:02 +07:00
parent b4005a2d1e
commit 6d661f459e
7 changed files with 30 additions and 69 deletions

View File

@@ -383,8 +383,7 @@ public class BacktestExecutor
var finalRequestId = requestId != null ? Guid.Parse(requestId) : Guid.NewGuid(); var finalRequestId = requestId != null ? Guid.Parse(requestId) : Guid.NewGuid();
// Create backtest result with conditional candles and indicators values // Create backtest result with conditional candles and indicators values
var result = new Backtest(config, tradingBot.Positions, tradingBot.Signals, var result = new Backtest(config, tradingBot.Positions, tradingBot.Signals)
withCandles ? candles : new HashSet<Candle>())
{ {
FinalPnl = realizedPnl, // Realized PnL before fees FinalPnl = realizedPnl, // Realized PnL before fees
WinRate = winRate, WinRate = winRate,
@@ -485,7 +484,9 @@ public class BacktestExecutor
string.Join(", ", bottlenecks)); string.Join(", ", bottlenecks));
} }
_logger.LogInformation("🎯 Backtest completed successfully - RequestId: {RequestId} - Score: {Score} - Realized PnL: {RealizedPnl} - Net PnL: {NetPnl} - Fees: {Fees}", finalRequestId, result.Score, result.FinalPnl, result.NetPnl, result.Fees); _logger.LogInformation(
"🎯 Backtest completed successfully - RequestId: {RequestId} - Score: {Score} - Realized PnL: {RealizedPnl} - Net PnL: {NetPnl} - Fees: {Fees}",
finalRequestId, result.Score, result.FinalPnl, result.NetPnl, result.Fees);
// Convert Backtest to LightBacktest // Convert Backtest to LightBacktest
return ConvertToLightBacktest(result); return ConvertToLightBacktest(result);

View File

@@ -4,7 +4,6 @@ using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services; using Managing.Application.Abstractions.Services;
using Managing.Application.Abstractions.Shared; using Managing.Application.Abstractions.Shared;
using Managing.Application.Hubs; using Managing.Application.Hubs;
using Managing.Domain.Accounts;
using Managing.Domain.Backtests; using Managing.Domain.Backtests;
using Managing.Domain.Bots; using Managing.Domain.Bots;
using Managing.Domain.Candles; using Managing.Domain.Candles;
@@ -136,7 +135,8 @@ namespace Managing.Application.Backtests
var startDate = candles.Min(c => c.Date); var startDate = candles.Min(c => c.Date);
var endDate = candles.Max(c => c.Date); var endDate = candles.Max(c => c.Date);
return await RunTradingBotBacktest(config, startDate, endDate, user, false, withCandles, requestId, metadata); return await RunTradingBotBacktest(config, startDate, endDate, user, false, withCandles, requestId,
metadata);
} }
public async Task<bool> DeleteBacktestAsync(string id) public async Task<bool> DeleteBacktestAsync(string id)
@@ -215,31 +215,6 @@ namespace Managing.Application.Backtests
if (backtest == null) if (backtest == null)
return null; return null;
if (backtest.Candles == null || backtest.Candles.Count == 0 || backtest.Candles.Count < 10)
{
try
{
var account = new Account
{ Name = backtest.Config.AccountName, Exchange = TradingExchanges.Evm };
var candles = await _exchangeService.GetCandlesInflux(
account.Exchange,
backtest.Config.Ticker,
backtest.StartDate,
backtest.Config.Timeframe,
backtest.EndDate);
if (candles != null && candles.Count > 0)
{
backtest.Candles = candles;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to retrieve candles for backtest {Id}", id);
}
}
return backtest; return backtest;
} }
@@ -431,7 +406,9 @@ namespace Managing.Application.Backtests
} }
// Get the first account for the user // Get the first account for the user
var accounts = await _accountService.GetAccountsByUserAsync(bundleRequest.User, hideSecrets: true, getBalance: false); var accounts =
await _accountService.GetAccountsByUserAsync(bundleRequest.User, hideSecrets: true,
getBalance: false);
var firstAccount = accounts.FirstOrDefault(); var firstAccount = accounts.FirstOrDefault();
if (firstAccount == null) if (firstAccount == null)
@@ -573,15 +550,17 @@ namespace Managing.Application.Backtests
return (bundleRequests, totalCount); return (bundleRequests, totalCount);
} }
public async Task<(IEnumerable<BundleBacktestRequest> BundleRequests, int TotalCount)> GetBundleBacktestRequestsPaginatedAsync( public async Task<(IEnumerable<BundleBacktestRequest> BundleRequests, int TotalCount)>
int page, GetBundleBacktestRequestsPaginatedAsync(
int pageSize, int page,
BundleBacktestRequestSortableColumn sortBy = BundleBacktestRequestSortableColumn.CreatedAt, int pageSize,
string sortOrder = "desc", BundleBacktestRequestSortableColumn sortBy = BundleBacktestRequestSortableColumn.CreatedAt,
BundleBacktestRequestsFilter? filter = null) string sortOrder = "desc",
BundleBacktestRequestsFilter? filter = null)
{ {
var (bundleRequests, totalCount) = var (bundleRequests, totalCount) =
await _backtestRepository.GetBundleBacktestRequestsPaginatedAsync(page, pageSize, sortBy, sortOrder, filter); await _backtestRepository.GetBundleBacktestRequestsPaginatedAsync(page, pageSize, sortBy, sortOrder,
filter);
return (bundleRequests, totalCount); return (bundleRequests, totalCount);
} }

View File

@@ -164,8 +164,7 @@ public class BacktestTradingBotGrain : Grain, IBacktestTradingBotGrain
var finalRequestId = requestId != null ? Guid.Parse(requestId) : Guid.NewGuid(); var finalRequestId = requestId != null ? Guid.Parse(requestId) : Guid.NewGuid();
// Create backtest result with conditional candles and indicators values // Create backtest result with conditional candles and indicators values
var result = new Backtest(config, tradingBot.Positions, tradingBot.Signals, var result = new Backtest(config, tradingBot.Positions, tradingBot.Signals)
withCandles ? candles : new HashSet<Candle>())
{ {
FinalPnl = finalPnl, FinalPnl = finalPnl,
WinRate = winRate, WinRate = winRate,

View File

@@ -257,7 +257,7 @@ public class MessengerService : IMessengerService
var score = backtest.Score; var score = backtest.Score;
var winRate = backtest.WinRate; var winRate = backtest.WinRate;
var tradeCount = backtest.Positions?.Count ?? 0; var tradeCount = backtest.Positions?.Count ?? 0;
var finalPnl = backtest.FinalPnl; var netPnl = backtest.NetPnl;
var growthPercentage = backtest.GrowthPercentage; var growthPercentage = backtest.GrowthPercentage;
var maxDrawdown = backtest.Statistics?.MaxDrawdown ?? 0; var maxDrawdown = backtest.Statistics?.MaxDrawdown ?? 0;
var sharpeRatio = (backtest.Statistics?.SharpeRatio * 100) ?? 0; var sharpeRatio = (backtest.Statistics?.SharpeRatio * 100) ?? 0;
@@ -288,8 +288,8 @@ public class MessengerService : IMessengerService
$"🔍 Score Analysis: {backtest.ScoreMessage}\n" + $"🔍 Score Analysis: {backtest.ScoreMessage}\n" +
$"🏆 Win Rate: {winRate:F1}%\n" + $"🏆 Win Rate: {winRate:F1}%\n" +
$"📊 Total Trades: {tradeCount}\n" + $"📊 Total Trades: {tradeCount}\n" +
$"💰 Final PnL: ${finalPnl:F2}\n" + $"💰 Net PnL: ${netPnl:F2}\n" +
$"📈 Growth: {growthPercentage:F1}%\n" + $"📈 ROI: {growthPercentage:F1}%\n" +
$"📉 Max Drawdown: ${maxDrawdown:N}\n" + $"📉 Max Drawdown: ${maxDrawdown:N}\n" +
$"📊 Sharpe Ratio: {sharpeRatio:F2}\n\n" + $"📊 Sharpe Ratio: {sharpeRatio:F2}\n\n" +
$"🆔 Backtest ID: {backtest.Id}"; $"🆔 Backtest ID: {backtest.Id}";

View File

@@ -2,7 +2,6 @@
using System.ComponentModel.DataAnnotations; 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.Indicators; using Managing.Domain.Indicators;
using Managing.Domain.Trades; using Managing.Domain.Trades;
using Managing.Domain.Users; using Managing.Domain.Users;
@@ -14,26 +13,12 @@ public class Backtest
public Backtest( public Backtest(
TradingBotConfig config, TradingBotConfig config,
Dictionary<Guid, Position> positions, Dictionary<Guid, Position> positions,
Dictionary<string, LightSignal> signals, Dictionary<string, LightSignal> signals)
HashSet<Candle> candles = null)
{ {
Config = config; Config = config;
Positions = positions; Positions = positions;
Signals = signals; Signals = signals;
Candles = candles != null ? candles : new HashSet<Candle>();
WalletBalances = new List<KeyValuePair<DateTime, decimal>>(); WalletBalances = new List<KeyValuePair<DateTime, decimal>>();
// Initialize start and end dates if candles are provided
if (candles != null && candles.Count > 0)
{
StartDate = candles.Min(c => c.Date);
EndDate = candles.Max(c => c.Date);
}
else
{
StartDate = DateTime.UtcNow.AddDays(-30);
EndDate = DateTime.UtcNow;
}
} }
[Required] public string Id { get; set; } [Required] public string Id { get; set; }
@@ -44,7 +29,6 @@ public class Backtest
[Required] public TradingBotConfig Config { get; } [Required] public TradingBotConfig Config { get; }
[Required] public Dictionary<Guid, Position> Positions { get; } [Required] public Dictionary<Guid, Position> Positions { get; }
[Required] public Dictionary<string, LightSignal> Signals { get; } [Required] public Dictionary<string, LightSignal> Signals { get; }
[Required] public HashSet<Candle> Candles { get; set; }
[Required] public DateTime StartDate { get; set; } [Required] public DateTime StartDate { get; set; }
[Required] public DateTime EndDate { get; set; } [Required] public DateTime EndDate { get; set; }
[Required] public PerformanceMetrics Statistics { get; set; } [Required] public PerformanceMetrics Statistics { get; set; }

View File

@@ -4736,7 +4736,6 @@ export interface Backtest {
config: TradingBotConfig; config: TradingBotConfig;
positions: { [key: string]: Position; }; positions: { [key: string]: Position; };
signals: { [key: string]: LightSignal; }; signals: { [key: string]: LightSignal; };
candles: Candle[];
startDate: Date; startDate: Date;
endDate: Date; endDate: Date;
statistics: PerformanceMetrics; statistics: PerformanceMetrics;

View File

@@ -298,7 +298,6 @@ export interface Backtest {
config: TradingBotConfig; config: TradingBotConfig;
positions: { [key: string]: Position; }; positions: { [key: string]: Position; };
signals: { [key: string]: LightSignal; }; signals: { [key: string]: LightSignal; };
candles: Candle[];
startDate: Date; startDate: Date;
endDate: Date; endDate: Date;
statistics: PerformanceMetrics; statistics: PerformanceMetrics;