Files
Finlytic/PROBLEMS.md
T

13 KiB
Raw Blame History

Finlytic Problemanalyse & Schwachstellenbericht (PROBLEMS.md)

Dieses Dokument analysiert detailliert alle identifizierten Fehler, logischen Inkonsistenzen, mathematischen/finanziellen Ungenauigkeitsquellen, fehlenden Funktionen und Skalierungsrisiken im gesamten Finlytic-Codebase.


Inhaltsverzeichnis

  1. Kritische Bugs & Logikfehler
  2. Ursachen für Ungenauigkeiten (Inaccuracies & Drift)
  3. Fehlende Funktionen & Architekturlücken
  4. Skalierungs-, Performance- & Resilienz-Risiken
  5. Konkreter Maßnahmen- & Optimierungs-Fahrplan

1. Kritische Bugs & Logikfehler

1.1 Alpaca Bracket-Order Stop-Loss Update Fehler

  • Ort: FinlyticBot/Services/Alpaca/AlpacaPaperTradingService.cs (Zeilen 123147)
  • Problem: Beim Platzieren einer Bracket-Order (PostOrderAsync) gibt Alpaca die Order-ID der übergeordneten Market-Order zurück. Sobald diese ausgeführt wird, ist diese Order abgeschlossen (filled). In UpdateStopLossAsync wird versucht, client.PatchOrderAsync(new ChangeOrderRequest(orderGuid) { StopPrice = ... }) direkt mit der übergeordneten Market-Order-ID aufzurufen.
  • Auswirkung: Alpaca lehnt das Update mit 422 Unprocessable Entity oder 404 Not Found ab, da nicht die Parent-Order, sondern die untergeordnete Stop-Loss-Leg-Order gepatcht werden muss.
  • Lösung: Nach der Ausführung muss die Order über client.GetOrderAsync() abgefragt werden, um die legs (Child-Orders) zu inspizieren und die ID der Stop-Loss-Order in BotPositionEntity zu speichern.

1.2 Bot-Positionsüberwachung fragt nicht existierende 1m-Kerzen ab

  • Ort: FinlyticBot/Services/Monitoring/BotTradeLifecycleBackgroundService.cs (Zeile 8286)
  • Problem: Der Lifecycle-Service pollt ta_GetCandles mit Timeframe = "1m". FinlyticTechnicals befüllt seine Ringpuffer jedoch primär via Yahoo Finance mit den Timeframes 15m, 1h und 1d. Die 1m-Kerzen werden ausschließlich live generiert, wenn TradeRepublicIngestionService für genau dieses Asset Ticks streamt.
  • Auswirkung: Für Assets, die nicht aktiv über Trade Republic gestreamt werden, gibt ta_GetCandles eine leere Liste zurück (candles.Count == 0). Der Bot führt continue aus und aktualisiert weder den aktuellen Kurs (CurrentPrice), noch prüft er Stop-Loss- oder Take-Profit-Bedingungen.
  • Lösung: Fallback auf den kleinsten verfügbaren Timeframe (15m) oder direkte Abfrage des letzten Live-Kurses (tr_GetLivePrice).

1.3 Inkonsistente Datenbankbenennung für FinlyticSentiment

  • Ort: compose.yaml (Zeile 138) vs. Dokumentation & Konventionen
  • Problem: In compose.yaml heißt die Datenbank finlytic_sentimental, während die Namenskonvention aller anderen Services finlytic_{service} lautet (also finlytic_sentiment).
  • Auswirkung: Bei automatisierten Backups, Init-Skripten oder manuellen SQL-Inspektionen führt dieser Tippfehler zu Verwirrung oder fehlgeschlagenen Migrations-Skripten.
  • Lösung: Vereinheitlichung auf finlytic_sentiment.

