Update agent stats

This commit is contained in:
2025-09-28 13:55:24 +07:00
parent 6e07bac6ae
commit a8d09c36b7
5 changed files with 37 additions and 20 deletions

View File

@@ -35,4 +35,5 @@ public interface ITradingRepository
Task<IndicatorBase> GetStrategyByNameUserAsync(string name, User user); Task<IndicatorBase> GetStrategyByNameUserAsync(string name, User user);
Task<Scenario> GetScenarioByNameUserAsync(string scenarioName, User user); Task<Scenario> GetScenarioByNameUserAsync(string scenarioName, User user);
Task UpdateTradeAsync(Trade trade); Task UpdateTradeAsync(Trade trade);
Task<IEnumerable<Position>> GetPositionByUserIdAsync(int userId);
} }

View File

@@ -64,4 +64,5 @@ public interface ITradingService
Task<IndicatorBase?> GetIndicatorByNameUserAsync(string name, User user); Task<IndicatorBase?> GetIndicatorByNameUserAsync(string name, User user);
Task<Scenario?> GetScenarioByNameUserAsync(string scenarioName, User user); Task<Scenario?> GetScenarioByNameUserAsync(string scenarioName, User user);
Task<IEnumerable<Position>> GetPositionByUserIdAsync(int userId);
} }

View File

@@ -7,6 +7,7 @@ using Managing.Application.Orleans;
using Managing.Common; using Managing.Common;
using Managing.Core; using Managing.Core;
using Managing.Core.Exceptions; using Managing.Core.Exceptions;
using Managing.Domain.Bots;
using Managing.Domain.Statistics; using Managing.Domain.Statistics;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -154,32 +155,25 @@ public class AgentGrain : Grain, IAgentGrain
try try
{ {
// Get all positions for this agent's bots as initiator // 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 // Calculate aggregated statistics from position data
var totalPnL = positions.Sum(p => p.ProfitAndLoss?.Realized ?? 0); var totalPnL = positions.Sum(p => p.ProfitAndLoss?.Realized ?? 0);
var totalVolume = positions.Sum(p => p.Open.Price * p.Open.Quantity * p.Open.Leverage); 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()); var totalFees = positions.Sum(p => p.CalculateTotalFees());
// Calculate wins/losses from position PnL // Calculate wins/losses from position PnL
var totalWins = positions.Count(p => (p.ProfitAndLoss?.Realized ?? 0) > 0); var totalWins = positions.Count(p => (p.ProfitAndLoss?.Realized ?? 0) > 0);
var totalLosses = 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 => 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) // Calculate total balance (USDC + open positions value)
decimal totalBalance = 0; decimal totalBalance = 0;
try try
@@ -199,11 +193,7 @@ public class AgentGrain : Grain, IAgentGrain
totalBalance += usdcBalance; totalBalance += usdcBalance;
} }
// Get positions for all bots using their GUIDs as InitiatorIdentifier foreach (var position in positions.Where(p => !p.IsFinished()))
var botPositions =
await _tradingService.GetPositionsByInitiatorIdentifiersAsync(_state.State.BotIds);
foreach (var position in botPositions.Where(p => !p.IsFinished()))
{ {
totalBalance += position.Open.Price * position.Open.Quantity; totalBalance += position.Open.Price * position.Open.Quantity;
totalBalance += position.ProfitAndLoss?.Realized ?? 0; totalBalance += position.ProfitAndLoss?.Realized ?? 0;
@@ -216,12 +206,17 @@ public class AgentGrain : Grain, IAgentGrain
totalBalance = 0; // Set to 0 if calculation fails 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<IBotService, IEnumerable<Bot>> (_scopeFactory, async (botService) => {
var bots = await ServiceScopeHelpers.WithScopedService<IGrainFactory, List<BotRegistryEntry>> (_scopeFactory, async (grainFactory) => { return await botService.GetBotsByUser((int)this.GetPrimaryKeyLong());
var registry = grainFactory.GetGrain<ILiveBotRegistryGrain>(0);
return await registry.GetBotsForUser((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 activeStrategiesCount = bots.Count(b => b.Status == BotStatus.Running);
var summary = new AgentSummary var summary = new AgentSummary

View File

@@ -472,4 +472,9 @@ public class TradingService : ITradingService
{ {
return await _tradingRepository.GetScenarioByNameUserAsync(scenarioName, user); return await _tradingRepository.GetScenarioByNameUserAsync(scenarioName, user);
} }
public async Task<IEnumerable<Position>> GetPositionByUserIdAsync(int userId)
{
return await _tradingRepository.GetPositionByUserIdAsync(userId);
}
} }

View File

@@ -610,5 +610,20 @@ public class PostgreSqlTradingRepository : ITradingRepository
return PostgreSqlMappers.Map(scenario); return PostgreSqlMappers.Map(scenario);
} }
public async Task<IEnumerable<Position>> 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 #endregion
} }