@inherits LayoutComponentBase @using TradingBot.Services @using TradingBot.Models @inject TradingBotService BotService @inject SettingsService SettingsService @inject NavigationManager Navigation @implements IDisposable
@Body
@code { private bool sidebarCollapsed = false; private bool isRunning => BotService.Status.IsRunning; private decimal portfolioValue = 0; private decimal totalProfit = 0; private decimal totalCapital = 0; private decimal investedCapital = 0; private decimal availableCapital = 0; private decimal currentPL = 0; private decimal roiPercentage = 0; protected override void OnInitialized() { var settings = SettingsService.GetSettings(); sidebarCollapsed = settings.SidebarCollapsed; BotService.OnStatusChanged += HandleUpdate; BotService.OnTradeExecuted += HandleTradeExecuted; BotService.OnPriceUpdated += HandlePriceUpdate; SettingsService.OnSettingsChanged += HandleSettingsChanged; UpdateStats(); if (settings.AutoStartBot && !BotService.Status.IsRunning) { BotService.Start(); } } private void ToggleSidebar() { sidebarCollapsed = !sidebarCollapsed; SettingsService.UpdateSetting(nameof(AppSettings.SidebarCollapsed), sidebarCollapsed); StateHasChanged(); // Force immediate UI update Console.WriteLine($"Sidebar toggled: collapsed={sidebarCollapsed}"); // Debug log } private void ToggleBot() { if (isRunning) BotService.Stop(); else BotService.Start(); } private void UpdateStats() { totalCapital = 0; investedCapital = 0; availableCapital = 0; currentPL = 0; totalProfit = 0; foreach (var config in BotService.AssetConfigurations.Values) { if (!config.IsEnabled) continue; // Capitale disponibile (cash) availableCapital += config.CurrentBalance; // Capitale investito in posizioni aperte var currentPrice = BotService.GetLatestPrice(config.Symbol)?.Price ?? 0; var positionValue = config.CurrentHoldings * currentPrice; investedCapital += positionValue; // P&L non realizzato sulle posizioni aperte if (config.CurrentHoldings > 0 && config.AverageEntryPrice > 0) { var entryValue = config.CurrentHoldings * config.AverageEntryPrice; currentPL += (positionValue - entryValue); } // Totale profitti/perdite realizzati totalProfit += config.TotalProfit; } // Capitale totale = Disponibile + Investito totalCapital = availableCapital + investedCapital; // Portfolio value include anche i profitti realizzati portfolioValue = totalCapital + totalProfit; // ROI basato sul capitale iniziale var initialCapital = BotService.AssetConfigurations.Values .Where(c => c.IsEnabled) .Sum(c => c.InitialBalance); if (initialCapital > 0) { var totalGain = currentPL + totalProfit; roiPercentage = (totalGain / initialCapital) * 100; } else { roiPercentage = 0; } } private void HandleUpdate() => InvokeAsync(() => { UpdateStats(); StateHasChanged(); }); private void HandleTradeExecuted(Trade trade) => InvokeAsync(() => { UpdateStats(); StateHasChanged(); }); private void HandlePriceUpdate(string symbol, MarketPrice price) => InvokeAsync(() => { UpdateStats(); StateHasChanged(); }); private void HandleSettingsChanged() => InvokeAsync(StateHasChanged); public void Dispose() { BotService.OnStatusChanged -= HandleUpdate; BotService.OnTradeExecuted -= HandleTradeExecuted; BotService.OnPriceUpdated -= HandlePriceUpdate; SettingsService.OnSettingsChanged -= HandleSettingsChanged; } }