Add stats for kaigen
This commit is contained in:
@@ -1,9 +1,12 @@
|
|||||||
using Managing.Application.Abstractions;
|
using Managing.Application.Abstractions;
|
||||||
using Managing.Application.Abstractions.Services;
|
using Managing.Application.Abstractions.Services;
|
||||||
using Managing.Application.Hubs;
|
using Managing.Application.Hubs;
|
||||||
|
using Managing.Application.ManageBot.Commands;
|
||||||
using Managing.Application.Workers.Abstractions;
|
using Managing.Application.Workers.Abstractions;
|
||||||
|
using Managing.Api.Models.Responses;
|
||||||
using Managing.Domain.Candles;
|
using Managing.Domain.Candles;
|
||||||
using Managing.Domain.Statistics;
|
using Managing.Domain.Statistics;
|
||||||
|
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;
|
||||||
@@ -16,7 +19,6 @@ namespace Managing.Api.Controllers;
|
|||||||
/// Requires authorization for access.
|
/// Requires authorization for access.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Authorize]
|
|
||||||
[Route("[controller]")]
|
[Route("[controller]")]
|
||||||
public class DataController : ControllerBase
|
public class DataController : ControllerBase
|
||||||
{
|
{
|
||||||
@@ -25,6 +27,7 @@ public class DataController : ControllerBase
|
|||||||
private readonly ICacheService _cacheService;
|
private readonly ICacheService _cacheService;
|
||||||
private readonly IStatisticService _statisticService;
|
private readonly IStatisticService _statisticService;
|
||||||
private readonly IHubContext<CandleHub> _hubContext;
|
private readonly IHubContext<CandleHub> _hubContext;
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="DataController"/> class.
|
/// Initializes a new instance of the <see cref="DataController"/> class.
|
||||||
@@ -34,18 +37,21 @@ public class DataController : ControllerBase
|
|||||||
/// <param name="cacheService">Service for caching data.</param>
|
/// <param name="cacheService">Service for caching data.</param>
|
||||||
/// <param name="statisticService">Service for statistical analysis.</param>
|
/// <param name="statisticService">Service for statistical analysis.</param>
|
||||||
/// <param name="hubContext">SignalR hub context for real-time communication.</param>
|
/// <param name="hubContext">SignalR hub context for real-time communication.</param>
|
||||||
|
/// <param name="mediator">Mediator for handling commands and queries.</param>
|
||||||
public DataController(
|
public DataController(
|
||||||
IExchangeService exchangeService,
|
IExchangeService exchangeService,
|
||||||
IAccountService accountService,
|
IAccountService accountService,
|
||||||
ICacheService cacheService,
|
ICacheService cacheService,
|
||||||
IStatisticService statisticService,
|
IStatisticService statisticService,
|
||||||
IHubContext<CandleHub> hubContext)
|
IHubContext<CandleHub> hubContext,
|
||||||
|
IMediator mediator)
|
||||||
{
|
{
|
||||||
_exchangeService = exchangeService;
|
_exchangeService = exchangeService;
|
||||||
_accountService = accountService;
|
_accountService = accountService;
|
||||||
_cacheService = cacheService;
|
_cacheService = cacheService;
|
||||||
_statisticService = statisticService;
|
_statisticService = statisticService;
|
||||||
_hubContext = hubContext;
|
_hubContext = hubContext;
|
||||||
|
_mediator = mediator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -72,6 +78,7 @@ public class DataController : ControllerBase
|
|||||||
/// Retrieves the latest spotlight overview, using caching to enhance response times.
|
/// Retrieves the latest spotlight overview, using caching to enhance response times.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A <see cref="SpotlightOverview"/> object containing spotlight data.</returns>
|
/// <returns>A <see cref="SpotlightOverview"/> object containing spotlight data.</returns>
|
||||||
|
[Authorize]
|
||||||
[HttpGet("Spotlight")]
|
[HttpGet("Spotlight")]
|
||||||
public ActionResult<SpotlightOverview> GetSpotlight()
|
public ActionResult<SpotlightOverview> GetSpotlight()
|
||||||
{
|
{
|
||||||
@@ -94,10 +101,110 @@ public class DataController : ControllerBase
|
|||||||
/// <param name="startDate">The start date for the candle data.</param>
|
/// <param name="startDate">The start date for the candle data.</param>
|
||||||
/// <param name="timeframe">The timeframe for the candle data.</param>
|
/// <param name="timeframe">The timeframe for the candle data.</param>
|
||||||
/// <returns>A list of <see cref="Candle"/> objects.</returns>
|
/// <returns>A list of <see cref="Candle"/> objects.</returns>
|
||||||
|
[Authorize]
|
||||||
[HttpGet("GetCandles")]
|
[HttpGet("GetCandles")]
|
||||||
public async Task<ActionResult<List<Candle>>> GetCandles(TradingExchanges exchange, Ticker ticker,
|
public async Task<ActionResult<List<Candle>>> GetCandles(TradingExchanges exchange, Ticker ticker,
|
||||||
DateTime startDate, Timeframe timeframe)
|
DateTime startDate, Timeframe timeframe)
|
||||||
{
|
{
|
||||||
return Ok(await _exchangeService.GetCandlesInflux(exchange, ticker, startDate, timeframe));
|
return Ok(await _exchangeService.GetCandlesInflux(exchange, ticker, startDate, timeframe));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves statistics about currently running bots and their change in the last 24 hours.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="StrategiesStatisticsViewModel"/> containing bot statistics.</returns>
|
||||||
|
[HttpGet("GetStrategiesStatistics")]
|
||||||
|
public async Task<ActionResult<StrategiesStatisticsViewModel>> GetStrategiesStatistics()
|
||||||
|
{
|
||||||
|
const string cacheKey = "StrategiesStatistics";
|
||||||
|
const string previousCountKey = "PreviousBotsCount";
|
||||||
|
|
||||||
|
// Check if the statistics are already cached
|
||||||
|
var cachedStats = _cacheService.GetValue<StrategiesStatisticsViewModel>(cacheKey);
|
||||||
|
|
||||||
|
if (cachedStats != null)
|
||||||
|
{
|
||||||
|
return Ok(cachedStats);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get active bots
|
||||||
|
var activeBots = await _mediator.Send(new GetActiveBotsCommand());
|
||||||
|
var currentCount = activeBots.Count;
|
||||||
|
|
||||||
|
// Get previous count from cache
|
||||||
|
var previousCount = _cacheService.GetValue<int>(previousCountKey);
|
||||||
|
|
||||||
|
// Calculate change - if no previous value, set current count as the change (all are new)
|
||||||
|
int change;
|
||||||
|
if (previousCount == 0)
|
||||||
|
{
|
||||||
|
// First time running - assume all bots are new (positive change)
|
||||||
|
change = currentCount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Calculate actual difference between current and previous count
|
||||||
|
change = currentCount - previousCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the response
|
||||||
|
var botsStatistics = new StrategiesStatisticsViewModel
|
||||||
|
{
|
||||||
|
TotalStrategiesRunning = currentCount,
|
||||||
|
ChangeInLast24Hours = change
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store current count for future comparison (with 24 hour expiration)
|
||||||
|
_cacheService.SaveValue(previousCountKey, currentCount, TimeSpan.FromHours(24));
|
||||||
|
|
||||||
|
// Cache the statistics for 5 minutes
|
||||||
|
_cacheService.SaveValue(cacheKey, botsStatistics, TimeSpan.FromMinutes(5));
|
||||||
|
|
||||||
|
return Ok(botsStatistics);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the top 3 performing strategies based on ROI.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="TopStrategiesViewModel"/> containing the top performing strategies.</returns>
|
||||||
|
[HttpGet("GetTopStrategies")]
|
||||||
|
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
|
||||||
|
{
|
||||||
|
TopStrategies = botsWithPnL
|
||||||
|
.Select(item => new StrategyPerformance
|
||||||
|
{
|
||||||
|
StrategyName = item.Bot.Name,
|
||||||
|
PnL = item.PnL
|
||||||
|
})
|
||||||
|
.ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cache the result for 10 minutes
|
||||||
|
_cacheService.SaveValue(cacheKey, topStrategies, TimeSpan.FromMinutes(10));
|
||||||
|
|
||||||
|
return Ok(topStrategies);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
namespace Managing.Api.Models.Responses
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// View model representing statistics about active bots
|
||||||
|
/// </summary>
|
||||||
|
public class StrategiesStatisticsViewModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Total number of bots currently running
|
||||||
|
/// </summary>
|
||||||
|
public int TotalStrategiesRunning { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Change in bot count over the last 24 hours
|
||||||
|
/// </summary>
|
||||||
|
public int ChangeInLast24Hours { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/Managing.Api/Models/Responses/TopStrategiesViewModel.cs
Normal file
29
src/Managing.Api/Models/Responses/TopStrategiesViewModel.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
namespace Managing.Api.Models.Responses
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a high-performing strategy with its name and PnL value
|
||||||
|
/// </summary>
|
||||||
|
public class StrategyPerformance
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the strategy bot
|
||||||
|
/// </summary>
|
||||||
|
public string StrategyName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Profit and Loss value of the strategy
|
||||||
|
/// </summary>
|
||||||
|
public decimal PnL { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// View model containing the top performing strategies by ROI
|
||||||
|
/// </summary>
|
||||||
|
public class TopStrategiesViewModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// List of the top performing strategies by ROI
|
||||||
|
/// </summary>
|
||||||
|
public List<StrategyPerformance> TopStrategies { get; set; } = new List<StrategyPerformance>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ test('GMX Position Opening', async (t) => {
|
|||||||
2,
|
2,
|
||||||
50003,
|
50003,
|
||||||
96001,
|
96001,
|
||||||
35002
|
85002
|
||||||
)
|
)
|
||||||
console.log('Position opening result:', result)
|
console.log('Position opening result:', result)
|
||||||
assert.ok(result, 'Position opening result should be defined')
|
assert.ok(result, 'Position opening result should be defined')
|
||||||
|
|||||||
Reference in New Issue
Block a user