Clean and update event

This commit is contained in:
2025-09-27 22:20:12 +07:00
parent 6d91c75ec2
commit d432549d26
13 changed files with 255 additions and 239 deletions

View File

@@ -1,6 +1,6 @@
#nullable enable
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Grains;
using Managing.Application.Abstractions.Models;
using Managing.Application.Abstractions.Services;
using Managing.Application.Bots.Models;
using Managing.Application.Orleans;
@@ -91,40 +91,107 @@ public class AgentGrain : Grain, IAgentGrain
_logger.LogInformation("Agent {UserId} updated with name {AgentName}", this.GetPrimaryKeyLong(), agentName);
}
public async Task OnAgentSummaryUpdateAsync(AgentSummaryUpdateEvent updateEvent)
public async Task OnPositionOpenedAsync(PositionOpenEvent evt)
{
try
{
_logger.LogInformation("Received agent summary update event for user {UserId}, event type: {EventType}",
this.GetPrimaryKeyLong(), updateEvent.EventType);
_logger.LogInformation("Position opened event received for user {UserId}, position: {PositionId}",
this.GetPrimaryKeyLong(), evt.PositionIdentifier);
// Only update summary if the event is for this agent's bots
if (_state.State.BotIds.Contains(updateEvent.BotId))
{
await UpdateSummary();
}
// Update event-driven metrics
_state.State.TotalVolume += evt.Volume;
_state.State.TotalFees += evt.Fee;
_state.State.LastSummaryUpdate = DateTime.UtcNow;
await _state.WriteStateAsync();
// Update the agent summary with the new data
await UpdateSummary();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing agent summary update event for user {UserId}",
_logger.LogError(ex, "Error processing position opened event for user {UserId}",
this.GetPrimaryKeyLong());
}
}
public async Task UpdateSummary()
public async Task OnPositionClosedAsync(PositionClosedEvent evt)
{
try
{
// Get all bots for this agent
var bots = await _botService.GetBotsByIdsAsync(_state.State.BotIds);
_logger.LogInformation("Position closed event received for user {UserId}, position: {PositionId}, PnL: {PnL}",
this.GetPrimaryKeyLong(), evt.PositionIdentifier, evt.RealizedPnL);
// Calculate aggregated statistics from bot data
var totalPnL = bots.Sum(b => b.Pnl);
var totalWins = bots.Sum(b => b.TradeWins);
var totalLosses = bots.Sum(b => b.TradeLosses);
// Update event-driven metrics
_state.State.TotalPnL += evt.RealizedPnL;
_state.State.TotalVolume += evt.Volume;
// Update wins/losses count
if (evt.RealizedPnL > 0)
{
_state.State.Wins++;
}
else if (evt.RealizedPnL < 0)
{
_state.State.Losses++;
}
_state.State.LastSummaryUpdate = DateTime.UtcNow;
await _state.WriteStateAsync();
// Update the agent summary with the new data
await UpdateSummary();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing position closed event for user {UserId}",
this.GetPrimaryKeyLong());
}
}
public async Task OnPositionUpdatedAsync(PositionUpdatedEvent evt)
{
try
{
_logger.LogInformation("Position updated event received for user {UserId}, position: {PositionId}",
this.GetPrimaryKeyLong(), evt.PositionIdentifier);
// Update event-driven metrics for PnL changes
// Note: This is for real-time PnL updates, not cumulative like closed positions
_state.State.LastSummaryUpdate = DateTime.UtcNow;
await _state.WriteStateAsync();
// Update the agent summary with the new data
await UpdateSummary();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing position updated event for user {UserId}",
this.GetPrimaryKeyLong());
}
}
/// <summary>
/// Updates the agent summary by recalculating from position data (used for initialization or manual refresh)
/// </summary>
private async Task UpdateSummary()
{
try
{
// Get all positions for this agent's bots as initiator
var positions = await _tradingService.GetPositionsByInitiatorIdentifiersAsync(_state.State.BotIds);
// 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);
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);
// Calculate ROI based on total volume traded with proper division by zero handling
var totalVolume = bots.Sum(b => b.Volume);
decimal totalROI;
if (totalVolume > 0)
@@ -148,11 +215,11 @@ public class AgentGrain : Grain, IAgentGrain
totalROI = 0;
}
// Calculate Runtime based on the farthest date from bot startup times
// Calculate Runtime based on the earliest position date
DateTime? runtime = null;
if (bots.Any())
if (positions.Any())
{
runtime = bots.Max(b => b.StartupTime);
runtime = positions.Min(p => p.Date);
}
// Calculate total balance (USDC + open positions value)
@@ -192,6 +259,10 @@ 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 _botService.GetBotsByIdsAsync(_state.State.BotIds);
var activeStrategiesCount = bots.Count(b => b.Status == BotStatus.Running);
var summary = new AgentSummary
{
UserId = (int)this.GetPrimaryKeyLong(),
@@ -201,13 +272,16 @@ public class AgentGrain : Grain, IAgentGrain
Losses = totalLosses,
TotalROI = totalROI,
Runtime = runtime,
ActiveStrategiesCount = bots.Count(b => b.Status == BotStatus.Running),
ActiveStrategiesCount = activeStrategiesCount,
TotalVolume = totalVolume,
TotalBalance = totalBalance,
};
// Save summary to database
await _agentService.SaveOrUpdateAgentSummary(summary);
_logger.LogDebug("Updated agent summary from position data for user {UserId}: PnL={PnL}, Volume={Volume}, Wins={Wins}, Losses={Losses}",
this.GetPrimaryKeyLong(), totalPnL, totalVolume, totalWins, totalLosses);
}
catch (Exception ex)
{
@@ -219,6 +293,10 @@ public class AgentGrain : Grain, IAgentGrain
{
if (_state.State.BotIds.Add(botId))
{
// Update active strategies count
_state.State.ActiveStrategiesCount = _state.State.BotIds.Count;
_state.State.LastSummaryUpdate = DateTime.UtcNow;
await _state.WriteStateAsync();
_logger.LogInformation("Bot {BotId} registered to Agent {UserId}", botId, this.GetPrimaryKeyLong());
@@ -231,6 +309,10 @@ public class AgentGrain : Grain, IAgentGrain
{
if (_state.State.BotIds.Remove(botId))
{
// Update active strategies count
_state.State.ActiveStrategiesCount = _state.State.BotIds.Count;
_state.State.LastSummaryUpdate = DateTime.UtcNow;
await _state.WriteStateAsync();
_logger.LogInformation("Bot {BotId} unregistered from Agent {UserId}", botId, this.GetPrimaryKeyLong());