1.4 Unbenutzte Gebührenvariable im Synthetischen Ledger

  • Ort: FinlyticBot/Services/Ledger/SyntheticPaperBroker.cs (Zeile 134, 149)
  • Problem: In GetSummaryAsync wird decimal totalFees = positions.Sum(p => p.TotalFeesEur); berechnet, aber in der Equity-Formel nicht verwendet: decimal currentEquity = baseCapital + totalRealized + unrealizedPnl; (Hinweis: totalRealized hat die Gebühren bereits bei Schließung abgezogen; die Variable totalFees ist toter Code).
  • Lösung: Bereinigung oder explizite Dokumentation der Netto-PnL-Logik.

2. Ursachen für Ungenauigkeiten (Inaccuracies & Drift)

2.1 Fehlende Währungskonvertierung (USD vs. EUR bei Alpaca)

  • Ort: FinlyticBot/Services/Execution/BotOrderExecutor.cs & FinlyticBot/Services/Alpaca/AlpacaPaperTradingService.cs
  • Problem:
    • Finlytics Kontoführung, synthetischer Ledger und Risikoberechnungen (SyntheticBaseCapitalEur, Sizing-Formel) rechnen strikt in EUR (€).
    • Alpaca US-Equities (z.B. AAPL, NVDA) werden in USD ($) abgerechnet und bepreist.
    • BotOrderExecutor übergibt den EUR-Preis 1:1 an Alpaca bzw. nimmt für das Sizing an, dass 1 = 1 €.
  • Ungenauigkeit: Je nach EUR/USD-Wechselkurs (z.B. 1,08) weicht das tatsächliche Risiko um 815% von der 1%-Risikoregel ab.
  • Lösung: Integration eines FX-Umrechnungskurses (z.B. über EZB-Feed oder Yahoo EURUSD=X) in die Sizing- und Positionsbewertungslogik.

2.2 Warmup-Verzerrung bei EMA 200 & langfristigen Indikatoren [BEHOBEN]

  • Ort: FinlyticTechnicals/Indicators/TechnicalIndicatorsEngine.cs, CoreStrategies.cs & TechnicalScoringEngineV2.cs
  • Problem: Wenn für ein neu hinzugefügtes Asset weniger als 200 historische Kerzen vorlagen, wurde der EMA 200 aus den verfügbaren Kerzen berechnet (Fallback auf SMA über z.B. 50 Kerzen).
  • Lösung / Status: Behoben: CalculateEma gibt bei candles.Count < period strikt 0m zurück. TrendPullbackFvgStrategy und MovingAverageCrossoverStrategy prüfen strikt \ge 205 Kerzen, und TechnicalScoringEngineV2 vergibt Confluence-Punkte nur bei EMA > 0m.

2.3 Intrabar-Pfad-Ungewissheit im Backtesting [BEHOBEN]

  • Ort: FinlyticSimulation/Engine/VirtualBacktestBroker.cs
  • Problem: Eine Kerze liefert nur O, H, L, C. Wenn innerhalb derselben Kerze sowohl das Take-Profit-Level (H) als auch das Stop-Loss-Level (L) berührt wurden, konnte der Backtester nicht feststellen, welches Extremum zuerst eintrat.
  • Lösung / Status: Behoben: Konservatives Worst-Case-Prinzip implementiert. Stop-Loss und Knock-Out-Checks werden strikt vor Take-Profit ausgeführt. Wird TP1 in einer Kerze ausgelöst und der Stop auf Break-Even gezogen, wird sofort geprüft, ob das Bar-Tief auch das Break-Even-Level schneidet, um die Restposition ggf. direkt als Break-Even auszustoppen.

2.4 Feste Slippage [BEHOBEN / ENTFERNT]

  • Ort: FinlyticSimulation/Engine/VirtualBacktestBroker.cs & SimulationSettingKeys.cs
  • Problem: Bisher wurde neben der festen Ordergebühr zusätzlich eine prozentuale Slippage (0.05%) auf Kursdaten angewendet.
  • Lösung / Status: Behoben: Künstlicher Slippage-Aufschlag/-Abschlag vollständig aus der Kursausführung entfernt; Transaktionskosten werden transparent und sauber über die Ordergebühren (_orderFeeEur = 1.00 €) abgebildet. DefaultSlippagePercent wurde auf 0.0m gesetzt.

