13 KiB
13 KiB
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
- Kritische Bugs & Logikfehler
- Ursachen für Ungenauigkeiten (Inaccuracies & Drift)
- Fehlende Funktionen & Architekturlücken
- Skalierungs-, Performance- & Resilienz-Risiken
- 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 123–147) - 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). InUpdateStopLossAsyncwird versucht,client.PatchOrderAsync(new ChangeOrderRequest(orderGuid) { StopPrice = ... })direkt mit der übergeordneten Market-Order-ID aufzurufen. - Auswirkung:
Alpaca lehnt das Update mit
422 Unprocessable Entityoder404 Not Foundab, 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 dielegs(Child-Orders) zu inspizieren und die ID der Stop-Loss-Order inBotPositionEntityzu speichern.
1.2 Bot-Positionsüberwachung fragt nicht existierende 1m-Kerzen ab
- Ort:
FinlyticBot/Services/Monitoring/BotTradeLifecycleBackgroundService.cs(Zeile 82–86) - Problem:
Der Lifecycle-Service pollt
ta_GetCandlesmitTimeframe = "1m".FinlyticTechnicalsbefüllt seine Ringpuffer jedoch primär via Yahoo Finance mit den Timeframes15m,1hund1d. Die1m-Kerzen werden ausschließlich live generiert, wennTradeRepublicIngestionServicefür genau dieses Asset Ticks streamt. - Auswirkung:
Für Assets, die nicht aktiv über Trade Republic gestreamt werden, gibt
ta_GetCandleseine leere Liste zurück (candles.Count == 0). Der Bot führtcontinueaus 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.yamlheißt die Datenbankfinlytic_sentimental, während die Namenskonvention aller anderen Servicesfinlytic_{service}lautet (alsofinlytic_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
GetSummaryAsyncwirddecimal totalFees = positions.Sum(p => p.TotalFeesEur);berechnet, aber in der Equity-Formel nicht verwendet:decimal currentEquity = baseCapital + totalRealized + unrealizedPnl;(Hinweis:totalRealizedhat die Gebühren bereits bei Schließung abgezogen; die VariabletotalFeesist 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, dass1 = 1 €.
- Finlytics Kontoführung, synthetischer Ledger und Risikoberechnungen (
- Ungenauigkeit: Je nach EUR/USD-Wechselkurs (z.B. 1,08) weicht das tatsächliche Risiko um 8–15% 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:
CalculateEmagibt beicandles.Count < periodstrikt0mzurück.TrendPullbackFvgStrategyundMovingAverageCrossoverStrategyprüfen strikt\ge 205Kerzen, undTechnicalScoringEngineV2vergibt Confluence-Punkte nur beiEMA > 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.DefaultSlippagePercentwurde auf0.0mgesetzt.
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 1–3 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 nutzendecimal) - Problem:
In
CompositeOpportunityScorerV2wird(decimal)sentiment.CurrentSummary.CompoundScoregecastet. 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
FinlyticTechnicalsein starkes Short-Signal (Verkauf) generiert, sucht der Resolver ausschließlich nachknockOutProductmitOptionType.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:
EngineTradeEntityinFinlyticEnginebesitzt bereits einUserId-Feld für Multi-Tenancy.BotPositionEntityimFinlyticBotbesitzt jedoch keinUserId-Feld – alle Bot-Trades laufen in einem globalen Pool. - Erweiterung:
Erweiterung von
BotPositionEntityumUserIdund Filterung imBotControllernach 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:
_buffershält für jedes jemals abgefragte Asset einConcurrentDictionarymit 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.
MemoryCachemit 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 mitBrowserContext.CloseAsync()und Docker-Container-Speicherlimits (mem_limitincompose.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
ManagedMqttClientvorhanden, 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 |