From a8d09c36b7949c26666ec3ea6e05495b5601ca36 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Sun, 28 Sep 2025 13:55:24 +0700 Subject: [PATCH] Update agent stats --- .../Repositories/ITradingRepository.cs | 1 + .../Services/ITradingService.cs | 1 + .../Bots/Grains/AgentGrain.cs | 35 ++++++++----------- .../Trading/TradingService.cs | 5 +++ .../PostgreSql/PostgreSqlTradingRepository.cs | 15 ++++++++ 5 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/Managing.Application.Abstractions/Repositories/ITradingRepository.cs b/src/Managing.Application.Abstractions/Repositories/ITradingRepository.cs index 018a3585..3ab88bb1 100644 --- a/src/Managing.Application.Abstractions/Repositories/ITradingRepository.cs +++ b/src/Managing.Application.Abstractions/Repositories/ITradingRepository.cs @@ -35,4 +35,5 @@ public interface ITradingRepository Task GetStrategyByNameUserAsync(string name, User user); Task GetScenarioByNameUserAsync(string scenarioName, User user); Task UpdateTradeAsync(Trade trade); + Task> GetPositionByUserIdAsync(int userId); } \ No newline at end of file diff --git a/src/Managing.Application.Abstractions/Services/ITradingService.cs b/src/Managing.Application.Abstractions/Services/ITradingService.cs index cc7d8c30..89086b01 100644 --- a/src/Managing.Application.Abstractions/Services/ITradingService.cs +++ b/src/Managing.Application.Abstractions/Services/ITradingService.cs @@ -64,4 +64,5 @@ public interface ITradingService Task GetIndicatorByNameUserAsync(string name, User user); Task GetScenarioByNameUserAsync(string scenarioName, User user); + Task> GetPositionByUserIdAsync(int userId); } \ No newline at end of file diff --git a/src/Managing.Application/Bots/Grains/AgentGrain.cs b/src/Managing.Application/Bots/Grains/AgentGrain.cs index 22c57512..fb07e3a0 100644 --- a/src/Managing.Application/Bots/Grains/AgentGrain.cs +++ b/src/Managing.Application/Bots/Grains/AgentGrain.cs @@ -7,6 +7,7 @@ using Managing.Application.Orleans; using Managing.Common; using Managing.Core; using Managing.Core.Exceptions; +using Managing.Domain.Bots; using Managing.Domain.Statistics; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -154,32 +155,25 @@ public class AgentGrain : Grain, IAgentGrain try { // Get all positions for this agent's bots as initiator - var positions = await _tradingService.GetPositionsByInitiatorIdentifiersAsync(_state.State.BotIds); + var positions = await _tradingService.GetPositionByUserIdAsync((int)this.GetPrimaryKeyLong()); // Calculate aggregated statistics from position data var totalPnL = positions.Sum(p => p.ProfitAndLoss?.Realized ?? 0); var totalVolume = positions.Sum(p => p.Open.Price * p.Open.Quantity * p.Open.Leverage); - var totalVolumeWithoutLeverage = positions.Sum(p => p.Open.Price * p.Open.Quantity); + var collateral = positions.Sum(p => p.Open.Price * p.Open.Quantity); var totalFees = positions.Sum(p => p.CalculateTotalFees()); // Calculate wins/losses from position PnL var totalWins = positions.Count(p => (p.ProfitAndLoss?.Realized ?? 0) > 0); var totalLosses = positions.Count(p => (p.ProfitAndLoss?.Realized ?? 0) <= 0); - var totalROI = totalVolume switch + var totalROI = collateral switch { - > 0 => (totalPnL / totalVolumeWithoutLeverage) * 100, + > 0 => (totalPnL / collateral) * 100, >= 0 => 0, _ => 0 }; - // Calculate Runtime based on the earliest position date - DateTime? runtime = null; - if (positions.Any()) - { - runtime = positions.Min(p => p.Date); - } - // Calculate total balance (USDC + open positions value) decimal totalBalance = 0; try @@ -199,11 +193,7 @@ public class AgentGrain : Grain, IAgentGrain totalBalance += usdcBalance; } - // Get positions for all bots using their GUIDs as InitiatorIdentifier - var botPositions = - await _tradingService.GetPositionsByInitiatorIdentifiersAsync(_state.State.BotIds); - - foreach (var position in botPositions.Where(p => !p.IsFinished())) + foreach (var position in positions.Where(p => !p.IsFinished())) { totalBalance += position.Open.Price * position.Open.Quantity; totalBalance += position.ProfitAndLoss?.Realized ?? 0; @@ -216,12 +206,17 @@ public class AgentGrain : Grain, IAgentGrain totalBalance = 0; // Set to 0 if calculation fails } - // Get active strategies count from bot data (this is still needed for running bots) - var bots = await ServiceScopeHelpers.WithScopedService> (_scopeFactory, async (grainFactory) => { - var registry = grainFactory.GetGrain(0); - return await registry.GetBotsForUser((int)this.GetPrimaryKeyLong()); + var bots = await ServiceScopeHelpers.WithScopedService> (_scopeFactory, async (botService) => { + return await botService.GetBotsByUser((int)this.GetPrimaryKeyLong()); }); + // Calculate Runtime based on the earliest position date + DateTime? runtime = null; + if (positions.Any()) + { + runtime = bots.Min(p => p.StartupTime); + } + var activeStrategiesCount = bots.Count(b => b.Status == BotStatus.Running); var summary = new AgentSummary diff --git a/src/Managing.Application/Trading/TradingService.cs b/src/Managing.Application/Trading/TradingService.cs index bc48989c..f4c8f2cc 100644 --- a/src/Managing.Application/Trading/TradingService.cs +++ b/src/Managing.Application/Trading/TradingService.cs @@ -472,4 +472,9 @@ public class TradingService : ITradingService { return await _tradingRepository.GetScenarioByNameUserAsync(scenarioName, user); } + + public async Task> GetPositionByUserIdAsync(int userId) + { + return await _tradingRepository.GetPositionByUserIdAsync(userId); + } } \ No newline at end of file diff --git a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlTradingRepository.cs b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlTradingRepository.cs index ac4d1600..3fa6d37e 100644 --- a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlTradingRepository.cs +++ b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlTradingRepository.cs @@ -610,5 +610,20 @@ public class PostgreSqlTradingRepository : ITradingRepository return PostgreSqlMappers.Map(scenario); } + public async Task> GetPositionByUserIdAsync(int userId) + { + var positions = await _context.Positions + .AsNoTracking() + .Include(p => p.User) + .Include(p => p.OpenTrade) + .Include(p => p.StopLossTrade) + .Include(p => p.TakeProfit1Trade) + .Include(p => p.TakeProfit2Trade) + .Where(p => p.UserId == userId) + .ToListAsync() + .ConfigureAwait(false); + return PostgreSqlMappers.Map(positions); + } + #endregion } \ No newline at end of file