2.5 Trade Republic WebSocket-Inaktivitäts-Timeout

  • Ort: FinlyticCore/Services/TradeRepublic/TradeRepublicService.cs (_inactivityTimer = 461 Sekunden)
  • Problem: Wenn 7,6 Minuten lang keine Anfrage an Trade Republic gestellt wird, schließt der Timer die WebSocket-Verbindung. Bei der nächsten Anfrage muss die Verbindung neu aufgebaut werden.
  • Ungenauigkeit: Der Neuaufbau dauert 13 Sekunden. In dieser Zeit schlagen Live-Kurs-Abfragen fehl oder liefern veraltete Cache-Preise.
  • Lösung: Automatischer Ping/Keepalive statt Schließung oder resilienter Reconnect mit Retry.

2.6 Typkonvertierungen (double vs. decimal)

  • Ort: Mehrere Services (FinBERT DTOs nutzen double, Engine/Technicals nutzen decimal)
  • Problem: In CompositeOpportunityScorerV2 wird (decimal)sentiment.CurrentSummary.CompoundScore gecastet. Fließkommazahlen (double) können binäre Rundungsfehler aufweisen (z.B. 0.15000000000000002).
  • Lösung: Rundung auf 4 Nachkommastellen vor dem Casten (Math.Round((decimal)score, 4)).

3. Fehlende Funktionen & Architekturlücken

3.1 Fehlende Short-Derivate-Alternativen bei Trade Republic

  • Ort: FinlyticEngine/Services/Derivatives/KnockOutDerivativeResolver.cs
  • Lücke: Wenn FinlyticTechnicals ein starkes Short-Signal (Verkauf) generiert, sucht der Resolver ausschließlich nach knockOutProduct mit OptionType.Short (Put Knock-Outs). Gibt es für das Asset keine KO-Puts bei Trade Republic, scheitert die Derivate-Zuweisung komplett.
  • Erweiterung: Automatischer Fallback auf klassische Put-Optionsscheine (vanillaWarrant) oder Faktor-Short-Zertifikate.

3.2 Keine Portfolio-Korrelations- & Branchenrisiko-Prüfung

  • Ort: FinlyticBot/Services/Execution/BotOrderExecutor.cs
  • Lücke: Der Bot prüft lediglich, ob activeCount < MaxConcurrentPositions (5) ist. Er prüft nicht, ob alle 5 Positionen aus demselben Sektor stammen (z.B. 5x Halbleiter/Tech).
  • Erweiterung: Sektoren-Exposure-Limit: Maximal 2 Positionen pro Sektor oder maximal 40% Gesamtallokation in einer Branche.

3.3 Fehlende Multi-User-Isolation im Bot

  • Ort: FinlyticBot/Database/Entities/BotPositionEntity.cs
  • Lücke: EngineTradeEntity in FinlyticEngine besitzt bereits ein UserId-Feld für Multi-Tenancy. BotPositionEntity im FinlyticBot besitzt jedoch kein UserId-Feld alle Bot-Trades laufen in einem globalen Pool.
  • Erweiterung: Erweiterung von BotPositionEntity um UserId und Filterung im BotController nach dem authentifizierten Benutzer.

3.4 Fehlender nativer Trailing-Stop bei Alpaca

  • Ort: FinlyticBot/Services/Alpaca/AlpacaPaperTradingService.cs
  • Lücke: Alpaca unterstützt native Trailing-Stop-Orders (trailing_stop). Der Service nutzt bisher nur feste Bracket-Orders und versucht, den Stop-Loss diskret im 15s-Polling-Intervall nachzuziehen.
  • Erweiterung: Nutzung der nativen Alpaca TrailingStopOrder-API für exaktes Tick-basiertes Nachziehen ohne Latenzrisiko.

