Add BacktestCount

This commit is contained in:
2025-10-01 13:01:03 +07:00
parent 3e680ab815
commit 06850b57c4
14 changed files with 1571 additions and 9 deletions

View File

@@ -610,6 +610,7 @@ public class DataController : ControllerBase
TotalVolume = agentSummary.TotalVolume,
TotalBalance = agentSummary.TotalBalance,
TotalFees = agentSummary.TotalFees,
BacktestCount = agentSummary.BacktestCount,
};
agentSummaryViewModels.Add(agentSummaryViewModel);

View File

@@ -57,6 +57,11 @@ namespace Managing.Api.Models.Responses
/// Total fees paid by this agent across all positions
/// </summary>
public decimal TotalFees { get; set; }
/// <summary>
/// Total number of backtests run by this agent
/// </summary>
public int BacktestCount { get; set; }
}
/// <summary>

View File

@@ -41,4 +41,10 @@ public interface IAgentSummaryRepository
/// </summary>
/// <returns>Total number of agents</returns>
Task<int> GetTotalAgentCount();
/// <summary>
/// Increments the backtest count for a specific user's agent summary
/// </summary>
/// <param name="userId">The user ID</param>
Task IncrementBacktestCountAsync(int userId);
}

View File

@@ -27,4 +27,10 @@ public interface IAgentService
/// </summary>
/// <returns>Total number of agents</returns>
Task<int> GetTotalAgentCount();
/// <summary>
/// Increments the backtest count for a specific user's agent summary
/// </summary>
/// <param name="userId">The user ID</param>
Task IncrementBacktestCountAsync(int userId);
}

View File

@@ -40,8 +40,9 @@ namespace Managing.Application.Tests
var tradingBotLogger = TradingBaseTests.CreateTradingBotLogger();
var backtestLogger = TradingBaseTests.CreateBacktesterLogger();
var botService = new Mock<IBotService>().Object;
var agentService = new Mock<IAgentService>().Object;
_backtester = new Backtester(_exchangeService, backtestRepository, backtestLogger,
scenarioService, _accountService.Object, messengerService, kaigenService, hubContext, null);
scenarioService, _accountService.Object, messengerService, kaigenService, hubContext, null, agentService);
_elapsedTimes = new List<double>();
// Initialize cross-platform file paths

View File

@@ -150,4 +150,19 @@ public class AgentService : IAgentService
{
return await _agentSummaryRepository.GetTotalAgentCount();
}
public async Task IncrementBacktestCountAsync(int userId)
{
try
{
await _agentSummaryRepository.IncrementBacktestCountAsync(userId);
_logger.LogInformation("Backtest count incremented for user {UserId}", userId);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error incrementing backtest count for user {UserId}", userId);
throw;
}
}
}

View File

