diff --git a/src/Managing.Application/Abstractions/Grains/IAgentGrain.cs b/src/Managing.Application/Abstractions/Grains/IAgentGrain.cs
index f9bace3d..928fa7ea 100644
--- a/src/Managing.Application/Abstractions/Grains/IAgentGrain.cs
+++ b/src/Managing.Application/Abstractions/Grains/IAgentGrain.cs
@@ -69,10 +69,9 @@ namespace Managing.Application.Abstractions.Grains
Task ForceUpdateSummary();
///
- /// Triggers balance tracking data insertion when a bot starts/restarts.
- /// This captures the balance change related to botsAllocationUsdValue.
+ /// Updates the agent summary by recalculating from position data (used for initialization or manual refresh)
///
[OneWay]
- Task TrackBalanceOnBotStartAsync();
+ Task UpdateSummary();
}
}
\ 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 2d9610db..76cb0c68 100644
--- a/src/Managing.Application/Bots/Grains/AgentGrain.cs
+++ b/src/Managing.Application/Bots/Grains/AgentGrain.cs
@@ -180,7 +180,7 @@ public class AgentGrain : Grain, IAgentGrain
/// Updates the agent summary by recalculating from position data (used for initialization or manual refresh)
///
[OneWay]
- private async Task UpdateSummary()
+ public async Task UpdateSummary()
{
try
{
@@ -666,93 +666,4 @@ public class AgentGrain : Grain, IAgentGrain
}
}
- ///
- /// Triggers balance tracking data insertion when a bot starts/restarts.
- /// This captures the balance change related to botsAllocationUsdValue.
- ///
- [OneWay]
- public async Task TrackBalanceOnBotStartAsync()
- {
- try
- {
- _logger.LogInformation("Tracking balance on bot start/restart for user {UserId}", this.GetPrimaryKeyLong());
-
- // Get all positions for this agent's bots as initiator
- var positions = (await _tradingService.GetPositionByUserIdAsync((int)this.GetPrimaryKeyLong()))
- .Where(p => p.IsValidForMetrics()).ToList();
-
- var metrics = TradingBox.CalculateAgentSummaryMetrics(positions);
-
- // Calculate total balance (USDC wallet + USDC in open positions value)
- decimal totalBalance = 0;
- decimal usdcWalletValue = 0;
- decimal usdcInPositionsValue = 0;
- try
- {
- var userId = (int)this.GetPrimaryKeyLong();
- var user = await _userService.GetUserByIdAsync(userId);
- var userAccounts = await _accountService.GetAccountsByUserAsync(user, hideSecrets: true, true);
-
- foreach (var account in userAccounts)
- {
- // Get USDC balance
- var usdcBalances = await GetOrRefreshBalanceDataAsync(account.Name);
- var usdcBalance = usdcBalances?.UsdcValue ?? 0;
- usdcWalletValue += usdcBalance;
- }
-
- foreach (var position in positions.Where(p => p.IsOpen()))
- {
- var positionUsd = position.Open.Price * position.Open.Quantity;
- var net = position.ProfitAndLoss?.Net ?? 0;
- usdcInPositionsValue += positionUsd + net;
- }
-
- totalBalance = usdcWalletValue + usdcInPositionsValue;
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error calculating total balance for agent {UserId} during bot start tracking",
- this.GetPrimaryKeyLong());
- totalBalance = 0; // Set to 0 if calculation fails
- usdcWalletValue = 0;
- usdcInPositionsValue = 0;
- }
-
- // Get active strategies to calculate botsAllocationUsdValue
- var activeStrategies = await ServiceScopeHelpers.WithScopedService>(_scopeFactory,
- async (botService) =>
- {
- return (await botService.GetBotsByUser((int)this.GetPrimaryKeyLong()))
- .Where(b => b.Status == BotStatus.Running)
- .ToList();
- });
-
- var botsAllocationUsdValue = 0m;
-
- if (activeStrategies.Any())
- {
- // Calculate bots allocation USD value from bot configurations
- var botIds = activeStrategies.Select(b => b.Identifier);
- var botConfigs =
- await ServiceScopeHelpers.WithScopedService>(
- _scopeFactory,
- async (botService) => { return await botService.GetBotConfigsByIdsAsync(botIds); });
- botsAllocationUsdValue = botConfigs.Sum(config => config.BotTradingBalance);
- }
-
- // Insert balance tracking data
- InsertBalanceTrackingData(totalBalance, botsAllocationUsdValue, metrics.NetPnL, usdcWalletValue,
- usdcInPositionsValue);
-
- _logger.LogInformation(
- "Balance tracking completed on bot start/restart for user {UserId}: TotalBalance={TotalBalance}, BotsAllocation={BotsAllocation}, NetPnL={NetPnL}",
- this.GetPrimaryKeyLong(), totalBalance, botsAllocationUsdValue, metrics.NetPnL);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error tracking balance on bot start/restart for user {UserId}",
- this.GetPrimaryKeyLong());
- }
- }
}
\ No newline at end of file
diff --git a/src/Managing.Application/Bots/Grains/LiveTradingBotGrain.cs b/src/Managing.Application/Bots/Grains/LiveTradingBotGrain.cs
index 24f15564..3dc090d8 100644
--- a/src/Managing.Application/Bots/Grains/LiveTradingBotGrain.cs
+++ b/src/Managing.Application/Bots/Grains/LiveTradingBotGrain.cs
@@ -247,21 +247,21 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
await SaveBotAsync(BotStatus.Running);
await UpdateBotRegistryStatus(BotStatus.Running);
- // Trigger balance tracking since we now have a balance change related to botsAllocationUsdValue
+ // Update agent summary to ensure ActiveStrategiesCount and balance tracking are correctly updated
if (_state.State.User != null)
{
try
{
var agentGrain = GrainFactory.GetGrain(_state.State.User.Id);
- await agentGrain.TrackBalanceOnBotStartAsync();
+ await agentGrain.UpdateSummary();
}
catch (Exception ex)
{
_logger.LogWarning(ex,
- "Failed to track balance on bot start for LiveTradingBotGrain {GrainId}, but bot started successfully",
+ "Failed to update agent summary on bot start for LiveTradingBotGrain {GrainId}, but bot started successfully",
this.GetPrimaryKey());
SentrySdk.CaptureException(ex);
- // Don't throw - bot started successfully, balance tracking is non-critical
+ // Don't throw - bot started successfully, summary update is non-critical
}
}
@@ -425,6 +425,24 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
this.GetPrimaryKey());
}
+ // Update agent summary to ensure ActiveStrategiesCount and balance tracking are correctly updated
+ if (_state.State.User != null)
+ {
+ try
+ {
+ var agentGrain = GrainFactory.GetGrain(_state.State.User.Id);
+ await agentGrain.UpdateSummary();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex,
+ "Failed to update agent summary on bot stop for LiveTradingBotGrain {GrainId}, but bot stopped successfully",
+ this.GetPrimaryKey());
+ SentrySdk.CaptureException(ex);
+ // Don't throw - bot stopped successfully, summary update is non-critical
+ }
+ }
+
_logger.LogInformation("LiveTradingBotGrain {GrainId} stopped successfully", this.GetPrimaryKey());
}
catch (Exception ex)