feat(App): update Finlytic Flutter app UI and blocs
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../widgets/metric_explanation_modal.dart';
|
||||
|
||||
class MetricExplanations {
|
||||
static const Map<String, Map<String, String>> data = {
|
||||
'EMA (20)': {
|
||||
'title': 'Exponential Moving Average (20 Perioden)',
|
||||
'formula': 'EMA_t = (Preis_t * (2 / (20 + 1))) + EMA_{t-1} * (1 - (2 / (20 + 1)))',
|
||||
'description': 'Exponentiell gewichteter gleitender Durchschnitt der letzten 20 Kerzen. Gewichtete aktuelle Kurse stärker als ältere.',
|
||||
'tradingSignificance': 'Dient als dynamische Unterstützung/Widerstand für kurzfristige Trends. Ein Schnittpunkt über die Kerzen zeigt Kaufsignale.',
|
||||
},
|
||||
'SMA (50)': {
|
||||
'title': 'Simple Moving Average (50 Perioden)',
|
||||
'formula': 'SMA = (Summe der Schlusskurse der letzten 50 Kerzen) / 50',
|
||||
'description': 'Einfacher gleitender Durchschnitt der letzten 50 Perioden.',
|
||||
'tradingSignificance': 'Standard-Indikator für mittelfristige Trends. Preis über SMA50 deutet auf einen intakten Aufwärtstrend hin.',
|
||||
},
|
||||
'SMA (200)': {
|
||||
'title': 'Simple Moving Average (200 Perioden)',
|
||||
'formula': 'SMA = (Summe der Schlusskurse der letzten 200 Kerzen) / 200',
|
||||
'description': 'Einfacher gleitender Durchschnitt der letzten 200 Perioden.',
|
||||
'tradingSignificance': 'Wichtigster Indikator für den langfristigen Trend. "Golden Cross" (SMA50 schneidet SMA200 nach oben) ist ein starkes Bullen-Signal.',
|
||||
},
|
||||
'Supertrend': {
|
||||
'title': 'Supertrend Indikator',
|
||||
'formula': 'Upper/Lower Band = (High + Low)/2 ± (Multiplier * ATR(10))',
|
||||
'description': 'Kombiniert ATR (Average True Range) und Durchschnittskurs zur Trendfolge.',
|
||||
'tradingSignificance': 'Grün zeigt einen etablierten Aufwärtstrend mit dynamischem Stop-Loss Level; Rot signalisiert Abwärtstrend.',
|
||||
},
|
||||
'RSI (14)': {
|
||||
'title': 'Relative Strength Index (14 Perioden)',
|
||||
'formula': 'RSI = 100 - (100 / (1 + (Durchschnittl. Gewinn / Durchschnittl. Verlust)))',
|
||||
'description': 'Oszillator zur Messung der Geschwindigkeit und Veränderung von Kursbewegungen.',
|
||||
'tradingSignificance': 'Werte > 70 gelten als überkauft (Verkaufsrisiko), Werte < 30 gelten als überverkauft (Kaufchance).',
|
||||
},
|
||||
'KGV (Trailing P/E)': {
|
||||
'title': 'Kurs-Gewinn-Verhältnis (Trailing P/E)',
|
||||
'formula': 'KGV = Aktienkurs / Gewinn pro Aktie (EPS der letzten 12 Monate)',
|
||||
'description': 'Gibt an, das Wievielfache des Jahresgewinns für eine Aktie gezahlt wird.',
|
||||
'tradingSignificance': 'Ein niedriges KGV kann auf eine Unterbewertung hindeuten; ein hohes KGV verlangt hohes zukünftiges Gewinnwachstum.',
|
||||
},
|
||||
'KGV (Forward P/E)': {
|
||||
'title': 'Zukünftiges KGV (Forward P/E)',
|
||||
'formula': 'Forward KGV = Aktueller Kurs / Erwarteter Gewinn pro Aktie (nächste 12 Monate)',
|
||||
'description': 'Basiert auf den Konsens-Gewinnerwartungen von Analysten für das kommende Jahr.',
|
||||
'tradingSignificance': 'Ermöglicht den Vergleich mit dem historischen KGV, um festzustellen, ob das Gewinnwachstum die Bewertung verbilligt.',
|
||||
},
|
||||
'PEG Ratio': {
|
||||
'title': 'Price/Earnings-to-Growth Ratio',
|
||||
'formula': 'PEG = KGV / Zukünftiges Gewinnwachstum in %',
|
||||
'description': 'Setzt das KGV ins Verhältnis zum erwarteten Gewinnwachstum des Unternehmens.',
|
||||
'tradingSignificance': 'PEG < 1.0 gilt als fair oder unterbewertet im Verhältnis zum Wachstum. PEG > 2.0 gilt als teuer.',
|
||||
},
|
||||
'KBV (P/B Ratio)': {
|
||||
'title': 'Kurs-Buchwert-Verhältnis (P/B Ratio)',
|
||||
'formula': 'KBV = Aktienkurs / Buchwert pro Aktie',
|
||||
'description': 'Vergleicht den Börsenwert des Unternehmens mit seinem bilanziellen Eigenkapital.',
|
||||
'tradingSignificance': 'Besonders wichtig für Finanzwerte und Substanzwerte. KBV < 1 bedeutet, dass die Aktie unter ihrem Buchwert handelt.',
|
||||
},
|
||||
'KUV (P/S Ratio)': {
|
||||
'title': 'Kurs-Umsatz-Verhältnis (P/S Ratio)',
|
||||
'formula': 'KUV = Marktkapitalisierung / Gesamter Jahresumsatz',
|
||||
'description': 'Vergleicht den Marktwert des Unternehmens mit seinem Jahresumsatz.',
|
||||
'tradingSignificance': 'Nützlich bei noch unprofitablen Wachstumsunternehmen, bei denen noch kein positives KGV berechnet werden kann.',
|
||||
},
|
||||
'EV / EBITDA': {
|
||||
'title': 'Enterprise Value zu EBITDA',
|
||||
'formula': 'EV/EBITDA = Enterprise Value / (Gewinn vor Zinsen, Steuern & Abschreibungen)',
|
||||
'description': 'Misst den Unternehmenswert inklusive Schulden im Verhältnis zur operativen Cash-Generierung.',
|
||||
'tradingSignificance': 'Kapitalstruktur-neutraler Bewertungs-Multiple. Erlaubt fairen Vergleich zwischen Unternehmen mit unterschiedlicher Verschuldung.',
|
||||
},
|
||||
'EV / Sales': {
|
||||
'title': 'Enterprise Value zu Umsatz',
|
||||
'formula': 'EV/Sales = Enterprise Value / Jahresumsatz',
|
||||
'description': 'Vergleicht den gesamten Unternehmenswert (Eigen- + Fremdkapital) mit den Erlösen.',
|
||||
'tradingSignificance': 'Robustere Kennzahl als KUV, da sie auch die Schuldenlast des Unternehmens berücksichtigt.',
|
||||
},
|
||||
'Enterprise Value': {
|
||||
'title': 'Enterprise Value (Unternehmenswert)',
|
||||
'formula': 'EV = Marktkapitalisierung + Gesamtschulden - Liquide Mittel (Cash)',
|
||||
'description': 'Der theoretische Übernahmepreis für das gesamte Unternehmen inklusive Tilgung aller Verbindlichkeiten.',
|
||||
'tradingSignificance': 'Der tatsächliche wirtschaftliche Wert des Geschäftsbetriebs.',
|
||||
},
|
||||
'Marktkapitalisierung': {
|
||||
'title': 'Marktkapitalisierung (Market Cap)',
|
||||
'formula': 'Market Cap = Gesamtzahl ausstehender Aktien * Aktueller Aktienkurs',
|
||||
'description': 'Der Gesamtwert aller frei gehandelten Aktien des Unternehmens an der Börse.',
|
||||
'tradingSignificance': 'Teilt Unternehmen in Large Cap (>10 Mrd. €), Mid Cap (2-10 Mrd. €) und Small Cap (<2 Mrd. €) ein.',
|
||||
},
|
||||
'Short Ratio': {
|
||||
'title': 'Days to Cover (Short Ratio)',
|
||||
'formula': 'Short Ratio = Anzahl leerverkaufter Aktien / Durchschnittliches Tagesvolumen',
|
||||
'description': 'Gibt an, wie viele Handelstage Leerverkäufer bräuchten, um alle Positionen einzudecken.',
|
||||
'tradingSignificance': 'Hohe Werte (> 5-7 Tage) erhöhen die Wahrscheinlichkeit eines heftigen "Short Squeezes" bei positiven News.',
|
||||
},
|
||||
'Bruttomarge (Gross)': {
|
||||
'title': 'Bruttogewinnmarge (Gross Margin)',
|
||||
'formula': 'Gross Margin = ((Umsatz - Herstellkosten) / Umsatz) * 100',
|
||||
'description': 'Prozentualer Anteil des Umsatzes, der nach Abzug der direkten Produktionskosten verbleibt.',
|
||||
'tradingSignificance': 'Hohe Bruttomargen (> 50-70%) zeigen eine starke Preissetzungsmacht und Wettbewerbsvorteile (Moat).',
|
||||
},
|
||||
'Operative Marge': {
|
||||
'title': 'Operative Gewinnmarge (EBIT Margin)',
|
||||
'formula': 'Operating Margin = (Operatives Ergebnis (EBIT) / Umsatz) * 100',
|
||||
'description': 'Prozentualer Anteil des Umsatzes, der nach allen operativen Kosten (F&E, Vertrieb, Admin) übrig bleibt.',
|
||||
'tradingSignificance': 'Kerngröße für die operative Effizienz des Managements.',
|
||||
},
|
||||
'Nettogewinnmarge': {
|
||||
'title': 'Nettogewinnmarge (Net Profit Margin)',
|
||||
'formula': 'Net Profit Margin = (Nettogewinn nach Steuern / Umsatz) * 100',
|
||||
'description': 'Prozentualer Reingewinn, der von jedem Euro Umsatz im Unternehmen verbleibt.',
|
||||
'tradingSignificance': 'Zeigt die finale Rentabilität nach allen Zinsen und Steuern.',
|
||||
},
|
||||
'Eigenkapitalrendite (ROE)': {
|
||||
'title': 'Eigenkapitalrendite (Return on Equity)',
|
||||
'formula': 'ROE = (Nettogewinn / Eigenkapital) * 100',
|
||||
'description': 'Misst, wie effizient das Management das eingesetzte Eigenkapital verzinst.',
|
||||
'tradingSignificance': 'Werte > 15-20% stehen für hochprofitable Qualitätsunternehmen.',
|
||||
},
|
||||
'Verschuldungsgrad (D/E)': {
|
||||
'title': 'Debt-to-Equity Ratio (D/E)',
|
||||
'formula': 'D/E = Gesamtschulden / Eigenkapital',
|
||||
'description': 'Setzt das Fremdkapital ins Verhältnis zum Eigenkapital.',
|
||||
'tradingSignificance': 'Werte > 1.5 - 2.0 deuten auf ein erhöhtes mehraufwand- und Insolvenzrisiko bei steigenden Zinsen hin.',
|
||||
},
|
||||
};
|
||||
|
||||
static void show(BuildContext context, String key) {
|
||||
final info = data[key];
|
||||
if (info == null) return;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => MetricExplanationModal(
|
||||
title: info['title']!,
|
||||
formula: info['formula']!,
|
||||
description: info['description']!,
|
||||
tradingSignificance: info['tradingSignificance']!,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../../core/theme/app_theme.dart';
|
||||
|
||||
class PatternExplanations {
|
||||
static const Map<String, Map<String, String>> dictionary = {
|
||||
'ASCENDING_TRIANGLE': {
|
||||
'title': 'Steigendes Dreieck (Ascending Triangle)',
|
||||
'bias': 'BULLISH',
|
||||
'description': 'Ein bullisches Fortsetzungsmuster, das durch eine horizontale Widerstandslinie oben und eine steigende Unterstützungslinie unten gekennzeichnet ist.',
|
||||
'significance': 'Käufer werden bei jedem Rücksetzer aggressiver (höhere Tiefs). Ein Ausbruch über die obere Widerstandslinie signalisiert eine starke Fortsetzung des Aufwärtstrends.',
|
||||
'action': 'Kauf-Order / Breakout-Trade beim Ausbruch über den horizontalen Widerstand mit Stop-Loss knapp unter der steigenden Trendlinie.',
|
||||
},
|
||||
'DESCENDING_TRIANGLE': {
|
||||
'title': 'Fallendes Dreieck (Descending Triangle)',
|
||||
'bias': 'BEARISH',
|
||||
'description': 'Ein bärisches Fortsetzungsmuster mit einer horizontalen Unterstützungslinie unten und fallenden Hochs oben.',
|
||||
'significance': 'Verkäufer drücken den Kurs bei jeder Erholung schneller nach unten. Ein Bruch der unteren Unterstützung führt meist zu dynamischen Abverkäufen.',
|
||||
'action': 'Short-Trade oder Verkauf bei Durchbruch der unteren Unterstützungslinie.',
|
||||
},
|
||||
'HEAD_AND_SHOULDERS': {
|
||||
'title': 'Kopf-Schulter-Formation (Head & Shoulders)',
|
||||
'bias': 'BEARISH',
|
||||
'description': 'Klassisches Umkehrmuster bestehend aus drei Höchstständen: der mittleren höchsten Spitze (Kopf) und zwei kleineren Höchstständen links und rechts (Schultern).',
|
||||
'significance': 'Ein nachhaltiger Bruch der Nackenlinie (Neckline) markiert das Ende eines Aufwärtstrends und den Beginn einer Bärenphase.',
|
||||
'action': 'Verkauf/Short-Position beim Bruch der Nackenlinie mit Kursziel entsprechend der Distanz zwischen Kopf und Nackenlinie.',
|
||||
},
|
||||
'INVERSE_HEAD_AND_SHOULDERS': {
|
||||
'title': 'Umgekehrte Kopf-Schulter-Formation',
|
||||
'bias': 'BULLISH',
|
||||
'description': 'Bullisches Bodenbildungsmuster nach einem Abwärtstrend mit drei Tiefspunkten.',
|
||||
'significance': 'Signalisiert das Ende des Abwärtstrends und den Beginn eines neuen Bullenmarktes.',
|
||||
'action': 'Kauf bei Ausbruch über die obere Nackenlinie.',
|
||||
},
|
||||
'BULL_FLAG': {
|
||||
'title': 'Bullische Flagge (Bull Flag)',
|
||||
'bias': 'BULLISH',
|
||||
'description': 'Kurze Konsolidierung gegen den übergeordneten starken Aufwärtstrend (Fahnenstange).',
|
||||
'significance': 'Zeigt eine temporäre Gewinnmitnahme vor der nächsten Welle nach oben.',
|
||||
'action': 'Kauf beim Ausbruch aus der oberen Begrenzung des Flaggenkanals.',
|
||||
},
|
||||
'BEAR_FLAG': {
|
||||
'title': 'Bärische Flagge (Bear Flag)',
|
||||
'bias': 'BEARISH',
|
||||
'description': 'Kurze Aufwärtskonsolidierung in einem steilen Abwärtstrend.',
|
||||
'significance': 'Signalisiert eine Fortsetzung des steilen Abverkaufs.',
|
||||
'action': 'Short-Position bei Durchbrechen der unteren Flaggenkante.',
|
||||
},
|
||||
'DOUBLE_BOTTOM': {
|
||||
'title': 'Doppelboden (W-Formation)',
|
||||
'bias': 'BULLISH',
|
||||
'description': 'Zwei aufeinanderfolgende Tiefpunkte auf etwa gleichem Kursniveau.',
|
||||
'significance': 'Starke Unterstützung auf dem Tiefststand wurde zweimal erfolgreich verteidigt. Ausbruch über das Zwischenhoch bestätigt W-Boden.',
|
||||
'action': 'Kauf bei Überschreiten des W-Zwischenhochs.',
|
||||
},
|
||||
'DOUBLE_TOP': {
|
||||
'title': 'Doppeltopp (M-Formation)',
|
||||
'bias': 'BEARISH',
|
||||
'description': 'Zwei markante Höchststände auf ähnlicher Höhe, die nicht durchbrochen werden konnten.',
|
||||
'significance': 'Widerstandszone ist zu stark für die Bullen. Bruch des Zwischen-Tiefs leitet Trendwende ein.',
|
||||
'action': 'Verkauf/Short bei Bruch des Zwischentiefs.',
|
||||
},
|
||||
'CHANNEL': {
|
||||
'title': 'Trendkanal (Trading Channel)',
|
||||
'bias': 'NEUTRAL',
|
||||
'description': 'Parallele obere und untere Trendlinien, zwischen denen der Kurs Oszilliert.',
|
||||
'significance': 'Erlaubt Swing-Trading zwischen den Kanallinien oder Breakout-Trading beim Ausbruch.',
|
||||
'action': 'Kauf an der Unterkante, Verkauf an der Oberkante oder Breakout-Trading.',
|
||||
},
|
||||
'SUPPORT_RESISTANCE': {
|
||||
'title': 'Unterstützungs- & Widerstandslinien',
|
||||
'bias': 'NEUTRAL',
|
||||
'description': 'Preisniveaus, an denen historisch gehäuft Kauf- oder Verkaufsinteresse auftrat.',
|
||||
'significance': 'Wichtige Marken für Stop-Loss Platzierungen und Kursziele.',
|
||||
'action': 'Trading an Key-Levels mit engem Risikomanagement.',
|
||||
},
|
||||
};
|
||||
|
||||
static void showPatternDetails(BuildContext context, String rawPatternType) {
|
||||
final key = dictionary.keys.firstWhere(
|
||||
(k) => rawPatternType.toUpperCase().contains(k) || k.contains(rawPatternType.toUpperCase()),
|
||||
orElse: () => '',
|
||||
);
|
||||
|
||||
final info = key.isNotEmpty ? dictionary[key]! : {
|
||||
'title': rawPatternType,
|
||||
'bias': 'NEUTRAL',
|
||||
'description': 'Ein vom FinlyticAnalyzer erkanntes technisches Chart-Muster ($rawPatternType).',
|
||||
'significance': 'Trendlinien und Schlüssel-Zonen zur Bestimmung von Ein- und Ausstiegssignalen.',
|
||||
'action': 'Nutzen Sie Stopp-Orders und beachten Sie den übergeordneten Markt-Trend.',
|
||||
};
|
||||
|
||||
final isBullish = info['bias'] == 'BULLISH';
|
||||
final isBearish = info['bias'] == 'BEARISH';
|
||||
final biasColor = isBullish ? AppTheme.primaryEmerald : (isBearish ? AppTheme.accentRed : AppTheme.accentCyan);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (modalContext) => AlertDialog(
|
||||
backgroundColor: AppTheme.cardSurface,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
side: BorderSide(color: AppTheme.glassBorder),
|
||||
),
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
info['title']!,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
|
||||
decoration: BoxDecoration(
|
||||
color: biasColor.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(color: biasColor),
|
||||
),
|
||||
child: Text(
|
||||
info['bias']!,
|
||||
style: TextStyle(color: biasColor, fontWeight: FontWeight.bold, fontSize: 11),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text('Formationsbeschreibung:', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 13)),
|
||||
const SizedBox(height: 4),
|
||||
Text(info['description']!, style: TextStyle(color: AppTheme.textSecondary, fontSize: 13, height: 1.4)),
|
||||
const SizedBox(height: 14),
|
||||
|
||||
const Text('Markt-Bedeutung & Psychologie:', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 13)),
|
||||
const SizedBox(height: 4),
|
||||
Text(info['significance']!, style: const TextStyle(color: Colors.white70, fontSize: 13, height: 1.4)),
|
||||
const SizedBox(height: 14),
|
||||
|
||||
const Text('Empfohlene Trading-Handlung:', style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white, fontSize: 13)),
|
||||
const SizedBox(height: 4),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: AppTheme.glassSurface,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppTheme.glassBorder),
|
||||
),
|
||||
child: Text(info['action']!, style: TextStyle(color: AppTheme.accentCyan, fontSize: 12, fontWeight: FontWeight.w600, height: 1.4)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(modalContext),
|
||||
child: const Text('Schließen', style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user