From c93ccd5e4afb07f339ec422485b55265cf89be5d Mon Sep 17 00:00:00 2001 From: Alberto Balbo Date: Mon, 15 Dec 2025 10:37:31 +0100 Subject: [PATCH] Migliora robustezza Dockerfile e controlli TradingBotService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Installa wget e aggiorna healthcheck in Dockerfile (usa wget invece di curl, UID 1001 per utente non-root) - Aggiunti controlli di nullità e validità su simboli, prezzi e segnali in TradingBotService - Migliorata gestione delle eccezioni con stampa dello stack trace - Filtrati dati non validi prima del calcolo degli indicatori - Aumentata la sicurezza e la resilienza contro dati corrotti o incompleti --- TradingBot/Dockerfile | 13 ++++--- TradingBot/Services/TradingBotService.cs | 43 +++++++++++++++++++----- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/TradingBot/Dockerfile b/TradingBot/Dockerfile index 857f3d2..af33db7 100644 --- a/TradingBot/Dockerfile +++ b/TradingBot/Dockerfile @@ -21,8 +21,13 @@ RUN dotnet publish "TradingBot.csproj" -c Release -o /app/publish /p:UseAppHost= FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final WORKDIR /app +# Installa wget per health check (curl non disponibile nell'immagine base) +RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/* + # Crea utente non-root per sicurezza -RUN useradd -m -u 1000 tradingbot && \ +# Usa UID 1001 invece di 1000 (1000 spesso già in uso nell'immagine base) +RUN groupadd -r -g 1001 tradingbot && \ + useradd -r -u 1001 -g tradingbot -m -s /bin/bash tradingbot && \ chown -R tradingbot:tradingbot /app # Esponi porta @@ -46,9 +51,9 @@ ENV ASPNETCORE_URLS=http://+:8080 ENV ASPNETCORE_ENVIRONMENT=Production ENV DOTNET_RUNNING_IN_CONTAINER=true -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:8080/health || exit 1 +# Health check con wget invece di curl +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1 # Entry point ENTRYPOINT ["dotnet", "TradingBot.dll"] diff --git a/TradingBot/Services/TradingBotService.cs b/TradingBot/Services/TradingBotService.cs index cf37b02..aee56bc 100644 --- a/TradingBot/Services/TradingBotService.cs +++ b/TradingBot/Services/TradingBotService.cs @@ -162,17 +162,23 @@ public class TradingBotService try { var enabledSymbols = _assetConfigs.Values - .Where(c => c.IsEnabled) + .Where(c => c != null && c.IsEnabled) .Select(c => c.Symbol) + .Where(s => !string.IsNullOrWhiteSpace(s)) .ToList(); if (enabledSymbols.Count == 0) return; var prices = await _marketDataService.GetMarketPricesAsync(enabledSymbols); + if (prices == null) return; + foreach (var price in prices) { - await ProcessAssetUpdate(price); + if (price != null) + { + await ProcessAssetUpdate(price); + } } UpdateGlobalStatistics(); @@ -180,11 +186,16 @@ public class TradingBotService catch (Exception ex) { Console.WriteLine($"Error in UpdateAsync: {ex.Message}"); + Console.WriteLine($"Stack trace: {ex.StackTrace}"); } } private async Task ProcessAssetUpdate(MarketPrice price) { + // Add null check for price + if (price == null || price.Price <= 0) + return; + if (!_assetConfigs.TryGetValue(price.Symbol, out var config) || !config.IsEnabled) return; @@ -216,10 +227,15 @@ public class TradingBotService // Generate trading signal var signal = await _strategy.AnalyzeAsync(price.Symbol, _priceHistory[price.Symbol]); - OnSignalGenerated?.Invoke(signal); + + // Add null check for signal + if (signal != null) + { + OnSignalGenerated?.Invoke(signal); - // Execute trades based on strategy and configuration - await EvaluateAndExecuteTrade(price.Symbol, signal, price, config); + // Execute trades based on strategy and configuration + await EvaluateAndExecuteTrade(price.Symbol, signal, price, config); + } } } @@ -339,10 +355,18 @@ public class TradingBotService private void UpdateIndicators(string symbol) { - var history = _priceHistory[symbol]; - if (history.Count < 26) return; + if (!_priceHistory.TryGetValue(symbol, out var history) || history == null || history.Count < 26) + return; - var prices = history.Select(p => p.Price).ToList(); + // Filter out null prices and extract valid price values + var prices = history + .Where(p => p != null && p.Price > 0) + .Select(p => p.Price) + .ToList(); + + // Ensure we still have enough data after filtering + if (prices.Count < 26) + return; var rsi = TechnicalAnalysis.CalculateRSI(prices); var (macd, signal, histogram) = TechnicalAnalysis.CalculateMACD(prices); @@ -482,6 +506,9 @@ public class TradingBotService public MarketPrice? GetLatestPrice(string symbol) { + if (string.IsNullOrWhiteSpace(symbol)) + return null; + var history = GetPriceHistory(symbol); return history?.LastOrDefault(); }