using System; using System.Threading; using System.Threading.Tasks; using FinlyticCore.Models.Analyzer; using FinlyticCore.Services.Yahoo; using Microsoft.Extensions.Logging; namespace FinlyticAnalyzer.Services; public class VixTrackerService : IVixTrackerService { private readonly YahooFinanceClient _yahooClient; private readonly ILogger _logger; private decimal _currentVix = 18.5m; // Default: Normal Regime private VixMarketRegime _currentRegime = VixMarketRegime.Normal; private readonly object _lock = new(); public VixTrackerService(YahooFinanceClient yahooClient, ILogger logger) { _yahooClient = yahooClient; _logger = logger; } public decimal GetCurrentVix() { lock (_lock) { return _currentVix; } } public VixMarketRegime GetCurrentRegime() { lock (_lock) { return _currentRegime; } } public void UpdateVixFromTick(decimal vixValue) { if (vixValue <= 0m) return; lock (_lock) { var oldRegime = _currentRegime; var oldVix = _currentVix; _currentVix = vixValue; _currentRegime = CalculateRegime(vixValue); if (oldRegime != _currentRegime) { _logger.LogWarning("[{Channel}] [VIX REGIME SHIFT] Markt-Regime gewechselt: {OldRegime} -> {NewRegime} (VIX: {Vix:F2})", "AnalyzerChannel", oldRegime, _currentRegime, _currentVix); } else if (Math.Abs(oldVix - vixValue) >= 0.5m) { _logger.LogInformation("[{Channel}] VIX aktualisiert: {Vix:F2} (Regime: {Regime})", "AnalyzerChannel", _currentVix, _currentRegime); } } } public async Task PollVixAsync(CancellationToken cancellationToken = default) { try { var vix = await _yahooClient.GetLivePriceAsync("^VIX", cancellationToken); if (vix.HasValue && vix.Value > 0m) { UpdateVixFromTick(vix.Value); return vix.Value; } } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { // Graceful shutdown } catch (Exception ex) { _logger.LogWarning(ex, "[{Channel}] Fehler beim Abfragen von ^VIX über YahooFinanceClient. Nutze gecachten Wert {Vix}.", "AnalyzerChannel", GetCurrentVix()); } return GetCurrentVix(); } private static VixMarketRegime CalculateRegime(decimal vix) { return vix switch { < 15.0m => VixMarketRegime.LowVol, >= 15.0m and < 20.0m => VixMarketRegime.Normal, >= 20.0m and < 30.0m => VixMarketRegime.HighVol, _ => VixMarketRegime.Panic }; } }