Implement profitable bots filtering in BotController and DataController

- Added IConfiguration dependency to BotController for accessing environment variables.
- Updated GetBotsPaginatedAsync method in BotService and IBotService to include a flag for filtering profitable bots.
- Modified DataController to utilize the new filtering option for agent summaries and bot retrieval.
- Enhanced PostgreSqlBotRepository to apply filtering based on profitability when querying bots.
This commit is contained in:
2025-11-22 14:02:29 +07:00
parent e69dd43ace
commit 2a354bd7d2
6 changed files with 42 additions and 18 deletions

View File

@@ -20,6 +20,7 @@ using MediatR;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using static Managing.Common.Enums; using static Managing.Common.Enums;
namespace Managing.Api.Controllers; namespace Managing.Api.Controllers;
@@ -43,6 +44,7 @@ public class BotController : BaseController
private readonly IMoneyManagementService _moneyManagementService; private readonly IMoneyManagementService _moneyManagementService;
private readonly IServiceScopeFactory _scopeFactory; private readonly IServiceScopeFactory _scopeFactory;
private readonly IAdminConfigurationService _adminService; private readonly IAdminConfigurationService _adminService;
private readonly IConfiguration _configuration;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BotController"/> class. /// Initializes a new instance of the <see cref="BotController"/> class.
@@ -56,10 +58,11 @@ public class BotController : BaseController
/// <param name="botService"></param> /// <param name="botService"></param>
/// <param name="userService"></param> /// <param name="userService"></param>
/// <param name="scopeFactory"></param> /// <param name="scopeFactory"></param>
/// <param name="configuration">Configuration for accessing environment variables.</param>
public BotController(ILogger<BotController> logger, IMediator mediator, IHubContext<BotHub> hubContext, public BotController(ILogger<BotController> logger, IMediator mediator, IHubContext<BotHub> hubContext,
IBacktester backtester, IBotService botService, IUserService userService, IBacktester backtester, IBotService botService, IUserService userService,
IAccountService accountService, IMoneyManagementService moneyManagementService, IAccountService accountService, IMoneyManagementService moneyManagementService,
IServiceScopeFactory scopeFactory, IAdminConfigurationService adminService) : base(userService) IServiceScopeFactory scopeFactory, IAdminConfigurationService adminService, IConfiguration configuration) : base(userService)
{ {
_logger = logger; _logger = logger;
_mediator = mediator; _mediator = mediator;
@@ -70,6 +73,7 @@ public class BotController : BaseController
_moneyManagementService = moneyManagementService; _moneyManagementService = moneyManagementService;
_scopeFactory = scopeFactory; _scopeFactory = scopeFactory;
_adminService = adminService; _adminService = adminService;
_configuration = configuration;
} }
/// <summary> /// <summary>
@@ -431,6 +435,9 @@ public class BotController : BaseController
pageSize = Math.Min(Math.Max(pageSize, 1), 100); pageSize = Math.Min(Math.Max(pageSize, 1), 100);
} }
// Check environment variable for filtering profitable bots only
var showOnlyProfitable = _configuration.GetValue<bool>("showOnlyProfitable", false);
// Get paginated bots from service // Get paginated bots from service
var (bots, totalCount) = await _botService.GetBotsPaginatedAsync( var (bots, totalCount) = await _botService.GetBotsPaginatedAsync(
pageNumber, pageNumber,
@@ -440,7 +447,8 @@ public class BotController : BaseController
ticker, ticker,
agentName, agentName,
sortBy, sortBy,
sortDirection); sortDirection,
showOnlyProfitable);
// Map to response objects // Map to response objects
var tradingBotResponses = MapBotsToTradingBotResponse(bots); var tradingBotResponses = MapBotsToTradingBotResponse(bots);

View File

