docs: add comprehensive platform STATE.md and diagnostic PROBLEMS.md
This commit is contained in:
+221
@@ -0,0 +1,221 @@
|
|||||||
|
# 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](#1-kritische-bugs--logikfehler)
|
||||||
|
2. [Ursachen für Ungenauigkeiten (Inaccuracies & Drift)](#2-ursachen-für-ungenauigkeiten-inaccuracies--drift)
|
||||||
|
3. [Fehlende Funktionen & Architekturlücken](#3-fehlende-funktionen--architekturlücken)
|
||||||
|
4. [Skalierungs-, Performance- & Resilienz-Risiken](#4-skalierungs--performance---resilienz-risiken)
|
||||||
|
5. [Konkreter Maßnahmen- & Optimierungs-Fahrplan](#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 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`).
|
||||||
|
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 82–86)
|
||||||
|
- **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 **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**: `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 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 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 |
|
||||||
@@ -0,0 +1,612 @@
|
|||||||
|
# Finlytic Systemdokumentation (STATE.md)
|
||||||
|
|
||||||
|
Dieses Dokument bietet eine lückenlose, detaillierte und strukturierte Gesamtdokumentation der gesamten Finlytic-Plattform. Es umfasst die Architektur, alle Konfigurationen & Einstellungen, mathematische/finanzielle Formeln, sämtliche Schnittstellen (MQTT RPC, MQTT Pub/Sub, REST API, SignalR Hubs), Datenbankstrukturen sowie die genaue Funktionsweise der 9 Microservices und des Flutter-Frontends.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Inhaltsverzeichnis
|
||||||
|
1. [Systemarchitektur & Topologie](#1-systemarchitektur--topologie)
|
||||||
|
2. [Microservices-Übersicht & Datenbanken](#2-microservices-übersicht--datenbanken)
|
||||||
|
3. [Einstellungen & Konfiguration (Settings)](#3-einstellungen--konfiguration-settings)
|
||||||
|
4. [Mathematische, Technische & Finanzielle Formeln](#4-mathematische-technische--finanzielle-formeln)
|
||||||
|
5. [Schnittstellen & Endpunkte](#5-schnittstellen--endpunkte)
|
||||||
|
- [5.1 MQTT RPC-Kanäle](#51-mqtt-rpc-kanäle)
|
||||||
|
- [5.2 MQTT Pub/Sub Event-Topics](#52-mqtt-pubsub-event-topics)
|
||||||
|
- [5.3 REST API Endpunkte (FinlyticBackend)](#53-rest-api-endpunkte-finlyticbackend)
|
||||||
|
- [5.4 SignalR Hubs & Methoden](#54-signalr-hubs--methoden)
|
||||||
|
6. [Detaillierte Funktionsweise & Datenfluss](#6-detaillierte-funktionsweise--datenfluss)
|
||||||
|
7. [Frontend-Architektur (FinlyticApp)](#7-frontend-architektur-finlyticapp)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Systemarchitektur & Topologie
|
||||||
|
|
||||||
|
Finlytic ist eine modulare, ereignisgesteuerte Finanzanalyse- und automatisierte Trading-Plattform für Aktien und Derivate (Knock-Out-Zertifikate, Optionsscheine).
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ FinlyticApp (Flutter Web & Mobile) │
|
||||||
|
└───────────────────────────────────┬────────────────────────────────────┘
|
||||||
|
│ HTTP / WebSocket (SignalR)
|
||||||
|
▼
|
||||||
|
┌────────────────────────────────────────────────────────────────────────┐
|
||||||
|
│ FinlyticBackend (API & Gateway) │
|
||||||
|
└───────────────────────────────────┬────────────────────────────────────┘
|
||||||
|
│ MQTT RPC & Pub/Sub
|
||||||
|
┌──────────────┬───────────────┼──────────────┬──────────────┐
|
||||||
|
▼ ▼ ▼ ▼ ▼
|
||||||
|
┌──────────┐ ┌──────────────┐ ┌───────────┐ ┌─────────────┐ ┌────────────┐
|
||||||
|
│Finlytic │ │FinlyticNews │ │Finlytic │ │Finlytic │ │Finlytic │
|
||||||
|
│Assets │ │ │ │Sentiment │ │Fundamentals │ │Technicals │
|
||||||
|
└────┬─────┘ └──────┬───────┘ └─────┬─────┘ └──────┬──────┘ └─────┬──────┘
|
||||||
|
│ │ │ │ │
|
||||||
|
└──────────────┴───────┬───────┴──────────────┴──────────────┘
|
||||||
|
│ MQTT (Signale, Scores, Setups)
|
||||||
|
┌──────────────────────┼──────────────────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌──────────┐ ┌──────────────┐ ┌────────────┐
|
||||||
|
│Finlytic │ ──────► │FinlyticBot │ │Finlytic │
|
||||||
|
│Engine │ (Trades)│(Auto-Trading)│ │Simulation │
|
||||||
|
└────┬─────┘ └──────────────┘ └────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────┐
|
||||||
|
│Finlytic │ ──────► ntfy Push-Server (Mobil & Webhooks)
|
||||||
|
│Notify │
|
||||||
|
└──────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kernprinzipien & Regeln (Rules.md):
|
||||||
|
1. **MQTT-Exklusivität im Backend**: Alle internen Microservices kommunizieren ausschließlich über MQTT. Es gibt keine direkten HTTP-Verbindungen zwischen Backend-Diensten.
|
||||||
|
2. **Einziges Web-Gateway**: `FinlyticBackend` ist der einzige Dienst mit Kestrel-HTTP/WebSocket-Port (`5000:8080`).
|
||||||
|
3. **Strikte Datenisolation**: Jeder Service besitzt seine eigene PostgreSQL-Datenbank (keine geteilten Tabellen).
|
||||||
|
4. **Dynamische Konfiguration**: Dynamic Settings (`ISettingsService`) werden in DB persistiert und per MQTT aktualisiert, ohne Neustart.
|
||||||
|
5. **Kanalbasiertes Logging**: Jeder Service sendet strukturierte Logs per MQTT (`finlytic/logs/{service}`), die im Admin-Panel live gestreamt werden.
|
||||||
|
6. **Keine Scheindaten**: Reine Echtdaten oder explizite Empty-States/Exceptions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Microservices-Übersicht & Datenbanken
|
||||||
|
|
||||||
|
| Service | Typ / Basis | PostgreSQL-Datenbank | Hauptaufgabe |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| **FinlyticCore** | Shared Class Library | *(Keine eigene DB)* | Gemeinsame DTOs, Enums, MQTT-Clients, TradeRepublic-Client, Settings-Interface. |
|
||||||
|
| **FinlyticAssets** | Background Worker | `finlytic_assets` | Stammdaten-Synchronisation (Stocks, ETFs), Lokale Logo-Speicherung, Trade Republic Ticker-Proxy, KO-Derivate-Abfrage. |
|
||||||
|
| **FinlyticNews** | Playwright Worker | `finlytic_news` | Scraping von 10 Finanzportalen, Duplikaterkennung (SimHash/Jaccard), Regex/NLP-Asset-Matching, Sector-Clustering. |
|
||||||
|
| **FinlyticSentiment** | Background Worker | `finlytic_sentimental` | FinBERT KI-Sentiment-Analyse (Deutsch & Englisch Webhooks), Exponentielle Zeit-Decay-Gewichtung ($\lambda = \ln(2)/\tau$). |
|
||||||
|
| **FinlyticFundamentals** | Playwright Worker | `finlytic_fundamentals`| Fundamentaldaten & Kennzahlen (KGV, ROE, Cashflow, Analysten-Ratings, Dividenden, Earnings-Kalender). |
|
||||||
|
| **FinlyticTechnicals** | Background Worker | `finlytic_ta` | Multi-Timeframe-Kerzen (15m, 1h, 1d), 10 Kernstrategien, 15 Pattern-Detektoren (SMC & Chart), Symmetrisches Scoring V2. |
|
||||||
|
| **FinlyticEngine** | Background Worker | `finlytic_engine` | Composite Opportunity Scorer (COS V2), Earnings/Dividenden-Sperren, n8n AI Reasoning Gate, Trade Lifecycle & Monitoring. |
|
||||||
|
| **FinlyticSimulation** | Background Worker | `finlytic_simulation` | Quantitative Backtesting-Engine, Replay-Runner (Anti-Lookahead), Zuverlässigkeitsmatrix, Slippage- & Gebührenmodellierung. |
|
||||||
|
| **FinlyticBot** | Background Worker | `finlytic_bot` | Automatisierte Orderausführung (1-2% Risikoregel), Alpaca Paper Trading (US-Equities) & Interner Synthetischer Ledger. |
|
||||||
|
| **FinlyticNotify** | Background Worker | `finlytic_notify` | Push-Benachrichtigungen via ntfy (Proposals, Trade-Events, Bot-Status, News). |
|
||||||
|
| **FinlyticBackend** | ASP.NET Core Kestrel | `finlytic_backend` | JWT-Authentifizierung, User- & Favoritenverwaltung, SignalR-Streaming, MQTT-Bridge. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Einstellungen & Konfiguration (Settings)
|
||||||
|
|
||||||
|
### 3.1 Umgebungsvariablen (`compose.yaml` / `.env`)
|
||||||
|
|
||||||
|
| Variable | Standardwert | Beschreibung |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `DB_HOST` | `OmniDB` | Hostname der PostgreSQL-Instanz |
|
||||||
|
| `DB_PORT` | `5432` | Port der PostgreSQL-Instanz |
|
||||||
|
| `DB_PASSWORD` | *(Pflichtfeld)* | Passwort für den PostgreSQL-Benutzer `admin` |
|
||||||
|
| `MQTT_HOST` | `host.docker.internal` | Hostname des MQTT-Brokers (z.B. Mosquitto) |
|
||||||
|
| `MQTT_PORT` | `4545` | Port des MQTT-Brokers |
|
||||||
|
| `JWT_SECRET_KEY` | *(Pflichtfeld, $\ge 32$ Zeichen)* | Signaturschlüssel für JWT-Token |
|
||||||
|
| `ADMIN_DEFAULT_PASSWORD` | *(Pflichtfeld)* | Initiales Passwort für den Standard-Admin |
|
||||||
|
| `FINLYTIC_DATA_ROOT` | `C:/Users/larsh/Documents/docker/finlytic` | Pfad für persistente Assets (Logos, Index) |
|
||||||
|
| `NTFY_BASE_URL` | `http://host.docker.internal:8080` | Basis-URL des ntfy-Push-Servers |
|
||||||
|
| `Webhooks__German` | `https://n8n.kleidukos.me/webhook/sentiment/de` | FinBERT Webhook für deutsche Artikel |
|
||||||
|
| `Webhooks__English` | `https://n8n.kleidukos.me/webhook/sentiment/en` | FinBERT Webhook für englische Artikel |
|
||||||
|
| `Ai__N8nValidationWebhookUrl`| `https://n8n.kleidukos.me/webhook/trade-validation` | n8n Webhook für AI-Trade-Validierung |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 Dynamische Service-Einstellungen (`ISettingsService`)
|
||||||
|
|
||||||
|
Jeder Microservice verwaltet typisierte, zur Laufzeit änderbare Konfigurationswerte:
|
||||||
|
|
||||||
|
#### **FinlyticAssets (`SettingKeys.cs`)**
|
||||||
|
- `Logging.Channel.Assets` (bool, default: `true`): Logging für Asset-Scans
|
||||||
|
- `Logging.Channel.MQTT` (bool, default: `true`): Logging für MQTT-Verkehr
|
||||||
|
- `Logging.Channel.Health` (bool, default: `true`): Logging für Ping-Healthchecks
|
||||||
|
- `Logging.Channel.TradeRepublic` (bool, default: `true`): Logging für TR-WebSocket
|
||||||
|
- `TradeRepublic.WsReconnectIntervalSeconds` (int, default: `5`): Reconnect-Wartezeit
|
||||||
|
- `TradeRepublic.WsTimeoutSeconds` (int, default: `15`): Timeout für TR-Anfragen
|
||||||
|
- `Scanner.EnableAutoScan` (bool, default: `true`): Automatischer Asset-Sync aktiviert
|
||||||
|
- `Scanner.CurrentScanningType` (string, default: `"Stock"`): Aktueller Typ im Loop
|
||||||
|
- `Scanner.CurrentScanningPage` (int, default: `0`): Aktuelle Paginierungsseite (Recovery-Modus)
|
||||||
|
- `Scanner.FinishedInitialScan` (bool, default: `false`): Status des Initial-Scans
|
||||||
|
- `Scanner.BatchAssetUpdateDelay` (int, default: `0`): Pause zwischen Batches (Sekunden)
|
||||||
|
- `Scanner.AssetUpdateTypeDelay` (int, default: `0`): Pause zwischen Typen (Sekunden)
|
||||||
|
- `Scanner.TradeRepublicMaxRequestPageSize` (int, default: `50`): Batchgröße pro TR-Call
|
||||||
|
- `Scanner.CycleDelayMinutes` (int, default: `1440`): Wartezeit bis zum nächsten Vollscan (24h)
|
||||||
|
|
||||||
|
#### **FinlyticNews (`SettingKeys.cs`)**
|
||||||
|
- `Logging.Channel.News` (bool, default: `true`): News-Verarbeitungs-Logs
|
||||||
|
- `Logging.Channel.Scraper` (bool, default: `true`): Scraper-Adapter-Logs
|
||||||
|
- `Logging.Channel.Matcher` (bool, default: `true`): In-Memory Asset-Matcher-Logs
|
||||||
|
- `Logging.Channel.Deduplication` (bool, default: `true`): Duplikaterkennungs-Logs
|
||||||
|
- `Scraping.IntervalMinutes` (int, default: `15`): Scraping-Intervall
|
||||||
|
- `Scraping.MaxArticlesPerFeed` (int, default: `20`): Maximale Artikel pro Feed
|
||||||
|
- `Feature.EnableAutoScraping` (bool, default: `true`): Automatisches Scraping aktiv
|
||||||
|
- `Scraping.HttpTimeoutSeconds` (int, default: `30`): Timeout für HTTP/Playwright
|
||||||
|
- `Deduplication.TitleSimilarityThreshold` (double, default: `0.85`): Jaccard-Schwellenwert
|
||||||
|
- `Deduplication.SimHashMaxHammingDistance` (int, default: `3`): Max. SimHash-Bitdistanz
|
||||||
|
- `Deduplication.WindowDays` (int, default: `7`): Historienfenster für Duplikate
|
||||||
|
- `Matching.MinNameLength` (int, default: `3`): Minimale Zeichenlänge für Namensmatching
|
||||||
|
- `Matching.EnableSectorClustering` (bool, default: `true`): Sektorenprüfung bei Einzeltreffern
|
||||||
|
- `Matching.RequireFinancialContextForShortNames` (bool, default: `true`): Finanzkontext für kurze Namen
|
||||||
|
- `Data.ArticleRetentionDays` (int, default: `90`): Aufbewahrungsdauer für News
|
||||||
|
|
||||||
|
#### **FinlyticSentiment (`SettingKeys.cs`)**
|
||||||
|
- `Logging.Channel.Sentiment` (bool, default: `true`): Sentiment-Logs
|
||||||
|
- `Sentiment.GermanWebhookUrl` (string, default: `https://n8n.kleidukos.me/webhook/sentiment/de`)
|
||||||
|
- `Sentiment.EnglishWebhookUrl` (string, default: `https://n8n.kleidukos.me/webhook/sentiment/en`)
|
||||||
|
- `Sentiment.MinimumConfidenceThreshold` (double, default: `0.60`): Mindestkonfidenz
|
||||||
|
- `Sentiment.TimeDecayHalfLifeDays` (double, default: `7.0`): Halbwertszeit $\tau$ für Zeit-Decay
|
||||||
|
- `Sentiment.SentimentWindowDays` (int, default: `30`): Zeitfenster für Aggregation
|
||||||
|
- `Sentiment.AnalysisBatchSize` (int, default: `10`): Artikel pro Analysezyklus
|
||||||
|
- `Sentiment.PollIntervalSeconds` (int, default: `30`): Polling für neue Artikel
|
||||||
|
- `Sentiment.EnableAutoSentiment` (bool, default: `true`): Automatische Analyse aktiv
|
||||||
|
|
||||||
|
#### **FinlyticFundamentals (`SettingKeys.cs`)**
|
||||||
|
- `Logging.Channel.Fundamentals` (bool, default: `true`): Fundamentaldaten-Logs
|
||||||
|
- `Logging.Channel.HtmlScrapper` (bool, default: `true`): Playwright-Scraper-Logs
|
||||||
|
- `Logging.Channel.YahooClient` (bool, default: `true`): Yahoo Finance API-Logs
|
||||||
|
- `Feature.EnableHtmlFallback` (bool, default: `true`): HTML-Scraping falls API fehlt
|
||||||
|
- `Scraper.ForceHtmlFallback` (bool, default: `false`): HTML-Scraping erzwingen
|
||||||
|
- `Feature.AllowForceRefresh` (bool, default: `true`): Cache-Umgehung erlauben
|
||||||
|
- `Cache.FundamentalDataValidityDays` (int, default: `30`): Cache-Gültigkeit
|
||||||
|
|
||||||
|
#### **FinlyticTechnicals (`SettingKeys.cs`)**
|
||||||
|
- `Logging.Channel.TechnicalAnalysis` (bool, default: `true`): TA-Berechnungs-Logs
|
||||||
|
- `Indicators.RsiPeriod` (int, default: `14`): RSI-Periode
|
||||||
|
- `Indicators.MacdFastPeriod` (int, default: `12`): MACD Fast EMA
|
||||||
|
- `Indicators.MacdSlowPeriod` (int, default: `26`): MACD Slow EMA
|
||||||
|
- `Indicators.MacdSignalPeriod` (int, default: `9`): MACD Signal Line
|
||||||
|
- `Indicators.EmaShortPeriod` (int, default: `50`): EMA Short
|
||||||
|
- `Indicators.EmaLongPeriod` (int, default: `200`): EMA Long
|
||||||
|
- `Indicators.BollingerBandsPeriod` (int, default: `20`): Bollinger-Periode
|
||||||
|
- `Indicators.BollingerBandsStdDev` (double, default: `2.0`): Bollinger Standardabweichung
|
||||||
|
- `Indicators.AtrPeriod` (int, default: `14`): ATR-Periode
|
||||||
|
- `Cache.DurationMinutes` (int, default: `60`): Cache-Dauer
|
||||||
|
|
||||||
|
#### **FinlyticEngine (`EngineSettingKeys.cs`)**
|
||||||
|
- `Engine.MinCompositeScore` (decimal, default: `75.0`): Mindest-Gesamtscore für Proposals
|
||||||
|
- `Engine.WeightTechnical` (decimal, default: `0.45`): Gewichtung Technik (45%)
|
||||||
|
- `Engine.WeightSentiment` (decimal, default: `0.35`): Gewichtung Sentiment (35%)
|
||||||
|
- `Engine.WeightFundamental` (decimal, default: `0.20`): Gewichtung Fundamentaldaten (20%)
|
||||||
|
- `Engine.EarningsLockoutDays` (int, default: `2`): Vorlaufzeit vor Earnings (Score-Suppression)
|
||||||
|
- `Engine.DividendGateDays` (int, default: `1`): Vorlaufzeit vor Ex-Dividende
|
||||||
|
- `Engine.MinDerivativeLeverage` (decimal, default: `5.0`): Mindesthebel für KO-Derivate
|
||||||
|
- `Engine.TargetDefaultLeverage` (decimal, default: `7.0`): Zielhebel für KO-Derivate
|
||||||
|
- `Engine.KnockOutSafetyBufferPercent` (decimal, default: `2.0`): Sicherheitsabstand Barrier zu SL
|
||||||
|
- `Engine.AiValidationTimeoutSeconds` (int, default: `15`): Timeout für n8n AI-Validierung
|
||||||
|
- `Engine.EnableAiValidation` (bool, default: `true`): KI-Gate aktiv (sonst Fast-Pass)
|
||||||
|
- `Engine.EnablePaperTradingBot` (bool, default: `false`): Automatische Bot-Ausführung
|
||||||
|
- `Engine.PollingIntervalSeconds` (int, default: `120`): Poller-Intervall (Opportunity-Scan)
|
||||||
|
- `Engine.MonitoringIntervalSeconds` (int, default: `60`): Aktives Trade-Monitoring-Intervall
|
||||||
|
- `Engine.PollerMinScore` (decimal, default: `70.0`): Mindestscore für FTA-Abfrage
|
||||||
|
- `Engine.PollerTopPicksOnly` (bool, default: `true`): Nur Top-Picks abfragen ($\ge 75$)
|
||||||
|
- `Engine.PollerLimit` (int, default: `25`): Max. Setups pro Scan
|
||||||
|
- `Engine.ProposalValidityHours` (int, default: `24`): Gültigkeitsdauer eines Vorschlags (24h)
|
||||||
|
|
||||||
|
#### **FinlyticSimulation (`SimulationSettingKeys.cs`)**
|
||||||
|
- `Simulation.DefaultSlippagePercent` (decimal, default: `0.00`): Slippage deaktiviert (wird in Ordergebühren `DefaultOrderFeeEur` abgebildet)
|
||||||
|
- `Simulation.DefaultOrderFeeEur` (decimal, default: `1.00`): Ordergebühr pro Transaktion (1 €)
|
||||||
|
- `Simulation.DefaultStartingCapital` (decimal, default: `10000.00`): Startkapital für Backtests
|
||||||
|
- `Simulation.MinSampleTradesForApproval` (int, default: `5`): Mindest-Trades für Matrix-Zulassung
|
||||||
|
- `Simulation.HighProfitFactorThreshold` (decimal, default: `1.60`): PF für Score-Bonus (+15 Pkt)
|
||||||
|
- `Simulation.LowProfitFactorThreshold` (decimal, default: `1.00`): PF für Veto-Sperre
|
||||||
|
- `Simulation.KnockOutBarrierBufferPercent` (decimal, default: `2.0`): KO-Barrier-Simulation
|
||||||
|
- `Simulation.DefaultTrailingStopPercent` (decimal, default: `3.0`): Fallback-Trailing-Stop
|
||||||
|
- `Simulation.EnableScheduledMatrixRecompute` (bool, default: `true`): Periodische Matrix-Neuberechnung
|
||||||
|
- `Simulation.MatrixRecomputeIntervalHours` (int, default: `24`): Matrix-Stale-Schwelle (24h)
|
||||||
|
- `Simulation.MatrixRecomputeCheckIntervalMinutes` (int, default: `60`): Recompute-Check-Intervall
|
||||||
|
|
||||||
|
#### **FinlyticBot (`BotSettingKeys.cs`)**
|
||||||
|
- `Alpaca.KeyId` (string): Alpaca API Key
|
||||||
|
- `Alpaca.SecretKey` (string): Alpaca Secret Key
|
||||||
|
- `Alpaca.IsPaper` (bool, default: `true`): Alpaca Paper vs. Live
|
||||||
|
- `Bot.EnableAutoExecution` (bool, default: `true`): Automatische Ausführung aktiv
|
||||||
|
- `Bot.RiskPerTradePercent` (decimal, default: `1.0`): 1% Risiko pro Trade bezogen auf Gesamtkapital
|
||||||
|
- `Bot.MaxPositionAllocationPercent` (decimal, default: `20.0`): Max. 20% Kapital pro Einzelposition
|
||||||
|
- `Bot.MaxConcurrentPositions` (int, default: `5`): Max. 5 offene Positionen gleichzeitig
|
||||||
|
- `Bot.DailyLossLimitPercent` (decimal, default: `3.0`): Täglicher Verluststopp (3%)
|
||||||
|
- `Bot.MonitoringIntervalSeconds` (int, default: `15`): Bot-Positionsüberwachung (15s)
|
||||||
|
- `Bot.SyntheticBaseCapitalEur` (decimal, default: `50000.0`): Startkapital Synthetischer Ledger
|
||||||
|
|
||||||
|
#### **FinlyticNotify (`NotifySettingKeys.cs`)**
|
||||||
|
- `Ntfy.BaseUrl` (string, default: `http://localhost:8080`)
|
||||||
|
- `Ntfy.TopicPrefix` (string, default: `finlytic`)
|
||||||
|
- `Ntfy.BroadcastChannel` (string, default: `broadcast`)
|
||||||
|
- `Ntfy.NewsChannel` (string, default: `news`)
|
||||||
|
- `Ntfy.DefaultUsername` (string, default: `admin`)
|
||||||
|
- `Ntfy.MinProposalScore` (decimal, default: `70.0`)
|
||||||
|
- `Ntfy.NotifyOnProposals` (bool, default: `true`)
|
||||||
|
- `Ntfy.NotifyOnTradeUpdates` (bool, default: `true`)
|
||||||
|
- `Ntfy.NotifyOnBotTrades` (bool, default: `true`)
|
||||||
|
- `Ntfy.NotifyOnNews` (bool, default: `true`)
|
||||||
|
- `Ntfy.ClickBaseUrl` (string, default: `http://localhost:3000`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Mathematische, Technische & Finanzielle Formeln
|
||||||
|
|
||||||
|
### 4.1 Technische Indikatoren (`TechnicalIndicatorsEngine.cs`)
|
||||||
|
|
||||||
|
#### 1. Simple Moving Average (SMA)
|
||||||
|
$$\text{SMA}_n = \frac{1}{n} \sum_{i=0}^{n-1} P_{t-i}$$
|
||||||
|
|
||||||
|
#### 2. Exponential Moving Average (EMA)
|
||||||
|
Glättungsfaktor $k$:
|
||||||
|
$$k = \frac{2}{n + 1}$$
|
||||||
|
$$\text{EMA}_t = (P_t \cdot k) + (\text{EMA}_{t-1} \cdot (1 - k))$$
|
||||||
|
*(Initialisierung über SMA der ersten $n$ Kerzen)*
|
||||||
|
|
||||||
|
#### 3. Relative Strength Index (RSI - Wilder's Smoothing)
|
||||||
|
Gewinne $U_t = \max(0, P_t - P_{t-1})$, Verluste $D_t = \max(0, P_{t-1} - P_t)$
|
||||||
|
$$\overline{U}_t = \frac{\overline{U}_{t-1} \cdot (n-1) + U_t}{n}, \quad \overline{D}_t = \frac{\overline{D}_{t-1} \cdot (n-1) + D_t}{n}$$
|
||||||
|
$$\text{RS} = \frac{\overline{U}_t}{\overline{D}_t}, \quad \text{RSI} = 100 - \frac{100}{1 + \text{RS}}$$
|
||||||
|
|
||||||
|
#### 4. Average True Range (ATR)
|
||||||
|
$$\text{TR}_t = \max \left( H_t - L_t, \, |H_t - C_{t-1}|, \, |L_t - C_{t-1}| \right)$$
|
||||||
|
$$\text{ATR}_n = \frac{1}{n} \sum_{i=0}^{n-1} \text{TR}_{t-i}$$
|
||||||
|
|
||||||
|
#### 5. Moving Average Convergence Divergence (MACD)
|
||||||
|
$$\text{MACD Line} = \text{EMA}_{12}(P) - \text{EMA}_{26}(P)$$
|
||||||
|
$$\text{Signal Line} = \text{EMA}_9(\text{MACD Line})$$
|
||||||
|
$$\text{Histogram} = \text{MACD Line} - \text{Signal Line}$$
|
||||||
|
|
||||||
|
#### 6. Bollinger Bands & %B
|
||||||
|
$$\text{Middle Band} = \text{SMA}_{20}(P)$$
|
||||||
|
$$\sigma = \sqrt{\frac{1}{20} \sum_{i=0}^{19} (P_{t-i} - \text{Middle Band})^2}$$
|
||||||
|
$$\text{Upper Band} = \text{Middle Band} + 2\sigma, \quad \text{Lower Band} = \text{Middle Band} - 2\sigma$$
|
||||||
|
$$\text{Bandwidth} = \frac{\text{Upper} - \text{Lower}}{\text{Middle}} \cdot 100, \quad \%B = \frac{P_t - \text{Lower}}{\text{Upper} - \text{Lower}}$$
|
||||||
|
|
||||||
|
#### 7. Keltner Channels & Volatility Squeeze
|
||||||
|
$$\text{KC Middle} = \text{EMA}_{20}(P), \quad \text{KC Upper} = \text{EMA}_{20} + 1.5 \cdot \text{ATR}_{20}, \quad \text{KC Lower} = \text{EMA}_{20} - 1.5 \cdot \text{ATR}_{20}$$
|
||||||
|
$$\text{Squeeze On} \iff \text{BB Lower} > \text{KC Lower} \quad \text{UND} \quad \text{BB Upper} < \text{KC Upper}$$
|
||||||
|
|
||||||
|
#### 8. SuperTrend
|
||||||
|
$$\text{HL2} = \frac{H_t + L_t}{2}$$
|
||||||
|
$$\text{Upper Band} = \text{HL2} + 3.0 \cdot \text{ATR}_{10}, \quad \text{Lower Band} = \text{HL2} - 3.0 \cdot \text{ATR}_{10}$$
|
||||||
|
|
||||||
|
#### 9. Average Directional Index (ADX / DMI)
|
||||||
|
$$+\text{DM} = \begin{cases} H_t - H_{t-1} & \text{falls } H_t - H_{t-1} > L_{t-1} - L_t \text{ und } > 0 \\ 0 & \text{sonst} \end{cases}$$
|
||||||
|
$$-\text{DM} = \begin{cases} L_{t-1} - L_t & \text{falls } L_{t-1} - L_t > H_t - H_{t-1} \text{ und } > 0 \\ 0 & \text{sonst} \end{cases}$$
|
||||||
|
$$+\text{DI}_{14} = \frac{\sum +\text{DM}}{\sum \text{TR}} \cdot 100, \quad -\text{DI}_{14} = \frac{\sum -\text{DM}}{\sum \text{TR}} \cdot 100$$
|
||||||
|
$$\text{DX} = \frac{|+\text{DI} - -\text{DI}|}{+\text{DI} + -\text{DI}} \cdot 100, \quad \text{ADX} = \text{SMA}_{14}(\text{DX})$$
|
||||||
|
|
||||||
|
#### 10. Volume Weighted Average Price (VWAP)
|
||||||
|
$$\text{VWAP} = \frac{\sum_{i=1}^N \left( \frac{H_i + L_i + C_i}{3} \cdot V_i \right)}{\sum_{i=1}^N V_i}$$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.2 Symmetrisches Technisches Scoring V2 (`TechnicalScoringEngineV2.cs`)
|
||||||
|
|
||||||
|
$$\text{FinalScore} = \text{Clamp}\Big( (0.35 \cdot S_{\text{Ind}}) + (0.35 \cdot S_{\text{Pattern}}) + (0.30 \cdot S_{\text{BaseStrategy}}), \; 0, \; 100 \Big)$$
|
||||||
|
|
||||||
|
#### Indikator-Confluence ($S_{\text{Ind}}$ Basis: 50 Pkt):
|
||||||
|
- **Buy (Long)**:
|
||||||
|
- $\text{EMA}_{20} > \text{EMA}_{50} \implies +15$ Pkt
|
||||||
|
- $\text{RSI}_{14} \in [45, 65] \implies +15$ Pkt
|
||||||
|
- $\text{ADX}_{14} \ge 25 \implies +10$ Pkt
|
||||||
|
- $P > \text{VWAP} \text{ oder } \text{EMA}_{20} > \text{VWAP} \implies +10$ Pkt
|
||||||
|
- **Sell (Short)**:
|
||||||
|
- $\text{EMA}_{20} < \text{EMA}_{50} \implies +15$ Pkt
|
||||||
|
- $\text{RSI}_{14} \in [35, 55] \implies +15$ Pkt
|
||||||
|
- $\text{ADX}_{14} \ge 25 \implies +10$ Pkt
|
||||||
|
- $P < \text{VWAP} \text{ oder } \text{EMA}_{20} < \text{VWAP} \implies +10$ Pkt
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.3 Exponentielles Zeit-Decay-Sentiment (`SentimentDbService.cs`)
|
||||||
|
|
||||||
|
Jeder Artikel $i$ hat Alter $\Delta t_i = \text{Now} - t_{\text{published}}$ in Tagen und FinBERT-Konfidenz $C_i$.
|
||||||
|
Abklingkonstante $\lambda$:
|
||||||
|
$$\lambda = \frac{\ln(2)}{\tau} \quad (\tau = \text{HalfLifeDays}, \text{ Standard: } 7.0)$$
|
||||||
|
Gewicht des Artikels $w_i$:
|
||||||
|
$$w_i = \max(0.01, C_i) \cdot e^{-\lambda \cdot \Delta t_i}$$
|
||||||
|
Aggregierter gewichteter Sentiment-Score $S_{\text{weighted}} \in [-1.0, +1.0]$:
|
||||||
|
$$S_{\text{weighted}} = \frac{\sum_{i=1}^N (w_i \cdot \text{CompoundScore}_i)}{\sum_{i=1}^N w_i}$$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.4 Composite Opportunity Score (COS V2) (`CompositeOpportunityScorerV2.cs`)
|
||||||
|
|
||||||
|
Gewichtete Faktoren:
|
||||||
|
- Technischer Score $S_{\text{Tech}} \in [0, 100]$ (Gewicht: $w_{\text{Tech}} = 0.45$)
|
||||||
|
- Sentiment Score $S_{\text{Sent}} \in [0, 100]$ (Gewicht: $w_{\text{Sent}} = 0.35$):
|
||||||
|
- Für Buy: $S_{\text{Sent}} = \frac{S_{\text{weighted}} + 1}{2} \cdot 100$
|
||||||
|
- Für Sell: $S_{\text{Sent}} = \frac{1 - S_{\text{weighted}}}{2} \cdot 100$
|
||||||
|
- Fundamentaler Score $S_{\text{Fund}} \in [0, 100]$ (Gewicht: $w_{\text{Fund}} = 0.20$):
|
||||||
|
- Richtungsabhängige Bewertung von KGV, ROE, Debt/Equity, Consensus-Rating und Short-Interest.
|
||||||
|
- Simulations-Matrix-Bonus: $B_{\text{Sim}} = +15$ falls $\text{PF} \ge 1.60$, Veto-Multiplikator $M_{\text{Veto}} = 0.20$ falls $\text{PF} < 1.00$.
|
||||||
|
- Sperr-Multiplikatoren:
|
||||||
|
- Earnings-Sperre: $M_{\text{Earnings}} = 0.15$ falls $\text{Tage zu Earnings} \le 2$.
|
||||||
|
- Dividenden-Sperre: $M_{\text{Dividend}} = 0.50$ falls $\text{Tage zu Ex-Dividende} \le 1$.
|
||||||
|
|
||||||
|
$$\text{RawScore} = (w_{\text{Tech}} \cdot S_{\text{Tech}}) + (w_{\text{Sent}} \cdot S_{\text{Sent}}) + (w_{\text{Fund}} \cdot S_{\text{Fund}}) + B_{\text{Sim}}$$
|
||||||
|
$$\text{COS} = \text{Clamp}\Big( \text{RawScore} \cdot M_{\text{Earnings}} \cdot M_{\text{Dividend}} \cdot M_{\text{Veto}}, \; 0, \; 100 \Big)$$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.5 Positionsgrößenbestimmung & Risikomodell (1-2% Regel) (`BotOrderExecutor.cs`)
|
||||||
|
|
||||||
|
Gesamtes Kontokapital $E$, Risiko pro Trade $R_{\%} = 1.0\%$, Maximalallokation $A_{\%} = 20.0\%$.
|
||||||
|
$$\text{MaxRiskCapital} = E \cdot \frac{R_{\%}}{100}$$
|
||||||
|
$$\text{UnitRisk} = |\text{EntryPrice} - \text{StopLossPrice}|$$
|
||||||
|
Berechnete Stückzahl $Q_{\text{calc}}$:
|
||||||
|
$$Q_{\text{calc}} = \frac{\text{MaxRiskCapital}}{\text{UnitRisk}}$$
|
||||||
|
Allokations-Deckelung:
|
||||||
|
$$Q_{\text{max}} = \frac{E \cdot \frac{A_{\%}}{100}}{\text{EntryPrice}}$$
|
||||||
|
$$Q_{\text{final}} = \max\Big(1, \, \text{Round}\big(\min(Q_{\text{calc}}, Q_{\text{max}})\big)\Big)$$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.6 Quantitative Simulations- & Performancemetriken (`VirtualBacktestBroker.cs`)
|
||||||
|
|
||||||
|
- **Win Rate (WR)**:
|
||||||
|
$$\text{WR} = \frac{N_{\text{Wins}}}{N_{\text{Trades}}} \cdot 100$$
|
||||||
|
- **Profit Factor (PF)**:
|
||||||
|
$$\text{PF} = \frac{\sum \text{Gewinne}}{\sum |\text{Verluste}|}$$
|
||||||
|
- **Erwartungswert (Expectancy in €)**:
|
||||||
|
$$\text{Expectancy} = \left(\frac{\text{WR}}{100} \cdot \overline{\text{Win}}\right) - \left(\left(1 - \frac{\text{WR}}{100}\right) \cdot \overline{\text{Loss}}\right)$$
|
||||||
|
- **Annualisierte Sharpe Ratio**:
|
||||||
|
$$\overline{R} = \frac{1}{N}\sum R_i, \quad \sigma_R = \sqrt{\frac{1}{N-1}\sum (R_i - \overline{R})^2}$$
|
||||||
|
$$\text{Sharpe Ratio} = \frac{\overline{R}}{\sigma_R} \cdot \sqrt{252}$$
|
||||||
|
- **R-Multiple**:
|
||||||
|
$$R_{\text{mult}} = \frac{\text{Realisierter PnL}}{\text{UnitRisk} \cdot \text{Menge}}$$
|
||||||
|
- **Max Adverse / Favorable Excursion (MAE / MFE)**:
|
||||||
|
$$\text{MAE}_{\text{Long}} = \frac{P_{\text{Entry}} - P_{\text{Min}}}{P_{\text{Entry}}} \cdot 100, \quad \text{MFE}_{\text{Long}} = \frac{P_{\text{Max}} - P_{\text{Entry}}}{P_{\text{Entry}}} \cdot 100$$
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Schnittstellen & Endpunkte
|
||||||
|
|
||||||
|
### 5.1 MQTT RPC-Kanäle
|
||||||
|
|
||||||
|
Schema: Request auf `services/request/{channel}/{correlationId}`, Response auf `services/response/{channel}/{correlationId}`.
|
||||||
|
|
||||||
|
| Kanalname (`MqttTopics.Channels`) | Betreuender Service | Request-DTO | Response-DTO | Beschreibung |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| `health_Ping` | *(Alle Services)* | `object` | `ServiceHealthResponse` | Liveness-Check pro Service |
|
||||||
|
| `assets_Get` | FinlyticAssets | `GetValidAssetRequest` | `List<AssetDto>` | Stammdaten für ISIN auflösen |
|
||||||
|
| `assets_GetDiscovery` | FinlyticAssets | `GetDiscoveryAssetsRequest` | `List<AssetDto>` | Kuratierte Discovery-Assets |
|
||||||
|
| `assets_GetDerivatives` | FinlyticAssets | `GetDerivativesRequest` | `List<DerivativeDto>` | KO-Derivate nach Hebel/Typ suchen |
|
||||||
|
| `tr_GetLivePrice` | FinlyticAssets | `IsinRequest` | `LivePriceDto?` | Realtime-Kurs via Trade Republic |
|
||||||
|
| `assets_settings_GetAll` | FinlyticAssets | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `assets_settings_Update` | FinlyticAssets | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `news_Get` | FinlyticNews | `DailyNewsRequest` | `List<NewsArticleDto>` | Paginierte/gefilterte News |
|
||||||
|
| `news_GetById` | FinlyticNews | `ArticleRequest` | `NewsArticleDto?` | Einzelartikel nach ID |
|
||||||
|
| `news_GetPending` | FinlyticNews | `object` | `List<NewsArticleDto>` | Artikel zur Sentiment-Analyse |
|
||||||
|
| `news_UpdateStatus` | FinlyticNews | `UpdateNewsStatusRequest` | `UpdateNewsStatusResponse` | Artikel-Status aktualisieren |
|
||||||
|
| `news_settings_GetAll` | FinlyticNews | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `news_settings_Update` | FinlyticNews | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `sentiment_GetIsin` | FinlyticSentiment | `GetSentimentByIsinRequest` | `IsinSentimentSummaryDto?` | Aggregiertes Sentiment für ISIN |
|
||||||
|
| `sentiment_GetSector` | FinlyticSentiment | `GetSectorSentimentRequest` | `SectorSentimentSummaryDto?`| Sektoren-Sentiment |
|
||||||
|
| `sentiment_GetArticle` | FinlyticSentiment | `ArticleRequest` | `IsinAnalysisEntry?` | FinBERT-Ergebnis für Artikel |
|
||||||
|
| `sentiment_GetAll` | FinlyticSentiment | `PaginatedRequest` | `List<CompanySentimentSummaryEntity>` | Alle Unternehmens-Sentiments |
|
||||||
|
| `sentiment_Analyze` | FinlyticSentiment | `JsonElement` / `NewsArticleDto` | `IsinAnalysisEntry?` | Ad-hoc FinBERT-Analyse |
|
||||||
|
| `sentiment_settings_GetAll` | FinlyticSentiment | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `sentiment_settings_Update` | FinlyticSentiment | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `fundamentals_Get` | FinlyticFundamentals | `IsinRequest` / `GetFundamentalsRequest` | `AssetFundamentalsDto?` | Fundamentaldaten & Kennzahlen |
|
||||||
|
| `events_GetAll` | FinlyticFundamentals | `object` | `List<CorporateEventDto>` | Alle Termine/Events |
|
||||||
|
| `events_GetByMonth` | FinlyticFundamentals | `GetEventsByMonthRequest` | `List<CorporateEventDto>` | Monatliche Termine/Earnings |
|
||||||
|
| `fundamentals_settings_GetAll`| FinlyticFundamentals | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `fundamentals_settings_Update`| FinlyticFundamentals | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `ta_GetAnalysis` | FinlyticTechnicals | `IsinRequest` | `TechnicalAnalysisDto?` | Komplette TA inkl. Indikatoren |
|
||||||
|
| `ta_GetSetupsForIsin` | FinlyticTechnicals | `IsinRequest` | `List<StrategyResultDto>` | Aktive Setups für eine ISIN |
|
||||||
|
| `ta_GetSetups` | FinlyticTechnicals | `GetSetupsRequest` | `List<StrategyResultDto>` | Universe-weite Setups/Top-Picks |
|
||||||
|
| `ta_GetCandles` | FinlyticTechnicals | `GetCandlesRequest` | `IReadOnlyList<CandleDto>` | Kerzen nach Timeframe |
|
||||||
|
| `ta_GetWatchlist` | FinlyticTechnicals | `object` | `List<WatchlistEntryDto>` | Monitorte Universe-Assets |
|
||||||
|
| `ta_GetRecentSetupHistory` | FinlyticTechnicals | `GetRecentSetupHistoryRequest` | `List<StrategyResultDto>` | Historische Setup-Scores |
|
||||||
|
| `ta_settings_GetAll` | FinlyticTechnicals | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `ta_settings_Update` | FinlyticTechnicals | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `engine_GetProposals` | FinlyticEngine | `GetProposalsRequest` | `List<TradeProposalDto>` | Aktive Trade-Vorschläge |
|
||||||
|
| `engine_GetTrades` | FinlyticEngine | `GetTradesRequest` | `List<ActiveTradeDto>` | Aktive Benutzertrades |
|
||||||
|
| `engine_EvaluateIsin` | FinlyticEngine | `EvaluateIsinRequest` | `AssetEvaluationResultDto?`| Manuelle ISIN-Evaluierung |
|
||||||
|
| `engine_AddFill` | FinlyticEngine | `AddFillRequest` | `ActiveTradeDto?` | Teil-/Vollausführung buchen |
|
||||||
|
| `engine_UpdateStopLoss` | FinlyticEngine | `UpdateStopLossRequest` | `ActiveTradeDto?` | Stop-Loss anpassen |
|
||||||
|
| `engine_CloseTrade` | FinlyticEngine | `CloseTradeRequest` | `ActiveTradeDto?` | Trade schließen |
|
||||||
|
| `engine_AcceptProposal` | FinlyticEngine | `AcceptTradeProposalRequest` | `ActiveTradeDto?` | Vorschlag als Trade annehmen |
|
||||||
|
| `engine_CreateManualTrade` | FinlyticEngine | `CreateManualTradeRequest` | `ActiveTradeDto?` | Manuellen Trade eröffnen |
|
||||||
|
| `engine_GetEvaluationHistory` | FinlyticEngine | `GetEvaluationHistoryRequest` | `GetEvaluationHistoryResponse` | Admin-Evaluierungs-Historie |
|
||||||
|
| `engine_settings_GetAll` | FinlyticEngine | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `engine_settings_Update` | FinlyticEngine | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `sim_RunBacktest` | FinlyticSimulation | `BacktestRequestDto` | `BacktestReportDto` | Quantitativen Backtest starten |
|
||||||
|
| `sim_GetReliability` | FinlyticSimulation | `GetReliabilityRequest` | `StrategyAssetReliabilityDto?`| Zuverlässigkeit für Setup |
|
||||||
|
| `sim_GetMatrixForAsset` | FinlyticSimulation | `IsinRequest` | `List<StrategyAssetReliabilityDto>`| Komplette Asset-Matrix |
|
||||||
|
| `sim_GetBacktestHistory` | FinlyticSimulation | `GetBacktestHistoryRequest` | `GetBacktestHistoryResponse` | Historische Backtest-Läufe |
|
||||||
|
| `sim_GetBacktestRunDetail` | FinlyticSimulation | `RunIdRequest` | `BacktestReportDto?` | Detailbericht eines Backtests |
|
||||||
|
| `sim_GetStrategyParameters` | FinlyticSimulation | `GetStrategyParametersRequest` | `StrategyParameterProfileDto?`| Gespeicherte TA-Parameter |
|
||||||
|
| `sim_SaveStrategyParameters` | FinlyticSimulation | `SaveStrategyParametersRequest`| `StrategyParameterProfileDto` | TA-Parameter speichern |
|
||||||
|
| `sim_settings_GetAll` | FinlyticSimulation | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `sim_settings_Update` | FinlyticSimulation | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `bot_GetStatus` | FinlyticBot | `object` | `BotStatusDto` | Bot-Status & Venue |
|
||||||
|
| `bot_GetPositions` | FinlyticBot | `object` | `List<BotTradeOrderDto>` | Offene Bot-Positionen |
|
||||||
|
| `bot_GetSummary` | FinlyticBot | `object` | `AccountSummaryDto` | Kontostand & PnL |
|
||||||
|
| `bot_ExecuteProposal` | FinlyticBot | `ExecuteProposalRequest` | `BotTradeOrderDto?` | Order für Proposal aufgeben |
|
||||||
|
| `bot_PanicClose` | FinlyticBot | `object` | `PanicCloseResultDto` | Notfall-Schließung aller Positionen |
|
||||||
|
| `bot_settings_GetAll` | FinlyticBot | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `bot_settings_Update` | FinlyticBot | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `notify_settings_GetAll` | FinlyticNotify | `object` | `List<DynamicSettingDto>` | Einstellungen abfragen |
|
||||||
|
| `notify_settings_Update` | FinlyticNotify | `Dictionary<string, object?>` | `List<DynamicSettingDto>` | Einstellungen aktualisieren |
|
||||||
|
| `backend_GetAggregatedFavorites`| FinlyticBackend | `object` | `List<string>` | Alle Benutzer-Favoriten-ISINs |
|
||||||
|
| `backend_GetUsername` | FinlyticBackend | `UserIdRequest` | `string?` | Benutzernamen nach GUID |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5.2 MQTT Pub/Sub Event-Topics
|
||||||
|
|
||||||
|
| Topic | Publisher | Konsumenten | Payload-Typ | Beschreibung |
|
||||||
|
| :--- | :--- | :--- | :--- | :--- |
|
||||||
|
| `services/news/completed` | FinlyticNews | FinlyticSentiment, Backend | `NewsArticleDto` | Neuer fertig verarbeiteter Artikel |
|
||||||
|
| `finlytic/news/stream/{isin}` | FinlyticNews | BackendMqttBridge | `NewsArticleDto` | ISIN-spezifischer News-Stream |
|
||||||
|
| `finlytic/sentiment/stream/{isin}`| FinlyticSentiment | FinlyticTechnicals, Backend | `IsinSentimentSummaryDto` | Aktualisiertes Sentiment |
|
||||||
|
| `finlytic/engine/proposals/created`| FinlyticEngine | FinlyticBot, FinlyticNotify, Backend | `TradeProposalDto` | Neuer Trade-Vorschlag erstellt |
|
||||||
|
| `finlytic/engine/trades/status_changed`| FinlyticEngine| FinlyticNotify, Backend | `ActiveTradeDto` | Trade-Statusänderung (TP/SL/Close) |
|
||||||
|
| `finlytic/bot/trades/stream` | FinlyticBot | FinlyticNotify, Backend | `BotTradeOrderDto` | Bot-Order-Lifecycle-Event |
|
||||||
|
| `finlytic/logs/{service}` | *(Alle Services)* | BackendMqttBridge | `LogMessageDto` | Strukturierter Service-Logstream |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5.3 REST API Endpunkte (`FinlyticBackend`)
|
||||||
|
|
||||||
|
Alle Endpunkte erfordern `Authorization: Bearer <JWT>` (außer Login und Health).
|
||||||
|
|
||||||
|
#### 1. Authentifizierung & Benutzer (`/api/v1/auth`, `/api/v1/user`, `/api/v1/admin`)
|
||||||
|
- `POST /api/v1/auth/login` `[AllowAnonymous]`: Login mit Username/Passwort $\to$ JWT Token & User-Objekt.
|
||||||
|
- `POST /api/v1/auth/change-initial-password`: Ändern des Initialpassworts bei `RequiresPasswordChange`.
|
||||||
|
- `POST /api/v1/user/fcm-token`: Hinterlegen des Firebase Cloud Messaging Push-Tokens.
|
||||||
|
- `GET /api/v1/user/me`: Profil des aktuell angemeldeten Benutzers abrufen.
|
||||||
|
- `GET /api/v1/admin/users` `[Roles: Admin]`: Benutzerliste.
|
||||||
|
- `POST /api/v1/admin/users` `[Roles: Admin]`: Neuen Benutzer anlegen.
|
||||||
|
- `PUT /api/v1/admin/users/{id}` `[Roles: Admin]`: Benutzer bearbeiten (Rolle, Status).
|
||||||
|
- `DELETE /api/v1/admin/users/{id}` `[Roles: Admin]`: Benutzer deaktivieren/löschen.
|
||||||
|
- `POST /api/v1/admin/users/{id}/reset-password` `[Roles: Admin]`: Passwort zurücksetzen.
|
||||||
|
|
||||||
|
#### 2. Assets & Discovery (`/api/v1/assets`)
|
||||||
|
- `GET /api/v1/assets/search?q={query}`: Volltextsuche nach Name/ISIN im lokalen Index.
|
||||||
|
- `GET /api/v1/assets/discovery?limit={limit}`: Kuratierte Trend-/Discovery-Assets.
|
||||||
|
- `GET /api/v1/assets/{isin}/fundamentals`: Fundamentaldaten, KGV, Events.
|
||||||
|
- `GET /api/v1/assets/{isin}/technicals`: TA-Indikatoren, Kerzen, Setups.
|
||||||
|
- `GET /api/v1/assets/{isin}/live`: Trade Republic Realtime-Tick (Bid/Ask/Last).
|
||||||
|
- `GET /api/v1/assets/{isin}/derivatives?optionType={long|short}&targetLeverage={x}`: Passende KO-Zertifikate.
|
||||||
|
- `GET /api/v1/logo/{isin}` `[AllowAnonymous]`: Lokales SVG-Logo ausliefern.
|
||||||
|
|
||||||
|
#### 3. Analyse & Engine (`/api/v1/analyze`, `/api/v1/engine`)
|
||||||
|
- `POST /api/v1/analyze/manual`: Ad-hoc Auswertung einer ISIN (TA, Sentiment, KI-Gate).
|
||||||
|
- `GET /api/v1/analyze/proposals`: Vorschläge abrufen.
|
||||||
|
- `GET /api/v1/engine/proposals?onlyActive={bool}&limit={limit}`: Aktive Vorschläge.
|
||||||
|
- `GET /api/v1/engine/trades?mode={Manual|Bot}`: Trades des eingeloggten Users.
|
||||||
|
- `POST /api/v1/engine/evaluate`: Evaluierungs-Trigger für ISIN.
|
||||||
|
- `POST /api/v1/engine/trades/{id}/fills`: Fill buchen.
|
||||||
|
- `PUT /api/v1/engine/trades/{id}/stoploss`: SL-Anpassung.
|
||||||
|
- `POST /api/v1/engine/trades/{id}/close`: Trade schließen.
|
||||||
|
|
||||||
|
#### 4. Benutzer-Trades (`/api/v1/user/trades`)
|
||||||
|
- `GET /api/v1/user/trades`: Eigene aktive & historische Trades.
|
||||||
|
- `POST /api/v1/user/trades/accept`: Vorschlag verbindlich annehmen.
|
||||||
|
- `POST /api/v1/user/trades/manual`: Eigenen Trade ohne Vorschlag eröffnen.
|
||||||
|
- `POST /api/v1/user/trades/{id}/close`: Eigenen Trade manuell schließen.
|
||||||
|
|
||||||
|
#### 5. Favoriten & Präferenzen (`/api/v1/user/favorites`, `/api/v1/user/preferences`)
|
||||||
|
- `GET /api/v1/user/favorites`: Favoritenliste mit Live-Preisen & Tagesänderung.
|
||||||
|
- `POST /api/v1/user/favorites/{symbol}`: Asset zu Favoriten hinzufügen.
|
||||||
|
- `POST /api/v1/user/favorites/{symbol}/ticker`: Ticker-Symbol zuweisen.
|
||||||
|
- `DELETE /api/v1/user/favorites/{symbol}`: Asset aus Favoriten entfernen.
|
||||||
|
- `GET /api/v1/user/preferences`: UI-Präferenzen (Theme, Layout).
|
||||||
|
- `PUT /api/v1/user/preferences/theme`: Theme anpassen.
|
||||||
|
|
||||||
|
#### 6. Backtesting & Simulation (`/api/v1/simulation`)
|
||||||
|
- `POST /api/v1/simulation/run`: Quantitativen Backtest starten.
|
||||||
|
- `GET /api/v1/simulation/matrix/{isin}`: Zuverlässigkeitsmatrix für ISIN.
|
||||||
|
- `GET /api/v1/simulation/history/{isin}`: Historische Backtests für ISIN.
|
||||||
|
- `GET /api/v1/simulation/history/run/{runId}`: Vollständiger Backtest-Report.
|
||||||
|
- `GET /api/v1/simulation/parameters/{isin}/{strategyKey}`: Gespeicherte Strategie-Parameter.
|
||||||
|
- `POST /api/v1/simulation/parameters`: Parameterprofil speichern.
|
||||||
|
|
||||||
|
#### 7. Bot & Paper-Trading (`/api/v1/bot`)
|
||||||
|
- `GET /api/v1/bot/status`: Bot-Status & Venue.
|
||||||
|
- `GET /api/v1/bot/positions/active`: Offene Bot-Positionen.
|
||||||
|
- `GET /api/v1/bot/portfolio/summary`: Kontostand & PnL.
|
||||||
|
- `POST /api/v1/bot/orders/execute`: Manuelle Order über Bot abschicken.
|
||||||
|
- `POST /api/v1/bot/orders/panic-close`: Notfall-Schließung.
|
||||||
|
- `POST /api/v1/bot/settings/update`: Bot-Einstellungen aktualisieren.
|
||||||
|
|
||||||
|
#### 8. News & Kalender (`/api/v1/news`, `/api/v1/calendar`)
|
||||||
|
- `GET /api/v1/news?limit={limit}&offset={offset}&isin={isin}&status={status}`: Gefilterte News.
|
||||||
|
- `GET /api/v1/calendar/events/{year}/{month}`: Corporate Events & Earnings.
|
||||||
|
|
||||||
|
#### 9. Admin-System (`/api/v1/admin/settings`, `/api/v1/admin/evaluations`)
|
||||||
|
- `GET /api/v1/admin/settings`: Einstellungen aller Services.
|
||||||
|
- `GET /api/v1/admin/settings/{serviceName}`: Einstellungen eines Services.
|
||||||
|
- `PUT /api/v1/admin/settings/{serviceName}`: Einstellungen dynamisch ändern.
|
||||||
|
- `GET /api/v1/admin/settings/health`: Health-Status aller Services.
|
||||||
|
- `GET /api/v1/admin/settings/logs/{serviceName}`: Letzte 250 Ringpuffer-Logs.
|
||||||
|
- `GET /api/v1/admin/evaluations`: Evaluierungs-Historie ("Warum kein Proposal?").
|
||||||
|
- `GET /api/v1/admin/evaluations/watchlist`: Gescannte Watchlist-Assets.
|
||||||
|
- `GET /api/v1/admin/evaluations/watchlist/{isin}/history`: Setup-Verlauf eines Assets.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5.4 SignalR Hubs & Methoden
|
||||||
|
|
||||||
|
Verbindung über `/hubs/{hubname}?access_token=<JWT>`.
|
||||||
|
|
||||||
|
| Hub-Route | Server-Methoden | Client-Events (Callbacks) | Zweck |
|
||||||
|
| :--- | :--- | :--- | :--- |
|
||||||
|
| `/hubs/trade-stream` | `SubscribeToAsset(isin)`<br>`UnsubscribeFromAsset(isin)` | `ReceiveTradeProposal(proposal)`<br>`ReceiveTradeUpdate(trade)` | Realtime-Updates zu Proposals & Trades |
|
||||||
|
| `/hubs/news` | `SubscribeToIsin(isin)` | `ReceiveNewsArticle(article)` | Neue gescrapte/analysierte News |
|
||||||
|
| `/hubs/health` | *(Keine)* | `ReceiveServiceHealth(health)` | Live-Healthcheck der Services |
|
||||||
|
| `/hubs/favorites-prices`| *(Keine)* | `ReceivePriceUpdate(isin, price, change)`| Realtime-Kursupdates der Favoriten (15s Takt) |
|
||||||
|
| `/hubs/logs` | *(Keine)* | `ReceiveLogMessage(logDto)` | Admin Live-Logstream |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Detaillierte Funktionsweise & Datenfluss
|
||||||
|
|
||||||
|
### 6.1 End-to-End Opportunity- & Trade-Lifecycle
|
||||||
|
|
||||||
|
```
|
||||||
|
1. DATA INGESTION
|
||||||
|
├── FinlyticNews: RSS/Scraping -> SimHash Deduplication -> In-Memory Matcher -> MQTT "services/news/completed"
|
||||||
|
├── FinlyticSentiment: FinBERT Webhook -> Time-Decay DB Update -> MQTT "finlytic/sentiment/stream/{isin}"
|
||||||
|
└── FinlyticTechnicals: Trade Republic & Yahoo Ticks -> Resampler -> Indicator Math (RSI, EMA, Squeeze, etc.)
|
||||||
|
|
||||||
|
2. TECHNICAL SCANNING (FinlyticTechnicals)
|
||||||
|
├── MultiTimeframeCandleAggregator aktualisiert Ringpuffer (15m, 1h, 1d)
|
||||||
|
├── 15 Pattern-Detektoren identifizieren FVG, OrderBlocks, DoubleBottom, Liquidity Sweeps
|
||||||
|
├── 10 CoreStrategies evaluieren Signale & erzeugen Exit-Pläne (TP1, TP2, Trailing-Stop, Break-Even)
|
||||||
|
└── TechnicalScoringEngineV2 berechnet Confluence-Score (Indikatoren + Patterns + Strategie)
|
||||||
|
|
||||||
|
3. ENGINE EVALUATION (FinlyticEngine)
|
||||||
|
├── OpportunityPollerBackgroundService pollt Top-Picks (Score >= 70)
|
||||||
|
├── CompositeOpportunityScorerV2 berechnet COS (Tech 45%, Sent 35%, Fund 20%)
|
||||||
|
├── Filter-Gates: EarningsLockout (2 Tage), DividendGate (1 Tag), Simulation Matrix Veto
|
||||||
|
├── AiReasoningGateService sendet strukturierten Context an n8n AI-Webhook
|
||||||
|
└── KnockOutDerivativeResolver matcht Hebel & Safety-Buffer -> Proposal persistiert & publiziert
|
||||||
|
|
||||||
|
4. EXECUTION & BOT (FinlyticBot / FinlyticApp)
|
||||||
|
├── FinlyticApp: User sieht Proposal im UI, klickt "Accept" -> Trade eröffnet
|
||||||
|
├── FinlyticBot: Falls AutoExecution aktiv -> 1-2% Risikosizing -> Orderausführung (Alpaca/Ledger)
|
||||||
|
└── FinlyticNotify: ntfy Push-Notification an Smartphone/Desktop
|
||||||
|
|
||||||
|
5. ACTIVE MONITORING & EXITS
|
||||||
|
├── ActiveTradeMonitoringBackgroundService (Engine) & BotTradeLifecycleBackgroundService (Bot)
|
||||||
|
├── Regelmäßige Kursabfrage (15s - 60s)
|
||||||
|
├── Bei TP1: Teilverkauf (50%) & Verschieben des Stop-Loss auf Break-Even (gebührenbereinigt)
|
||||||
|
├── Bei TP2: Teilverkauf (30%) & Aktivierung des ATR-Trailing-Stops für verbleibende 20%
|
||||||
|
└── Bei Stop-Loss / Knock-Out / MaxBars: Positionsschließung & PnL-Verbuchung
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Frontend-Architektur (FinlyticApp)
|
||||||
|
|
||||||
|
- **Technologie**: Flutter (Dart) mit Web- und Mobile-Unterstützung.
|
||||||
|
- **State Management**: `flutter_bloc` (`BlocProvider`, `BlocBuilder`, `BlocConsumer`, `Cubit`).
|
||||||
|
- **Netzwerk & Security**:
|
||||||
|
- Zentraler `Dio`-Client mit `AuthInterceptor`.
|
||||||
|
- Injiziert automatisch `Authorization: Bearer <token>` in jeden Request.
|
||||||
|
- **Automatischer Logout**: Fängt `401 Unauthorized` und `403 Forbidden` zentral ab, löscht Secure Storage und leitet sofort auf den Login-Bildschirm um.
|
||||||
|
- **Realtime-Kommunikation**: `SignalRService` mit automatischem Reconnect und Event-Subskriptionen (`trade-stream`, `news`, `health`, `favorites-prices`, `logs`).
|
||||||
|
- **Feature-Struktur**:
|
||||||
|
- `features/auth`: Login, Passwortänderung.
|
||||||
|
- `features/dashboard`: Schnellübersicht, aktive Trades, Markttrends.
|
||||||
|
- `features/discovery`: Top-Assets, Scanner-Ergebnisse.
|
||||||
|
- `features/asset_detail`: Interaktiver Chart, Multi-Timeframe-Indikatoren, Fundamentaldaten, Sentiment-Historie, Derivate-Selektor.
|
||||||
|
- `features/proposals`: Trade-Vorschläge mit detaillierter KI-Begründung, Setup-Chart und Direkt-Annahme.
|
||||||
|
- `features/trades`: Eigene Positionen, TP/SL-Visualisierung, manuelles Schließen.
|
||||||
|
- `features/bot`: Bot-Positionen, Performance-Graphen, Kontostand, Panic-Close-Button.
|
||||||
|
- `features/simulation`: Backtest-Runner, Equity-Kurven, Strategie-Zuverlässigkeitsmatrix, Parameter-Tuning.
|
||||||
|
- `features/news`: Live-Newsfeed mit Sentiment-Badges und Filter nach Asset.
|
||||||
|
- `features/calendar`: Earnings- und Corporate-Events-Kalender.
|
||||||
|
- `features/favorites`: Realtime-Watchlist mit Kurs-Ticker.
|
||||||
|
- `features/admin`: Dynamische Service-Settings, Live-Log-Konsole, System-Health, Benutzerverwaltung, Evaluierungs-Historie ("Warum kein Proposal?").
|
||||||
Reference in New Issue
Block a user