@@ -27,6 +27,7 @@ namespace Managing.Application.Backtests
private readonly IKaigenService _kaigenService;
private readonly IHubContext<BacktestHub> _hubContext;
private readonly IGrainFactory _grainFactory;
private readonly IAgentService _agentService;
public Backtester(
IExchangeService exchangeService,
@@ -37,7 +38,8 @@ namespace Managing.Application.Backtests
IMessengerService messengerService,
IKaigenService kaigenService,
IHubContext<BacktestHub> hubContext,
IGrainFactory grainFactory)
IGrainFactory grainFactory,
IAgentService agentService)
{
_exchangeService = exchangeService;
_backtestRepository = backtestRepository;
@@ -48,6 +50,7 @@ namespace Managing.Application.Backtests
_kaigenService = kaigenService;
_hubContext = hubContext;
_grainFactory = grainFactory;
_agentService = agentService;
}
/// <summary>
@@ -187,14 +190,25 @@ namespace Managing.Application.Backtests
// Create Orleans grain for backtesting
var backtestGrain = _grainFactory.GetGrain<IBacktestTradingBotGrain>(Guid.NewGuid());
// Run the backtest using the Orleans grain and return LightBacktest directly
return await backtestGrain.RunBacktestAsync(cleanConfig, candles, user, save, withCandles, requestId,
// Run the backtest using the Orleans grain
var result = await backtestGrain.RunBacktestAsync(cleanConfig, candles, user, save, withCandles, requestId,
metadata);
}
private async Task<Account> GetAccountFromConfig(TradingBotConfig config)
{
return await _accountService.GetAccountByAccountName(config.AccountName, false, false);
// Increment backtest count for the user if user is provided
if (user != null)
{
try
{
await _agentService.IncrementBacktestCountAsync(user.Id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to increment backtest count for user {UserId}", user.Id);
// Don't throw here as the backtest was successful, just log the error
}
}
return result;
}
private async Task<HashSet<Candle>> GetCandles(Ticker ticker, Timeframe timeframe,

View File

@@ -53,4 +53,7 @@ public class AgentSummary
[Id(15)]
public decimal NetPnL { get; set; }
[Id(16)]
public int BacktestCount { get; set; }
}

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Managing.Infrastructure.Databases.Migrations
{
/// <inheritdoc />
public partial class AddBacktestCountToAgentSummary : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "BacktestCount",
table: "AgentSummaries",
type: "integer",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "BacktestCount",
table: "AgentSummaries");
}
}
}

View File

@@ -86,6 +86,9 @@ namespace Managing.Infrastructure.Databases.Migrations
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<int>("BacktestCount")
.HasColumnType("integer");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");

View File

@@ -251,7 +251,8 @@ public class AgentSummaryRepository : IAgentSummaryRepository
ActiveStrategiesCount = domain.ActiveStrategiesCount,
TotalVolume = domain.TotalVolume,
TotalBalance = domain.TotalBalance,
TotalFees = domain.TotalFees
TotalFees = domain.TotalFees,
BacktestCount = domain.BacktestCount
};
}
@@ -269,6 +270,7 @@ public class AgentSummaryRepository : IAgentSummaryRepository
entity.TotalVolume = domain.TotalVolume;
entity.TotalBalance = domain.TotalBalance;
entity.TotalFees = domain.TotalFees;
entity.BacktestCount = domain.BacktestCount;
}
private static AgentSummary MapToDomain(AgentSummaryEntity entity)
@@ -290,6 +292,7 @@ public class AgentSummaryRepository : IAgentSummaryRepository
TotalVolume = entity.TotalVolume,
TotalBalance = entity.TotalBalance,
TotalFees = entity.TotalFees,
BacktestCount = entity.BacktestCount,
User = PostgreSqlMappers.Map(entity.User)
};
}
@@ -329,4 +332,26 @@ public class AgentSummaryRepository : IAgentSummaryRepository
{
return await _context.AgentSummaries.CountAsync();
}
public async Task IncrementBacktestCountAsync(int userId)
{
var entity = await _context.AgentSummaries
.FirstOrDefaultAsync(a => a.UserId == userId);
if (entity != null)
{
entity.BacktestCount++;
entity.UpdatedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
_logger.LogInformation("Backtest count incremented for user {UserId} to {BacktestCount}",
userId, entity.BacktestCount);
}
else
{
_logger.LogWarning("No AgentSummary found for user {UserId} when trying to increment backtest count",
userId);
}
}
}

View File

@@ -17,6 +17,7 @@ public class AgentSummaryEntity
public decimal TotalBalance { get; set; }
public decimal TotalFees { get; set; }
public decimal NetPnL { get; set; }
public int BacktestCount { get; set; }
// Navigation property
public UserEntity User { get; set; }

View File

@@ -548,6 +548,7 @@ public class ManagingDbContext : DbContext
entity.Property(e => e.ActiveStrategiesCount).IsRequired();
entity.Property(e => e.TotalVolume).HasPrecision(18, 8);
entity.Property(e => e.TotalBalance).HasPrecision(18, 8);
entity.Property(e => e.BacktestCount).IsRequired();
// Create indexes for common queries
entity.HasIndex(e => e.UserId).IsUnique();