Refactor agent summary update process; replace TrackBalanceOnBotStartAsync with UpdateSummary in IAgentGrain and AgentGrain, and adjust LiveTradingBotGrain to call UpdateSummary for improved balance tracking and strategy count accuracy.

This commit is contained in:
2025-12-26 16:01:40 +07:00
parent 7a3ede03ca
commit de540e0d45
3 changed files with 25 additions and 97 deletions

View File

@@ -69,10 +69,9 @@ namespace Managing.Application.Abstractions.Grains
Task ForceUpdateSummary();
/// <summary>
/// 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)
/// </summary>
[OneWay]
Task TrackBalanceOnBotStartAsync();
Task UpdateSummary();
}
}

View File

@@ -180,7 +180,7 @@ public class AgentGrain : Grain, IAgentGrain
/// Updates the agent summary by recalculating from position data (used for initialization or manual refresh)
/// </summary>
[OneWay]
private async Task UpdateSummary()
public async Task UpdateSummary()
{
try
{
@@ -666,93 +666,4 @@ public class AgentGrain : Grain, IAgentGrain
}
}
/// <summary>
/// Triggers balance tracking data insertion when a bot starts/restarts.
/// This captures the balance change related to botsAllocationUsdValue.
/// </summary>
[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<IBotService, List<Bot>>(_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<IBotService, IEnumerable<TradingBotConfig>>(
_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());
}
}
}

View File

@@ -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<IAgentGrain>(_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<IAgentGrain>(_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)