Update Agent balance tracking
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#nullable enable
|
||||
using Managing.Application.Abstractions;
|
||||
using Managing.Application.Abstractions.Grains;
|
||||
using Managing.Application.Abstractions.Repositories;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Bots.Models;
|
||||
using Managing.Application.Orleans;
|
||||
@@ -31,6 +32,7 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
private readonly IUserService _userService;
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly ITradingService _tradingService;
|
||||
private readonly IAgentBalanceRepository _agentBalanceRepository;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
|
||||
public AgentGrain(
|
||||
@@ -43,6 +45,7 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
IUserService userService,
|
||||
IAccountService accountService,
|
||||
ITradingService tradingService,
|
||||
IAgentBalanceRepository agentBalanceRepository,
|
||||
IServiceScopeFactory scopeFactory)
|
||||
{
|
||||
_state = state;
|
||||
@@ -53,6 +56,7 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
_userService = userService;
|
||||
_accountService = accountService;
|
||||
_tradingService = tradingService;
|
||||
_agentBalanceRepository = agentBalanceRepository;
|
||||
_scopeFactory = scopeFactory;
|
||||
}
|
||||
|
||||
@@ -88,7 +92,7 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
await _agentService.SaveOrUpdateAgentSummary(emptySummary);
|
||||
_logger.LogInformation("Agent {UserId} initialized with name {AgentName} and empty summary", userId, agentName);
|
||||
|
||||
// Notify platform summary about new agent activation
|
||||
// Notify platform summary about new agent activation
|
||||
await ServiceScopeHelpers.WithScopedService<IGrainFactory>(_scopeFactory, async grainFactory =>
|
||||
{
|
||||
var platformGrain = grainFactory.GetGrain<IPlatformSummaryGrain>("platform-summary");
|
||||
@@ -101,7 +105,7 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
{
|
||||
_state.State.AgentName = agentName;
|
||||
await _state.WriteStateAsync();
|
||||
|
||||
|
||||
// Use the efficient method to update only the agent name in the summary
|
||||
await _agentService.UpdateAgentSummaryNameAsync((int)this.GetPrimaryKeyLong(), agentName);
|
||||
_logger.LogInformation("Agent {UserId} updated with name {AgentName}", this.GetPrimaryKeyLong(), agentName);
|
||||
@@ -127,7 +131,8 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Position closed event received for user {UserId}, position: {PositionId}, PnL: {PnL}",
|
||||
_logger.LogInformation(
|
||||
"Position closed event received for user {UserId}, position: {PositionId}, PnL: {PnL}",
|
||||
this.GetPrimaryKeyLong(), evt.PositionIdentifier, evt.RealizedPnL);
|
||||
|
||||
await UpdateSummary();
|
||||
@@ -171,7 +176,7 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
var totalVolume = positions.Sum(p => p.Open.Price * p.Open.Quantity * p.Open.Leverage);
|
||||
var collateral = positions.Sum(p => p.Open.Price * p.Open.Quantity);
|
||||
var totalFees = positions.Sum(p => p.CalculateTotalFees());
|
||||
|
||||
|
||||
// Store total fees in grain state for caching
|
||||
_state.State.TotalFees = totalFees;
|
||||
|
||||
@@ -220,11 +225,10 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
totalBalance = 0; // Set to 0 if calculation fails
|
||||
}
|
||||
|
||||
var bots = await ServiceScopeHelpers.WithScopedService<IBotService, IEnumerable<Bot>> (_scopeFactory, async (botService) => {
|
||||
return await botService.GetBotsByUser((int)this.GetPrimaryKeyLong());
|
||||
});
|
||||
var bots = await ServiceScopeHelpers.WithScopedService<IBotService, IEnumerable<Bot>>(_scopeFactory,
|
||||
async (botService) => { return await botService.GetBotsByUser((int)this.GetPrimaryKeyLong()); });
|
||||
|
||||
// Calculate Runtime based on the earliest position date
|
||||
// Calculate Runtime based on the earliest position date
|
||||
DateTime? runtime = null;
|
||||
if (positions.Any())
|
||||
{
|
||||
@@ -233,6 +237,18 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
|
||||
var activeStrategiesCount = bots.Count(b => b.Status == BotStatus.Running);
|
||||
|
||||
// Calculate bots allocation USD value from bot configurations
|
||||
var botsAllocationUsdValue = 0m;
|
||||
if (bots.Any())
|
||||
{
|
||||
var botIds = bots.Select(b => b.Identifier);
|
||||
var botConfigs =
|
||||
await ServiceScopeHelpers.WithScopedService<IBotService, IEnumerable<TradingBotConfig>>(
|
||||
_scopeFactory,
|
||||
async (botService) => { return await botService.GetBotConfigsByIdsAsync(botIds); });
|
||||
botsAllocationUsdValue = botConfigs.Sum(config => config.BotTradingBalance);
|
||||
}
|
||||
|
||||
var summary = new AgentSummary
|
||||
{
|
||||
UserId = (int)this.GetPrimaryKeyLong(),
|
||||
@@ -251,8 +267,12 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
|
||||
// Save summary to database
|
||||
await _agentService.SaveOrUpdateAgentSummary(summary);
|
||||
|
||||
_logger.LogDebug("Updated agent summary from position data for user {UserId}: NetPnL={NetPnL}, TotalPnL={TotalPnL}, Fees={Fees}, Volume={Volume}, Wins={Wins}, Losses={Losses}",
|
||||
|
||||
// Insert balance tracking data
|
||||
InsertBalanceTrackingData(totalBalance, botsAllocationUsdValue, netPnL);
|
||||
|
||||
_logger.LogDebug(
|
||||
"Updated agent summary from position data for user {UserId}: NetPnL={NetPnL}, TotalPnL={TotalPnL}, Fees={Fees}, Volume={Volume}, Wins={Wins}, Losses={Losses}",
|
||||
this.GetPrimaryKeyLong(), netPnL, totalPnL, totalFees, totalVolume, totalWins, totalLosses);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -512,17 +532,18 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
{
|
||||
var botGrain = GrainFactory.GetGrain<ILiveTradingBotGrain>(botEntry.Identifier);
|
||||
var hasOpenPositions = await botGrain.HasOpenPositionsAsync();
|
||||
|
||||
|
||||
if (hasOpenPositions)
|
||||
{
|
||||
_logger.LogInformation("Bot {BotId} has open positions, blocking autoswap for user {UserId}",
|
||||
_logger.LogInformation("Bot {BotId} has open positions, blocking autoswap for user {UserId}",
|
||||
botEntry.Identifier, this.GetPrimaryKeyLong());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Error checking open positions for bot {BotId}, skipping", botEntry.Identifier);
|
||||
_logger.LogWarning(ex, "Error checking open positions for bot {BotId}, skipping",
|
||||
botEntry.Identifier);
|
||||
// Continue checking other bots even if one fails
|
||||
}
|
||||
}
|
||||
@@ -532,7 +553,8 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error checking for open positions across all bots for user {UserId}", this.GetPrimaryKeyLong());
|
||||
_logger.LogError(ex, "Error checking for open positions across all bots for user {UserId}",
|
||||
this.GetPrimaryKeyLong());
|
||||
return false; // Default to false on error to avoid blocking autoswap
|
||||
}
|
||||
}
|
||||
@@ -600,4 +622,33 @@ public class AgentGrain : Grain, IAgentGrain
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts balance tracking data into the AgentBalanceRepository
|
||||
/// </summary>
|
||||
private void InsertBalanceTrackingData(decimal totalAccountUsdValue, decimal botsAllocationUsdValue, decimal pnl)
|
||||
{
|
||||
try
|
||||
{
|
||||
var agentBalance = new AgentBalance
|
||||
{
|
||||
AgentName = _state.State.AgentName,
|
||||
TotalBalanceValue = totalAccountUsdValue,
|
||||
BotsAllocationUsdValue = botsAllocationUsdValue,
|
||||
PnL = pnl,
|
||||
Time = DateTime.UtcNow
|
||||
};
|
||||
|
||||
_agentBalanceRepository.InsertAgentBalance(agentBalance);
|
||||
|
||||
_logger.LogDebug(
|
||||
"Inserted balance tracking data for agent {AgentName}: TotalBalanceValue={TotalBalanceValue}, BotsAllocationUsdValue={BotsAllocationUsdValue}, PnL={PnL}",
|
||||
agentBalance.AgentName, agentBalance.TotalBalanceValue, agentBalance.BotsAllocationUsdValue,
|
||||
agentBalance.PnL);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error inserting balance tracking data for agent {AgentName}", _state.State.AgentName);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user