@page "/positions" @using TradingBot.Services @using TradingBot.Models @inject TradingBotService BotService @inject LoggingService LoggingService @implements IDisposable @rendermode InteractiveServer Posizioni Aperte - TradingBot
@if (activePositions.Count == 0) {

Nessuna Posizione Aperta

Non hai posizioni attive al momento. Le posizioni appaiono qui automaticamente quando il bot esegue un acquisto.

} else {
@foreach (var position in activePositions.OrderBy(p => p.Symbol)) { var currentPrice = GetCurrentPrice(position.Symbol); var unrealizedPL = CalculateUnrealizedPL(position, currentPrice); var plPercentage = CalculatePLPercentage(position, currentPrice); var currentValue = position.Amount * currentPrice; var holdingTime = DateTime.UtcNow - position.Timestamp;

@position.Symbol

Aperta @position.Timestamp.ToLocalTime().ToString("dd/MM/yyyy HH:mm")
@(unrealizedPL >= 0 ? "+" : "")$@unrealizedPL.ToString("N2") (@(plPercentage >= 0 ? "+" : "")@plPercentage.ToString("F2")%)
Quantità @position.Amount.ToString("F8") @position.Symbol
Prezzo Entrata $@position.Price.ToString("N2")
Prezzo Corrente $@currentPrice.ToString("N2")
Valore Iniziale $@(position.Amount * position.Price).ToString("N2")
Valore Corrente $@currentValue.ToString("N2")
Tempo Holding @FormatHoldingTime(holdingTime)
@if (!string.IsNullOrEmpty(position.Strategy)) {
Strategia @position.Strategy
}
@if (!BotService.Status.IsRunning) { Avvia il bot per chiudere posizioni }
}
} @if (showCloseModal && positionToClose != null) { var currentPrice = GetCurrentPrice(positionToClose.Symbol); var unrealizedPL = CalculateUnrealizedPL(positionToClose, currentPrice); var plPercentage = CalculatePLPercentage(positionToClose, currentPrice); } @if (showSuccessNotification) {
Posizione chiusa con successo!
}
@code { private List activePositions = new(); private decimal totalValue = 0; private decimal totalUnrealizedPL = 0; private bool showCloseModal = false; private Trade? positionToClose = null; private bool showSuccessNotification = false; protected override void OnInitialized() { LoadPositions(); BotService.OnTradeExecuted += HandleTradeExecuted; BotService.OnPriceUpdated += HandlePriceUpdated; BotService.OnStatusChanged += HandleStatusChanged; } private void LoadPositions() { activePositions = BotService.ActivePositions.Values.ToList(); CalculateTotals(); } private void CalculateTotals() { totalValue = 0; totalUnrealizedPL = 0; foreach (var position in activePositions) { var currentPrice = GetCurrentPrice(position.Symbol); var positionValue = position.Amount * currentPrice; var pl = CalculateUnrealizedPL(position, currentPrice); totalValue += positionValue; totalUnrealizedPL += pl; } } private decimal GetCurrentPrice(string symbol) { var latestPrice = BotService.GetLatestPrice(symbol); return latestPrice?.Price ?? 0; } private decimal CalculateUnrealizedPL(Trade position, decimal currentPrice) { return (currentPrice - position.Price) * position.Amount; } private decimal CalculatePLPercentage(Trade position, decimal currentPrice) { if (position.Price == 0) return 0; return ((currentPrice - position.Price) / position.Price) * 100; } private string FormatHoldingTime(TimeSpan time) { if (time.TotalDays >= 1) return $"{(int)time.TotalDays}g {time.Hours}h"; else if (time.TotalHours >= 1) return $"{(int)time.TotalHours}h {time.Minutes}m"; else return $"{(int)time.TotalMinutes}m {time.Seconds}s"; } private void ShowCloseConfirmation(Trade position) { positionToClose = position; showCloseModal = true; } private void HideCloseConfirmation() { showCloseModal = false; positionToClose = null; } private async Task ConfirmClosePosition() { if (positionToClose == null) return; try { // Close position using TradingBotService public method await BotService.ClosePositionManuallyAsync(positionToClose.Symbol); LoggingService.LogInfo( "Positions", $"Posizione chiusa manualmente: {positionToClose.Symbol}", $"Quantità: {positionToClose.Amount:F8}"); showSuccessNotification = true; HideCloseConfirmation(); LoadPositions(); // Hide notification after 3 seconds await Task.Delay(3000); showSuccessNotification = false; StateHasChanged(); } catch (Exception ex) { LoggingService.LogError("Positions", $"Errore chiusura posizione: {ex.Message}"); } } private void HandleTradeExecuted(Trade trade) { LoadPositions(); InvokeAsync(StateHasChanged); } private void HandlePriceUpdated(string symbol, MarketPrice price) { if (activePositions.Any(p => p.Symbol == symbol)) { CalculateTotals(); InvokeAsync(StateHasChanged); } } private void HandleStatusChanged() { InvokeAsync(StateHasChanged); } public void Dispose() { BotService.OnTradeExecuted -= HandleTradeExecuted; BotService.OnPriceUpdated -= HandlePriceUpdated; BotService.OnStatusChanged -= HandleStatusChanged; } }