@@ -711,10 +711,10 @@ public class DataController : ControllerBase
} }
// Check environment variable for filtering profitable agents only // Check environment variable for filtering profitable agents only
var showOnlyProfitableAgent = _configuration.GetValue<bool>("showOnlyProfitableAgent", false); var showOnlyProfitable = _configuration.GetValue<bool>("showOnlyProfitable", false);
// Get paginated results from database // Get paginated results from database
var command = new GetPaginatedAgentSummariesCommand(page, pageSize, sortBy, sortOrder, agentNamesList, showOnlyProfitableAgent); var command = new GetPaginatedAgentSummariesCommand(page, pageSize, sortBy, sortOrder, agentNamesList, showOnlyProfitable);
var result = await _mediator.Send(command); var result = await _mediator.Send(command);
var agentSummaries = result.Results; var agentSummaries = result.Results;
var totalCount = result.TotalCount; var totalCount = result.TotalCount;
@@ -928,6 +928,9 @@ public class DataController : ControllerBase
try try
{ {
// Check environment variable for filtering profitable strategies only
var showOnlyProfitable = _configuration.GetValue<bool>("showOnlyProfitable", false);
// Get paginated bots excluding Saved status // Get paginated bots excluding Saved status
var (bots, totalCount) = await _botService.GetBotsPaginatedAsync( var (bots, totalCount) = await _botService.GetBotsPaginatedAsync(
pageNumber, pageNumber,
@@ -937,7 +940,8 @@ public class DataController : ControllerBase
ticker, ticker,
agentName, agentName,
sortBy, sortBy,
sortDirection); sortDirection,
showOnlyProfitable);
// Filter out Saved status bots // Filter out Saved status bots
var filteredBots = bots.Where(bot => bot.Status != BotStatus.Saved).ToList(); var filteredBots = bots.Where(bot => bot.Status != BotStatus.Saved).ToList();

View File

@@ -22,12 +22,12 @@ public interface IBotRepository
/// <param name="pageNumber">Page number (1-based)</param> /// <param name="pageNumber">Page number (1-based)</param>
/// <param name="pageSize">Number of items per page</param> /// <param name="pageSize">Number of items per page</param>
/// <param name="status">Filter by status (optional)</param> /// <param name="status">Filter by status (optional)</param>
/// <param name="userId">Filter by user ID (optional)</param>
/// <param name="name">Filter by name (partial match, case-insensitive)</param> /// <param name="name">Filter by name (partial match, case-insensitive)</param>
/// <param name="ticker">Filter by ticker (partial match, case-insensitive)</param> /// <param name="ticker">Filter by ticker (partial match, case-insensitive)</param>
/// <param name="agentName">Filter by agent name (partial match, case-insensitive)</param> /// <param name="agentName">Filter by agent name (partial match, case-insensitive)</param>
/// <param name="sortBy">Sort field</param> /// <param name="sortBy">Sort field</param>
/// <param name="sortDirection">Sort direction ("Asc" or "Desc")</param> /// <param name="sortDirection">Sort direction ("Asc" or "Desc")</param>
/// <param name="showOnlyProfitable">Whether to show only profitable bots (ROI > 0)</param>
/// <returns>Tuple containing the bots for the current page and total count</returns> /// <returns>Tuple containing the bots for the current page and total count</returns>
Task<(IEnumerable<Bot> Bots, int TotalCount)> GetBotsPaginatedAsync( Task<(IEnumerable<Bot> Bots, int TotalCount)> GetBotsPaginatedAsync(
int pageNumber, int pageNumber,
@@ -37,7 +37,8 @@ public interface IBotRepository
string? ticker = null, string? ticker = null,
string? agentName = null, string? agentName = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate, BotSortableColumn sortBy = BotSortableColumn.CreateDate,
string sortDirection = "Desc"); string sortDirection = "Desc",
bool showOnlyProfitable = false);
/// <summary> /// <summary>
/// Gets the top performing bots by PnL from the specified statuses /// Gets the top performing bots by PnL from the specified statuses

View File

@@ -48,6 +48,7 @@ public interface IBotService
/// <param name="agentName">Filter by agent name (partial match, case-insensitive)</param> /// <param name="agentName">Filter by agent name (partial match, case-insensitive)</param>
/// <param name="sortBy">Sort field</param> /// <param name="sortBy">Sort field</param>
/// <param name="sortDirection">Sort direction ("Asc" or "Desc")</param> /// <param name="sortDirection">Sort direction ("Asc" or "Desc")</param>
/// <param name="showOnlyProfitable">Whether to show only profitable bots (ROI > 0)</param>
/// <returns>Tuple containing the bots for the current page and total count</returns> /// <returns>Tuple containing the bots for the current page and total count</returns>
Task<(IEnumerable<Bot> Bots, int TotalCount)> GetBotsPaginatedAsync( Task<(IEnumerable<Bot> Bots, int TotalCount)> GetBotsPaginatedAsync(
int pageNumber, int pageNumber,
@@ -57,7 +58,8 @@ public interface IBotService
string? ticker = null, string? ticker = null,
string? agentName = null, string? agentName = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate, BotSortableColumn sortBy = BotSortableColumn.CreateDate,
string sortDirection = "Desc"); string sortDirection = "Desc",
bool showOnlyProfitable = false);
/// <summary> /// <summary>
/// Checks USDC and ETH balances for EVM/GMX V2 accounts /// Checks USDC and ETH balances for EVM/GMX V2 accounts

View File

@@ -460,7 +460,8 @@ namespace Managing.Application.ManageBot
string? ticker = null, string? ticker = null,
string? agentName = null, string? agentName = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate, BotSortableColumn sortBy = BotSortableColumn.CreateDate,
string sortDirection = "Desc") string sortDirection = "Desc",
bool showOnlyProfitable = false)
{ {
return await ServiceScopeHelpers.WithScopedService<IBotRepository, (IEnumerable<Bot> Bots, int TotalCount)>( return await ServiceScopeHelpers.WithScopedService<IBotRepository, (IEnumerable<Bot> Bots, int TotalCount)>(
_scopeFactory, _scopeFactory,
@@ -474,7 +475,8 @@ namespace Managing.Application.ManageBot
ticker, ticker,
agentName, agentName,
sortBy, sortBy,
sortDirection); sortDirection,
showOnlyProfitable);
}); });
} }

View File

@@ -204,7 +204,8 @@ public class PostgreSqlBotRepository : IBotRepository
string? ticker = null, string? ticker = null,
string? agentName = null, string? agentName = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate, BotSortableColumn sortBy = BotSortableColumn.CreateDate,
string sortDirection = "Desc") string sortDirection = "Desc",
bool showOnlyProfitable = false)
{ {
// Build the query with filters // Build the query with filters
var query = _context.Bots var query = _context.Bots
@@ -234,6 +235,12 @@ public class PostgreSqlBotRepository : IBotRepository
query = query.Where(b => b.User != null && EF.Functions.ILike(b.User.AgentName, $"%{agentName}%")); query = query.Where(b => b.User != null && EF.Functions.ILike(b.User.AgentName, $"%{agentName}%"));
} }
// Apply profitable bots filtering if specified
if (showOnlyProfitable)
{
query = query.Where(b => b.Roi > 0);
}
// Get total count before applying pagination // Get total count before applying pagination
var totalCount = await query.CountAsync().ConfigureAwait(false); var totalCount = await query.CountAsync().ConfigureAwait(false);