feat(app): add evaluation history, bot control panel, simulation visualizer, and vendored signalr_core

This commit is contained in:
2026-08-24 21:37:43 +02:00
parent 676496b77d
commit 0894c40f07
113 changed files with 12413 additions and 3613 deletions
@@ -0,0 +1,237 @@
/// Describes one tunable indicator parameter for a strategy - mirrors the `context.GetParameter(StrategyKey, "...", default)`
/// calls in `FinlyticTechnicals/Strategies/CoreStrategies.cs`. Keys sent to the backend are always
/// `"{strategyKey}.{name}"`, matching `TechnicalContext.ParameterOverrides` exactly.
class StrategyParameterDef {
final String name;
final String label;
final double defaultValue;
/// Short plain-language explanation of what changing this value actually does, shown via an info tooltip
/// next to the field (Rules.md-style transparency: a bare abbreviation like "EMA schnell" means nothing to
/// someone who didn't just read the strategy's source code).
final String hint;
/// Whether the field should be entered/rounded as a whole number (indicator periods) vs. a decimal
/// (multipliers, thresholds).
final bool isInteger;
const StrategyParameterDef({
required this.name,
required this.label,
required this.defaultValue,
required this.hint,
this.isInteger = false,
});
}
/// Per-strategy list of tunable parameters, for the "Erweiterte Parameter" section of the backtest screen.
/// Every default value here must match the corresponding hardcoded default in `CoreStrategies.cs` exactly -
/// these are the same values the strategy already uses when nothing is overridden (Rules.md §4: never imply a
/// different default than what the backend actually falls back to).
class StrategyParameterDefinitions {
static const Map<String, List<StrategyParameterDef>> byStrategy = {
'TrendPullbackFvg': [
StrategyParameterDef(
name: 'EmaFast',
label: 'EMA schnell',
defaultValue: 20,
isInteger: true,
hint: 'Perioden der kurzen EMA. Kleiner = reagiert schneller auf Kursänderungen, aber mehr Fehlsignale.',
),
StrategyParameterDef(
name: 'EmaMid',
label: 'EMA mittel',
defaultValue: 50,
isInteger: true,
hint: 'Perioden der mittleren EMA, bestätigt zusammen mit der langsamen EMA den übergeordneten Trend.',
),
StrategyParameterDef(
name: 'EmaSlow',
label: 'EMA langsam',
defaultValue: 200,
isInteger: true,
hint: 'Perioden der langsamen EMA. Größer = stabilerer, aber träger erkannter Trend.',
),
StrategyParameterDef(
name: 'StopAtrMultiplier',
label: 'Stop-Loss (× ATR)',
defaultValue: 1.2,
hint: 'Abstand des Stop-Loss vom Einstieg, als Vielfaches der aktuellen Volatilität (ATR). Größer = weiterer Stop, weniger vorzeitige Ausstiege.',
),
],
'VolatilitySqueeze': [
StrategyParameterDef(
name: 'StopAtrMultiplier',
label: 'Stop-Loss (× ATR)',
defaultValue: 1.0,
hint: 'Abstand des Stop-Loss vom Einstieg, als Vielfaches der aktuellen Volatilität (ATR).',
),
StrategyParameterDef(
name: 'TargetAtrMultiplier',
label: 'Kursziel (× ATR)',
defaultValue: 2.0,
hint: 'Abstand des Kursziels vom Einstieg, als Vielfaches der aktuellen Volatilität (ATR).',
),
],
'SmcLiquiditySweep': [
StrategyParameterDef(
name: 'StopBufferPercent',
label: 'Stop-Puffer (%)',
defaultValue: 0.2,
hint: 'Zusätzlicher Sicherheitsabstand des Stop-Loss hinter dem Sweep-Extrempunkt, in Prozent.',
),
],
'MeanReversion': [
StrategyParameterDef(
name: 'BollingerMultiplier',
label: 'Bollinger-Multiplikator (σ)',
defaultValue: 2.5,
hint: 'Breite der Bollinger-Bänder in Standardabweichungen. Größer = seltenere, aber extremere Signale.',
),
StrategyParameterDef(
name: 'AdxThreshold',
label: 'ADX-Schwelle (max.)',
defaultValue: 22,
hint: 'Nur unterhalb dieser ADX-Trendstärke gilt der Markt als "seitwärts" - Voraussetzung für ein Signal.',
),
StrategyParameterDef(
name: 'RsiOversold',
label: 'RSI überverkauft (≤)',
defaultValue: 32,
hint: 'RSI-Wert, ab dem der Kurs als überverkauft gilt (Long-Signal-Voraussetzung).',
),
StrategyParameterDef(
name: 'RsiOverbought',
label: 'RSI überkauft (≥)',
defaultValue: 68,
hint: 'RSI-Wert, ab dem der Kurs als überkauft gilt (Short-Signal-Voraussetzung).',
),
],
'SuperTrendMultiTf': [
StrategyParameterDef(
name: 'Period',
label: 'SuperTrend-Periode',
defaultValue: 10,
isInteger: true,
hint: 'ATR-Periode, die der SuperTrend-Indikator auf beiden Zeitebenen (1h und 15m) zugrunde legt.',
),
StrategyParameterDef(
name: 'Multiplier',
label: 'SuperTrend-Multiplikator',
defaultValue: 3.0,
hint: 'Wie weit die SuperTrend-Linie von der ATR-Bandbreite entfernt liegt. Größer = trägere, glattere Linie.',
),
],
'MacdCrossover': [
StrategyParameterDef(
name: 'FastPeriod',
label: 'MACD schnell',
defaultValue: 12,
isInteger: true,
hint: 'Perioden der schnellen EMA im MACD.',
),
StrategyParameterDef(
name: 'SlowPeriod',
label: 'MACD langsam',
defaultValue: 26,
isInteger: true,
hint: 'Perioden der langsamen EMA im MACD.',
),
StrategyParameterDef(
name: 'SignalPeriod',
label: 'MACD Signal',
defaultValue: 9,
isInteger: true,
hint: 'Perioden der Signal-Linie (EMA der MACD-Linie), gegen die auf Kreuzung geprüft wird.',
),
StrategyParameterDef(
name: 'StopAtrMultiplier',
label: 'Stop-Loss (× ATR)',
defaultValue: 1.5,
hint: 'Abstand des Stop-Loss vom Einstieg, als Vielfaches der aktuellen Volatilität (ATR).',
),
],
'MovingAverageCrossover': [
StrategyParameterDef(
name: 'FastPeriod',
label: 'EMA schnell',
defaultValue: 50,
isInteger: true,
hint: 'Perioden der schnellen EMA (kreuzt für ein Golden/Death Cross durch die langsame EMA).',
),
StrategyParameterDef(
name: 'SlowPeriod',
label: 'EMA langsam',
defaultValue: 200,
isInteger: true,
hint: 'Perioden der langsamen EMA - je größer, desto seltener und langfristiger die Signale.',
),
StrategyParameterDef(
name: 'StopAtrMultiplier',
label: 'Stop-Loss (× ATR)',
defaultValue: 2.0,
hint: 'Abstand des Stop-Loss vom Einstieg, als Vielfaches der aktuellen Volatilität (ATR).',
),
],
'RsiReversal': [
StrategyParameterDef(
name: 'Period',
label: 'RSI-Periode',
defaultValue: 14,
isInteger: true,
hint: 'Anzahl Kerzen, über die der RSI berechnet wird.',
),
StrategyParameterDef(
name: 'OversoldThreshold',
label: 'Überverkauft-Schwelle',
defaultValue: 30,
hint: 'RSI-Schwelle, deren erneutes Überschreiten von unten ein Long-Signal auslöst.',
),
StrategyParameterDef(
name: 'OverboughtThreshold',
label: 'Überkauft-Schwelle',
defaultValue: 70,
hint: 'RSI-Schwelle, deren erneutes Unterschreiten von oben ein Short-Signal auslöst.',
),
StrategyParameterDef(
name: 'StopAtrMultiplier',
label: 'Stop-Loss (× ATR)',
defaultValue: 1.2,
hint: 'Abstand des Stop-Loss vom Einstieg, als Vielfaches der aktuellen Volatilität (ATR).',
),
],
'DonchianBreakout': [
StrategyParameterDef(
name: 'Period',
label: 'Kanal-Periode',
defaultValue: 20,
isInteger: true,
hint: 'Anzahl vorheriger Kerzen, deren Hoch/Tief den Ausbruchskanal bilden. Größer = seltenere, dafür signifikantere Ausbrüche.',
),
],
'VwapBounce': [
StrategyParameterDef(
name: 'EmaFast',
label: 'EMA schnell',
defaultValue: 20,
isInteger: true,
hint: 'Perioden der schnellen EMA, bestimmt zusammen mit der langsamen EMA die Trendrichtung.',
),
StrategyParameterDef(
name: 'EmaSlow',
label: 'EMA langsam',
defaultValue: 50,
isInteger: true,
hint: 'Perioden der langsamen EMA, bestimmt zusammen mit der schnellen EMA die Trendrichtung.',
),
StrategyParameterDef(
name: 'StopAtrMultiplier',
label: 'Stop-Loss (× ATR)',
defaultValue: 1.0,
hint: 'Abstand des Stop-Loss vom Einstieg, als Vielfaches der aktuellen Volatilität (ATR).',
),
],
};
static List<StrategyParameterDef> forStrategy(String strategyKey) => byStrategy[strategyKey] ?? const [];
}