Add stats for kaigen
This commit is contained in:
@@ -4,7 +4,9 @@ using Managing.Application.Hubs;
|
||||
using Managing.Application.ManageBot.Commands;
|
||||
using Managing.Application.Workers.Abstractions;
|
||||
using Managing.Api.Models.Responses;
|
||||
using Managing.Domain.Bots;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Shared.Helpers;
|
||||
using Managing.Domain.Statistics;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -171,25 +173,25 @@ public class DataController : ControllerBase
|
||||
public async Task<ActionResult<TopStrategiesViewModel>> GetTopStrategies()
|
||||
{
|
||||
const string cacheKey = "TopStrategies";
|
||||
|
||||
|
||||
// Check if the top strategies are already cached
|
||||
var cachedStrategies = _cacheService.GetValue<TopStrategiesViewModel>(cacheKey);
|
||||
|
||||
|
||||
if (cachedStrategies != null)
|
||||
{
|
||||
return Ok(cachedStrategies);
|
||||
}
|
||||
|
||||
|
||||
// Get active bots
|
||||
var activeBots = await _mediator.Send(new GetActiveBotsCommand());
|
||||
|
||||
|
||||
// Calculate PnL for each bot once and store in a list of tuples
|
||||
var botsWithPnL = activeBots
|
||||
.Select(bot => new { Bot = bot, PnL = bot.GetProfitAndLoss() })
|
||||
.OrderByDescending(item => item.PnL)
|
||||
.Take(3)
|
||||
.ToList();
|
||||
|
||||
|
||||
// Map to view model
|
||||
var topStrategies = new TopStrategiesViewModel
|
||||
{
|
||||
@@ -201,10 +203,130 @@ public class DataController : ControllerBase
|
||||
})
|
||||
.ToList()
|
||||
};
|
||||
|
||||
|
||||
// Cache the result for 10 minutes
|
||||
_cacheService.SaveValue(cacheKey, topStrategies, TimeSpan.FromMinutes(10));
|
||||
|
||||
|
||||
return Ok(topStrategies);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves list of the active strategies for a user with detailed information
|
||||
/// </summary>
|
||||
/// <param name="agentName">The agentName to retrieve strategies for</param>
|
||||
/// <returns>A list of detailed strategy information</returns>
|
||||
[HttpGet("GetUserStrategies")]
|
||||
public async Task<ActionResult<List<UserStrategyDetailsViewModel>>> GetUserStrategies(string agentName)
|
||||
{
|
||||
string cacheKey = $"UserStrategies_{agentName}";
|
||||
|
||||
// Check if the user strategy details are already cached
|
||||
var cachedDetails = _cacheService.GetValue<List<UserStrategyDetailsViewModel>>(cacheKey);
|
||||
|
||||
if (cachedDetails != null && cachedDetails.Count > 0)
|
||||
{
|
||||
return Ok(cachedDetails);
|
||||
}
|
||||
|
||||
// Get all strategies for the specified user
|
||||
var userStrategies = await _mediator.Send(new GetUserStrategiesCommand(agentName));
|
||||
|
||||
// Convert to detailed view model with additional information
|
||||
var result = userStrategies.Select(strategy => MapStrategyToViewModel(strategy)).ToList();
|
||||
|
||||
// Cache the results for 5 minutes
|
||||
_cacheService.SaveValue(cacheKey, result, TimeSpan.FromMinutes(5));
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a specific strategy for a user by strategy name
|
||||
/// </summary>
|
||||
/// <param name="agentName">The agent/user name to retrieve the strategy for</param>
|
||||
/// <param name="strategyName">The name of the strategy to retrieve</param>
|
||||
/// <returns>Detailed information about the requested strategy</returns>
|
||||
[HttpGet("GetUserStrategy")]
|
||||
public async Task<ActionResult<UserStrategyDetailsViewModel>> GetUserStrategy(string agentName, string strategyName)
|
||||
{
|
||||
string cacheKey = $"UserStrategy_{agentName}_{strategyName}";
|
||||
|
||||
// Check if the user strategy details are already cached
|
||||
var cachedDetails = _cacheService.GetValue<UserStrategyDetailsViewModel>(cacheKey);
|
||||
|
||||
if (cachedDetails != null)
|
||||
{
|
||||
return Ok(cachedDetails);
|
||||
}
|
||||
|
||||
// Get the specific strategy for the user
|
||||
var strategy = await _mediator.Send(new GetUserStrategyCommand(agentName, strategyName));
|
||||
|
||||
if (strategy == null)
|
||||
{
|
||||
return NotFound($"Strategy '{strategyName}' not found for user '{agentName}'");
|
||||
}
|
||||
|
||||
// Map the strategy to a view model using the shared method
|
||||
var result = MapStrategyToViewModel(strategy);
|
||||
|
||||
// Cache the results for 5 minutes
|
||||
_cacheService.SaveValue(cacheKey, result, TimeSpan.FromMinutes(5));
|
||||
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps a trading bot to a strategy view model with detailed statistics
|
||||
/// </summary>
|
||||
/// <param name="strategy">The trading bot to map</param>
|
||||
/// <returns>A view model with detailed strategy information</returns>
|
||||
private UserStrategyDetailsViewModel MapStrategyToViewModel(ITradingBot strategy)
|
||||
{
|
||||
// Get the runtime directly from the bot
|
||||
TimeSpan runtimeSpan = strategy.GetRuntime();
|
||||
|
||||
// Get the startup time from the bot's internal property
|
||||
// If bot is not running, we use MinValue as a placeholder
|
||||
DateTime startupTime = DateTime.MinValue;
|
||||
if (strategy is Bot bot && bot.StartupTime != DateTime.MinValue)
|
||||
{
|
||||
startupTime = bot.StartupTime;
|
||||
}
|
||||
|
||||
// Calculate ROI percentage based on PnL relative to account value
|
||||
decimal pnl = strategy.GetProfitAndLoss();
|
||||
|
||||
// If we had initial investment amount, we could calculate ROI like:
|
||||
decimal initialInvestment = 1000; // Example placeholder, ideally should come from the account
|
||||
decimal roi = pnl != 0 ? (pnl / initialInvestment) * 100 : 0;
|
||||
|
||||
// Calculate volume statistics
|
||||
decimal totalVolume = TradingBox.GetTotalVolumeTraded(strategy.Positions);
|
||||
decimal volumeLast24h = TradingBox.GetLast24HVolumeTraded(strategy.Positions);
|
||||
|
||||
// Calculate win/loss statistics
|
||||
(int wins, int losses) = TradingBox.GetWinLossCount(strategy.Positions);
|
||||
|
||||
// Calculate ROI for last 24h
|
||||
decimal roiLast24h = TradingBox.GetLast24HROI(strategy.Positions);
|
||||
|
||||
return new UserStrategyDetailsViewModel
|
||||
{
|
||||
Name = strategy.Name,
|
||||
StrategyName = strategy.ScenarioName,
|
||||
State = strategy.GetStatus() == BotStatus.Up.ToString() ? "RUNNING" :
|
||||
strategy.GetStatus() == BotStatus.Down.ToString() ? "STOPPED" : "UNUSED",
|
||||
PnL = pnl,
|
||||
ROIPercentage = roi,
|
||||
ROILast24H = roiLast24h,
|
||||
Runtime = startupTime,
|
||||
WinRate = strategy.GetWinRate(),
|
||||
TotalVolumeTraded = totalVolume,
|
||||
VolumeLast24H = volumeLast24h,
|
||||
Wins = wins,
|
||||
Losses = losses,
|
||||
Positions = strategy.Positions.OrderByDescending(p => p.Date).ToList() // Include sorted positions with most recent first
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
using Managing.Domain.Trades;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Api.Models.Responses
|
||||
{
|
||||
/// <summary>
|
||||
/// Detailed information about a user's deployed strategy
|
||||
/// </summary>
|
||||
public class UserStrategyDetailsViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the deployed strategy
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Strategy identifier
|
||||
/// </summary>
|
||||
public string StrategyName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current state of the strategy (RUNNING, STOPPED, UNUSED)
|
||||
/// </summary>
|
||||
public string State { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total profit or loss generated by the strategy in USD
|
||||
/// </summary>
|
||||
public decimal PnL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Return on investment percentage
|
||||
/// </summary>
|
||||
public decimal ROIPercentage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Return on investment percentage in the last 24 hours
|
||||
/// </summary>
|
||||
public decimal ROILast24H { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Date and time when the strategy was started
|
||||
/// </summary>
|
||||
public DateTime Runtime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Average percentage of successful trades
|
||||
/// </summary>
|
||||
public int WinRate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Total trading volume for all trades
|
||||
/// </summary>
|
||||
public decimal TotalVolumeTraded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Trading volume in the last 24 hours
|
||||
/// </summary>
|
||||
public decimal VolumeLast24H { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of winning trades
|
||||
/// </summary>
|
||||
public int Wins { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of losing trades
|
||||
/// </summary>
|
||||
public int Losses { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of all positions executed by this strategy
|
||||
/// </summary>
|
||||
public List<Position> Positions { get; set; } = new List<Position>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user