Refactor pagination sorting parameters across multiple controllers and services to use the new SortDirection enum; update related API models and TypeScript definitions for consistency. Fix minor documentation and naming inconsistencies in the Bot and Data controllers.

This commit is contained in:
2025-12-14 20:23:26 +07:00
parent cb6b52ef4a
commit bcb00b9a86
30 changed files with 251 additions and 202 deletions

View File

@@ -538,7 +538,7 @@ public class BacktestController : BaseController
if (request.Config.Scenario != null)
{
// Convert ScenarioRequest to Scenario domain object
scenario = new Scenario(request.Config.Scenario.Name, request.Config.Scenario.LoopbackPeriod)
scenario = new Scenario(request.Config.Scenario.Name, request.Config.Scenario.LookbackPeriod)
{
User = user
};

View File

@@ -1,4 +1,4 @@
using Managing.Api.Models.Requests;
using Managing.Api.Models.Requests;
using Managing.Api.Models.Responses;
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services;
@@ -430,7 +430,7 @@ public class BotController : BaseController
/// <param name="ticker">Filter by ticker (partial match, case-insensitive). If null, no ticker filtering is applied.</param>
/// <param name="agentName">Filter by agent name (partial match, case-insensitive). If null, no agent name filtering is applied.</param>
/// <param name="sortBy">Sort field. Valid values: "Name", "Ticker", "Status", "CreateDate", "StartupTime", "Pnl", "WinRate", "AgentName". Default is "CreateDate".</param>
/// <param name="sortDirection">Sort direction. Default is "Desc".</param>
/// <param name="sortDirection">Sort direction. Default is Desc.</param>
/// <returns>A paginated response containing trading bots</returns>
[HttpGet]
[Route("Paginated")]
@@ -442,7 +442,7 @@ public class BotController : BaseController
string? ticker = null,
string? agentName = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
string sortDirection = "Desc")
SortDirection sortDirection = SortDirection.Desc)
{
try
{
@@ -770,7 +770,7 @@ public class BotController : BaseController
if (request.Config.Scenario != null)
{
// Convert ScenarioRequest to Scenario domain object
scenarioForUpdate = new Scenario(request.Config.Scenario.Name, request.Config.Scenario.LoopbackPeriod)
scenarioForUpdate = new Scenario(request.Config.Scenario.Name, request.Config.Scenario.LookbackPeriod)
{
User = user
};
@@ -931,7 +931,7 @@ public class BotController : BaseController
if (request.Config.Scenario != null)
{
// Convert ScenarioRequest to Scenario domain object
scenario = new Scenario(request.Config.Scenario.Name, request.Config.Scenario.LoopbackPeriod)
scenario = new Scenario(request.Config.Scenario.Name, request.Config.Scenario.LookbackPeriod)
{
User = user
};

View File

@@ -1,4 +1,4 @@
using Managing.Api.Models.Requests;
using Managing.Api.Models.Requests;
using Managing.Api.Models.Responses;
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Grains;
@@ -561,7 +561,7 @@ public class DataController : ControllerBase
// Use caching for position data in UI context (not critical trading operations)
var cacheKey = $"positions_{strategy.Identifier}";
var cachedPositions = _cacheService.GetValue<List<Position>>(cacheKey);
List<Position> positions;
if (cachedPositions != null)
{
@@ -571,7 +571,7 @@ public class DataController : ControllerBase
{
// Fetch positions associated with this bot using the provided trading service
positions = (await tradingService.GetPositionsByInitiatorIdentifierAsync(strategy.Identifier)).ToList();
// Cache positions for 2 minutes for UI display purposes
_cacheService.SaveValue(cacheKey, positions, TimeSpan.FromMinutes(2));
}
@@ -619,9 +619,9 @@ public class DataController : ControllerBase
NetPnL = strategy.NetPnL,
ROIPercentage = strategy.Roi,
Runtime = strategy.Status == BotStatus.Running ? strategy.LastStartTime : null,
LastStartTime = strategy.LastStartTime,
LastStopTime = strategy.LastStopTime,
AccumulatedRunTimeSeconds = strategy.AccumulatedRunTimeSeconds,
LastStartTime = strategy.LastStartTime,
LastStopTime = strategy.LastStopTime,
AccumulatedRunTimeSeconds = strategy.AccumulatedRunTimeSeconds,
TotalRuntimeSeconds = strategy.GetTotalRuntimeSeconds(),
WinRate = winRate,
TotalVolumeTraded = totalVolume,
@@ -715,7 +715,9 @@ public class DataController : ControllerBase
var showOnlyProfitable = _configuration.GetValue<bool>("showOnlyProfitable", false);
// Get paginated results from database
var command = new GetPaginatedAgentSummariesCommand(page, pageSize, sortBy, sortOrder, agentNamesList, showOnlyProfitable);
var command =
new GetPaginatedAgentSummariesCommand(page, pageSize, sortBy, sortOrder, agentNamesList,
showOnlyProfitable);
var result = await _mediator.Send(command);
var agentSummaries = result.Results;
var totalCount = result.TotalCount;
@@ -819,7 +821,7 @@ public class DataController : ControllerBase
/// <returns>A domain Scenario object.</returns>
private Scenario MapScenarioRequestToScenario(ScenarioRequest scenarioRequest)
{
var scenario = new Scenario(scenarioRequest.Name, scenarioRequest.LoopbackPeriod);
var scenario = new Scenario(scenarioRequest.Name, scenarioRequest.LookbackPeriod);
foreach (var indicatorRequest in scenarioRequest.Indicators)
{
@@ -907,7 +909,7 @@ public class DataController : ControllerBase
/// <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="sortBy">Sort field (defaults to CreateDate)</param>
/// <param name="sortDirection">Sort direction - "Asc" or "Desc" (defaults to "Desc")</param>
/// <param name="sortDirection">Sort direction - Asc or Desc (defaults to Desc)</param>
/// <returns>A paginated list of strategies excluding Saved status bots</returns>
[HttpGet("GetStrategiesPaginated")]
public async Task<ActionResult<PaginatedResponse<TradingBotResponse>>> GetStrategiesPaginated(
@@ -917,7 +919,7 @@ public class DataController : ControllerBase
string? ticker = null,
string? agentName = null,
BotSortableColumn sortBy = BotSortableColumn.CreateDate,
string sortDirection = "Desc")
SortDirection sortDirection = SortDirection.Desc)
{
// Validate pagination parameters
if (pageNumber < 1)
@@ -930,11 +932,6 @@ public class DataController : ControllerBase
return BadRequest("Page size must be between 1 and 100");
}
// Validate sort direction
if (sortDirection != "Asc" && sortDirection != "Desc")
{
return BadRequest("Sort direction must be 'Asc' or 'Desc'");
}
try
{

View File

@@ -191,7 +191,7 @@ public class ScenarioController : BaseController
return new ScenarioViewModel
{
Name = scenario.Name,
LoopbackPeriod = scenario.LoopbackPeriod,
LoopbackPeriod = scenario.LookbackPeriod,
UserName = scenario.User?.Name,
Indicators = scenario.Indicators?.Select(MapToIndicatorViewModel).ToList() ?? new List<IndicatorViewModel>()
};

View File

@@ -49,7 +49,7 @@ public class GetBotsPaginatedRequest
public BotSortableColumn SortBy { get; set; } = BotSortableColumn.CreateDate;
/// <summary>
/// Sort direction. Default is "Desc" (descending).
/// Sort direction. Default is Desc (descending).
/// </summary>
public string SortDirection { get; set; } = "Desc";
public SortDirection SortDirection { get; set; } = SortDirection.Desc;
}

View File

@@ -1,3 +1,4 @@
using System.ComponentModel.DataAnnotations;
using Managing.Common;
namespace Managing.Api.Models.Responses
@@ -10,41 +11,49 @@ namespace Managing.Api.Models.Responses
/// <summary>
/// Name of the deployed strategy
/// </summary>
[Required]
public string Name { get; set; }
/// <summary>
/// Current state of the strategy (RUNNING, STOPPED, UNUSED)
/// </summary>
[Required]
public Enums.BotStatus State { get; set; }
/// <summary>
/// Total profit or loss generated by the strategy in USD (gross, before fees)
/// </summary>
[Required]
public decimal PnL { get; set; }
/// <summary>
/// Net profit or loss generated by the strategy in USD (after fees)
/// </summary>
[Required]
public decimal NetPnL { get; set; }
/// <summary>
/// Return on investment percentage
/// </summary>
[Required]
public decimal ROIPercentage { get; set; }
/// <summary>
/// Date and time when the strategy was started (only present when running, for live ticker)
/// </summary>
[Required]
public DateTime? Runtime { get; set; }
/// <summary>
/// Total accumulated runtime in seconds (including current session if running)
/// </summary>
[Required]
public long TotalRuntimeSeconds { get; set; }
/// <summary>
/// Time when the current or last session started
/// </summary>
[Required]
public DateTime? LastStartTime { get; set; }
/// <summary>
@@ -55,42 +64,49 @@ namespace Managing.Api.Models.Responses
/// <summary>
/// Total accumulated runtime across all past sessions (seconds)
/// </summary>
[Required]
public long AccumulatedRunTimeSeconds { get; set; }
/// <summary>
/// Average percentage of successful trades
/// </summary>
[Required]
public int WinRate { get; set; }
/// <summary>
/// Total trading volume for all trades
/// </summary>
[Required]
public decimal TotalVolumeTraded { get; set; }
/// <summary>
/// Trading volume in the last 24 hours
/// </summary>
[Required]
public decimal VolumeLast24H { get; set; }
/// <summary>
/// Number of winning trades
/// </summary>
[Required]
public int Wins { get; set; }
/// <summary>
/// Number of losing trades
/// </summary>
[Required]
public int Losses { get; set; }
/// <summary>
/// Dictionary of all positions executed by this strategy, keyed by position identifier
/// </summary>
[Required]
public List<PositionViewModel> Positions { get; set; } = new List<PositionViewModel>();
public Guid Identifier { get; set; }
[Required] public Guid Identifier { get; set; }
public Dictionary<DateTime, decimal> WalletBalances { get; set; } = new Dictionary<DateTime, decimal>();
public Enums.Ticker Ticker { get; set; }
[Required] public Enums.Ticker Ticker { get; set; }
/// <summary>
/// The agent name of the master bot's owner (for copy trading bots)