@page "/statistics" @using TradingBot.Models @using TradingBot.Services @inject TradingBotService BotService @inject NavigationManager Navigation @implements IDisposable @rendermode InteractiveServer Statistiche - TradingBot

Statistiche Avanzate

Analisi dettagliata delle performance e metriche di trading

@if (string.IsNullOrEmpty(selectedSymbol)) {

Panoramica Portfolio

Valore Totale
$@portfolioStats.TotalBalance.ToString("N2")
Profitto Netto
$@portfolioStats.TotalProfit.ToString("N2")
Totale Operazioni
@portfolioStats.TotalTrades
Win Rate
@portfolioStats.WinRate.ToString("F1")%
Miglior Performer
@if (!string.IsNullOrEmpty(portfolioStats.BestPerformingAssetSymbol)) {
@portfolioStats.BestPerformingAssetSymbol
+$@portfolioStats.BestPerformingAssetProfit.ToString("N2")
} else {
Nessun dato
}
Peggior Performer
@if (!string.IsNullOrEmpty(portfolioStats.WorstPerformingAssetSymbol)) {
@portfolioStats.WorstPerformingAssetSymbol
$@portfolioStats.WorstPerformingAssetProfit.ToString("N2")
} else {
Nessun dato
}

Breakdown per Asset

Asset
Valore
Profitto
% Profitto
Trades
Win Rate
Azioni
@foreach (var assetStat in portfolioStats.AssetStatistics.OrderByDescending(a => a.NetProfit)) { var config = BotService.AssetConfigurations.TryGetValue(assetStat.Symbol, out var c) ? c : null; if (config == null) continue; var currentValue = config.CurrentBalance + (config.CurrentHoldings * assetStat.CurrentPrice);
@assetStat.Symbol @assetStat.Name
$@currentValue.ToString("N2")
$@assetStat.NetProfit.ToString("N2")
@config.ProfitPercentage.ToString("F2")%
@assetStat.TotalTrades
@assetStat.WinRate.ToString("F1")%
}
} else { var assetStats = BotService.AssetStatistics.TryGetValue(selectedSymbol, out var stats) ? stats : null; var assetConfig = BotService.AssetConfigurations.TryGetValue(selectedSymbol, out var config) ? config : null; @if (assetStats != null && assetConfig != null) {

@assetStats.Name (@assetStats.Symbol)

@(assetConfig.IsEnabled ? "Attivo" : "Inattivo")
Prezzo Corrente
$@assetStats.CurrentPrice.ToString("N2")
Holdings
@assetConfig.CurrentHoldings.ToString("F6")
Profitto Netto
$@assetStats.NetProfit.ToString("N2")
ROI
@assetConfig.ProfitPercentage.ToString("F2")%

Performance Trading

Totale Operazioni @assetStats.TotalTrades
Operazioni Vincenti @assetStats.WinningTrades
Operazioni Perdenti @assetStats.LosingTrades
Win Rate @assetStats.WinRate.ToString("F1")%
Profit Factor @(assetStats.ProfitFactor > 1000 ? ">1000" : assetStats.ProfitFactor.ToString("F2"))
Vittorie Consecutive @assetStats.MaxConsecutiveWins

Analisi Profitti/Perdite

Profitti
$@assetStats.TotalProfit.ToString("N2")
Media per trade: $@assetStats.AverageProfit.ToString("N2")
Profitto massimo: $@assetStats.LargestWin.ToString("N2")
Perdite
$@assetStats.TotalLoss.ToString("N2")
Media per trade: $@assetStats.AverageLoss.ToString("N2")
Perdita massima: $@assetStats.LargestLoss.ToString("N2")
@if (assetStats.UnrealizedPnL != 0) {
P/L Non Realizzato
$@assetStats.UnrealizedPnL.ToString("N2")
@assetStats.UnrealizedPnLPercentage.ToString("F2")% sulla posizione corrente
}
@if (assetStats.RecentTrades.Count > 0) {

Operazioni Recenti

@foreach (var trade in assetStats.RecentTrades.Take(20)) {
@(trade.Type == TradeType.Buy ? "ACQUISTO" : "VENDITA") @if (trade.IsBot) { BOT }
@trade.Timestamp.ToLocalTime().ToString("dd/MM/yyyy HH:mm:ss")
@trade.Amount.ToString("F6") @trade.Symbol
@ $@trade.Price.ToString("N2")
$@((trade.Amount * trade.Price).ToString("N2"))
}
} else {

Nessuna operazione eseguita per questo asset

}
} else {

Asset non trovato o dati non disponibili

} }
@code { [SupplyParameterFromQuery(Name = "symbol")] private string? QuerySymbol { get; set; } private string selectedSymbol = ""; private PortfolioStatistics portfolioStats = new(); protected override void OnInitialized() { BotService.OnStatusChanged += HandleUpdate; BotService.OnTradeExecuted += HandleTradeExecuted; BotService.OnStatisticsUpdated += HandleUpdate; BotService.OnPriceUpdated += HandlePriceUpdate; if (!string.IsNullOrEmpty(QuerySymbol)) { selectedSymbol = QuerySymbol; } RefreshData(); } protected override void OnParametersSet() { if (!string.IsNullOrEmpty(QuerySymbol) && QuerySymbol != selectedSymbol) { selectedSymbol = QuerySymbol; RefreshData(); } } private void RefreshData() { portfolioStats = BotService.GetPortfolioStatistics(); StateHasChanged(); } private void OnSymbolChanged() { if (string.IsNullOrEmpty(selectedSymbol)) { Navigation.NavigateTo("/statistics"); } else { Navigation.NavigateTo($"/statistics?symbol={selectedSymbol}"); } RefreshData(); } private void ViewAssetDetails(string symbol) { selectedSymbol = symbol; Navigation.NavigateTo($"/statistics?symbol={symbol}"); RefreshData(); } private void ClearSelection() { selectedSymbol = ""; Navigation.NavigateTo("/statistics"); RefreshData(); } private void HandleUpdate() => InvokeAsync(RefreshData); private void HandleTradeExecuted(Trade trade) => InvokeAsync(RefreshData); private void HandlePriceUpdate(string symbol, MarketPrice price) => InvokeAsync(RefreshData); public void Dispose() { BotService.OnStatusChanged -= HandleUpdate; BotService.OnTradeExecuted -= HandleTradeExecuted; BotService.OnStatisticsUpdated -= HandleUpdate; BotService.OnPriceUpdated -= HandlePriceUpdate; } }