diff --git a/src/Managing.Application.Abstractions/Grains/PlatformSummaryGrainState.cs b/src/Managing.Application.Abstractions/Grains/PlatformSummaryGrainState.cs index 9539eea3..44d1faff 100644 --- a/src/Managing.Application.Abstractions/Grains/PlatformSummaryGrainState.cs +++ b/src/Managing.Application.Abstractions/Grains/PlatformSummaryGrainState.cs @@ -40,6 +40,9 @@ public class PlatformSummaryGrainState [Id(12)] public Dictionary PositionCountByAsset { get; set; } = new(); [Id(13)] public Dictionary PositionCountByDirection { get; set; } = new(); + + // Flag to track if volume has been updated by events (not from bot strategies) + [Id(14)] public bool VolumeUpdatedByEvents { get; set; } } /// diff --git a/src/Managing.Application/Grains/PlatformSummaryGrain.cs b/src/Managing.Application/Grains/PlatformSummaryGrain.cs index cb4254e2..4c13edf7 100644 --- a/src/Managing.Application/Grains/PlatformSummaryGrain.cs +++ b/src/Managing.Application/Grains/PlatformSummaryGrain.cs @@ -116,15 +116,34 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable // Update state _state.State.TotalAgents = totalAgents; _state.State.TotalActiveStrategies = totalActiveStrategies; - _state.State.TotalPlatformVolume = totalVolume; + + // Only update volume if it hasn't been updated by events recently + // This preserves real-time volume updates from position events + if (!_state.State.VolumeUpdatedByEvents) + { + _state.State.TotalPlatformVolume = totalVolume; + _logger.LogDebug("Updated volume from strategies: {Volume}", totalVolume); + } + else + { + _logger.LogDebug("Preserving event-updated volume: {Volume}", _state.State.TotalPlatformVolume); + } + _state.State.TotalPlatformPnL = totalPnL; _state.State.OpenInterest = totalOpenInterest; _state.State.TotalPositionCount = totalPositionCount; _state.State.LastUpdated = DateTime.UtcNow; _state.State.HasPendingChanges = false; - // Update volume breakdown by asset - UpdateVolumeBreakdown(strategies); + // Update volume breakdown by asset only if volume wasn't updated by events + if (!_state.State.VolumeUpdatedByEvents) + { + UpdateVolumeBreakdown(strategies); + } + else + { + _logger.LogDebug("Preserving event-updated volume breakdown"); + } // Update position count breakdown UpdatePositionCountBreakdown(strategies); @@ -309,6 +328,9 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable _state.State.VolumeByAsset[asset] += evt.Volume; + // Mark that volume has been updated by events + _state.State.VolumeUpdatedByEvents = true; + // Update open interest (subtract the closed position's volume) _state.State.OpenInterest = Math.Max(0, _state.State.OpenInterest - evt.Volume); @@ -347,6 +369,9 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable _state.State.VolumeByAsset[asset] += evt.Volume; + // Mark that volume has been updated by events + _state.State.VolumeUpdatedByEvents = true; + // Update open interest and position count // Since this is called only when position is fully open on broker, we always increase counts _state.State.TotalPositionCount++; @@ -421,6 +446,9 @@ public class PlatformSummaryGrain : Grain, IPlatformSummaryGrain, IRemindable _state.State.LastSnapshot = DateTime.UtcNow; + // Reset the volume updated by events flag daily to allow periodic refresh from strategies + _state.State.VolumeUpdatedByEvents = false; + await _state.WriteStateAsync(); }