3.5 Fehlende Historienbereinigung (Data Retention Cleanup Cron)

  • Ort: FinlyticNews, FinlyticSentiment, FinlyticEngine
  • Lücke: Obwohl SettingKeys.ArticleRetentionDays (90 Tage) existiert, läuft kein automatischer Hintergrund-Cleanup-Job, der abgelaufene Artikel, Snapshots oder Logs physisch aus der PostgreSQL-Datenbank löscht.
  • Erweiterung: Einrichten eines täglichen Wartungs-Background-Services (DataRetentionCleanupWorker).

4. Skalierungs-, Performance- & Resilienz-Risiken

4.1 Unbegrenztes Speicherwachstum bei In-Memory-Ringpuffern

  • Ort: FinlyticTechnicals/Services/MultiTimeframeCandleAggregator.cs
  • Risiko: _buffers hält für jedes jemals abgefragte Asset ein ConcurrentDictionary mit je 500 Kerzen über 5 Timeframes. Werden über den Scanner 10.000 Assets abgefragt, belegt dies mehrere Gigabyte RAM im Container.
  • Lösung: Einführung einer LRU-Cache-Bereinigung (z.B. MemoryCache mit Ablaufzeit für Assets außerhalb der Watchlist).

4.2 Playwright-Browser-Instanzen & Zombie-Prozesse

  • Ort: FinlyticNews/Services/PlaywrightScraperService.cs & FinlyticFundamentals
  • Risiko: Playwright startet Chromium-Headless-Instanzen. Bei Netzwerk-Timeouts oder abrupten Thread-Abbrüchen können verwaiste chrome-Prozesse im Docker-Container verbleiben und Speicher/CPU leersaugen.
  • Lösung: Striktes using-Ressourcenmanagement mit BrowserContext.CloseAsync() und Docker-Container-Speicherlimits (mem_limit in compose.yaml).

4.3 Rate-Limiting & IP-Blocking bei Yahoo Finance

  • Ort: FinlyticCore/Clients/YahooFinanceClient.cs & YahooFinanceScraper.cs
  • Risiko: Yahoo Finance besitzt unangekündigte Rate-Limits. Werden 100 Assets parallel gescannt, antwortet Yahoo mit HTTP 429 Too Many Requests.
  • Lösung: Zentraler Request-Throttler mit Polly-Retry und Exponential-Backoff im YahooFinanceClient.

4.4 Single Point of Failure (MQTT-Broker & OmniDB)

  • Risiko: Alle Microservices sind über einen einzelnen MQTT-Broker verbunden. Fällt dieser aus, bricht die gesamte Inter-Service-Kommunikation ab.
  • Lösung: Polly-basierte Reconnect-Pipelines sind in ManagedMqttClient vorhanden, sollten jedoch mit Offline-Queuing ergänzt werden.

5. Konkreter Maßnahmen- & Optimierungs-Fahrplan

Priorität Bereich Maßnahme Aufwand
🔴 P1 FinlyticBot Alpaca Bracket-Order Leg-ID Fix: Stop-Loss-Leg nach Orderplatzierung ermitteln und speichern, um UpdateStopLossAsync funktionsfähig zu machen. Gering
🔴 P1 FinlyticBot 1m-Kerzen-Polling beheben: Fallback auf 15m oder tr_GetLivePrice im BotTradeLifecycleBackgroundService. Gering
🟡 P2 FinlyticBot USD/EUR Währungskonvertierung: Integration eines dynamischen Wechselkurses für US-Positionen. Mittel
🟡 P2 FinlyticEngine Derivate-Fallback erweitern: Optionsscheine/Faktor-Zertifikate als Fallback bei fehlenden KO-Puts. Mittel
🟡 P2 FinlyticTechnicals EMA 200 Warmup-Guard: Keine Signalfreigabe bei unvollständiger Kerzenhistorie (<200). Gering
🟢 P3 FinlyticBot Multi-User Isolation: UserId zu BotPositionEntity hinzufügen. Mittel
🟢 P3 FinlyticCore Data Retention Background-Worker: Automatisches Löschen alter News/Logs nach 90 Tagen. Mittel
🟢 P3 FinlyticTechnicals LRU-Cache für Ringpuffer: Speicherdeckelung bei großen Asset-Zahlen. Mittel