UI: Dashboard-Ueberarbeitung (Scope-Filter, KPIs, ScottPlot-Charts, Tradehistorie)

Das Dashboard ist keine stumpfe Trade-Liste mehr, sondern ein Auswertungs-Fenster:
- ToolStrip (via Designer): Scope-Filter Konto/Modul/Live-Demo/Zeitraum + Aktualisieren.
- TabControl mit 2 Tabs:
  - Dashboard: KPI-Kacheln (Netto-PnL/Winrate/Trades/O-PnL/Profit-Faktor) + 3 Charts
    (Equity-Kurve, PnL je Modul, PnL je Tag) fuer den gewaehlten Scope.
  - Tradehistorie: gefilterte Trade-Liste (Spalten via Designer) + Suche + Gewinner/Verlierer.
- Charts via ScottPlot CORE-Paket (nur SkiaSharp, .NET-nativ) -> als Bitmap in PictureBoxen
  gerendert; KEINE OpenTK/.NET-Framework-Transitiven (bewusst nicht ScottPlot.WinForms).
- Auswertungslogik pur in TradeAnalytics (getestet). In-Memory-Filter auf gecachtem Recent-Set.
- Smoke-UI konstruiert die DashboardView jetzt direkt -> verifiziert das Chart-Rendering headless.

Build 0 Fehler, 331 Tests gruen, --smoke-ui: [OK] core.dashboard konstruiert (inkl. Charts).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-15 19:54:49 +02:00
co-authored by Claude Opus 4.8
parent 7d63791e38
commit b6dff7e210
4 changed files with 568 additions and 72 deletions
+344 -46
View File
@@ -17,9 +17,29 @@ namespace PolyTraderSharp.Ui.Views
private void InitializeComponent()
{
this.pnlTop = new System.Windows.Forms.Panel();
this.lblSummary = new System.Windows.Forms.Label();
this.btnRefresh = new System.Windows.Forms.Button();
this.toolStripDash = new System.Windows.Forms.ToolStrip();
this.tslKonto = new System.Windows.Forms.ToolStripLabel();
this.cbAccount = new System.Windows.Forms.ToolStripComboBox();
this.tslModul = new System.Windows.Forms.ToolStripLabel();
this.cbModule = new System.Windows.Forms.ToolStripComboBox();
this.tslArt = new System.Windows.Forms.ToolStripLabel();
this.cbMode = new System.Windows.Forms.ToolStripComboBox();
this.tslZeit = new System.Windows.Forms.ToolStripLabel();
this.cbRange = new System.Windows.Forms.ToolStripComboBox();
this.tsRefresh = new System.Windows.Forms.ToolStripButton();
this.tabControlDash = new System.Windows.Forms.TabControl();
this.tabDashboard = new System.Windows.Forms.TabPage();
this.picEquity = new System.Windows.Forms.PictureBox();
this.pnlChartsBottom = new System.Windows.Forms.Panel();
this.picDay = new System.Windows.Forms.PictureBox();
this.picModule = new System.Windows.Forms.PictureBox();
this.flpKpis = new System.Windows.Forms.FlowLayoutPanel();
this.lblKpiPnl = new System.Windows.Forms.Label();
this.lblKpiWin = new System.Windows.Forms.Label();
this.lblKpiTrades = new System.Windows.Forms.Label();
this.lblKpiAvg = new System.Windows.Forms.Label();
this.lblKpiPf = new System.Windows.Forms.Label();
this.tabHistory = new System.Windows.Forms.TabPage();
this.dgvTrades = new System.Windows.Forms.DataGridView();
this.colModule = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colAccount = new System.Windows.Forms.DataGridViewTextBoxColumn();
@@ -32,37 +52,242 @@ namespace PolyTraderSharp.Ui.Views
this.colPnl = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colPnlPct = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colClosedAt = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.pnlTop.SuspendLayout();
this.pnlHistFilters = new System.Windows.Forms.Panel();
this.lblSuche = new System.Windows.Forms.Label();
this.tbSearch = new System.Windows.Forms.TextBox();
this.lblErgebnis = new System.Windows.Forms.Label();
this.cbWinLoss = new System.Windows.Forms.ComboBox();
this.toolStripDash.SuspendLayout();
this.tabControlDash.SuspendLayout();
this.tabDashboard.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picEquity)).BeginInit();
this.pnlChartsBottom.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picDay)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picModule)).BeginInit();
this.flpKpis.SuspendLayout();
this.tabHistory.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvTrades)).BeginInit();
this.pnlHistFilters.SuspendLayout();
this.SuspendLayout();
//
// pnlTop
// toolStripDash
//
this.pnlTop.Controls.Add(this.lblSummary);
this.pnlTop.Controls.Add(this.btnRefresh);
this.pnlTop.Dock = System.Windows.Forms.DockStyle.Top;
this.pnlTop.Location = new System.Drawing.Point(0, 0);
this.pnlTop.Name = "pnlTop";
this.pnlTop.Size = new System.Drawing.Size(1100, 40);
this.pnlTop.TabIndex = 0;
this.toolStripDash.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.tslKonto, this.cbAccount, this.tslModul, this.cbModule, this.tslArt, this.cbMode,
this.tslZeit, this.cbRange, this.tsRefresh});
this.toolStripDash.Location = new System.Drawing.Point(0, 0);
this.toolStripDash.Name = "toolStripDash";
this.toolStripDash.Size = new System.Drawing.Size(1200, 27);
this.toolStripDash.TabIndex = 0;
//
// lblSummary
// tslKonto
//
this.lblSummary.AutoSize = true;
this.lblSummary.Location = new System.Drawing.Point(148, 12);
this.lblSummary.Name = "lblSummary";
this.lblSummary.Size = new System.Drawing.Size(63, 15);
this.lblSummary.TabIndex = 1;
this.lblSummary.Text = "—";
this.tslKonto.Name = "tslKonto";
this.tslKonto.Text = "Konto:";
//
// btnRefresh
// cbAccount
//
this.btnRefresh.Location = new System.Drawing.Point(8, 6);
this.btnRefresh.Name = "btnRefresh";
this.btnRefresh.Size = new System.Drawing.Size(130, 28);
this.btnRefresh.TabIndex = 0;
this.btnRefresh.Text = "Aktualisieren";
this.btnRefresh.UseVisualStyleBackColor = true;
this.cbAccount.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbAccount.Name = "cbAccount";
this.cbAccount.Size = new System.Drawing.Size(170, 27);
//
// tslModul
//
this.tslModul.Name = "tslModul";
this.tslModul.Text = "Modul:";
//
// cbModule
//
this.cbModule.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbModule.Name = "cbModule";
this.cbModule.Size = new System.Drawing.Size(150, 27);
//
// tslArt
//
this.tslArt.Name = "tslArt";
this.tslArt.Text = "Art:";
//
// cbMode
//
this.cbMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbMode.Name = "cbMode";
this.cbMode.Size = new System.Drawing.Size(100, 27);
//
// tslZeit
//
this.tslZeit.Name = "tslZeit";
this.tslZeit.Text = "Zeitraum:";
//
// cbRange
//
this.cbRange.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbRange.Name = "cbRange";
this.cbRange.Size = new System.Drawing.Size(110, 27);
//
// tsRefresh
//
this.tsRefresh.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
this.tsRefresh.Name = "tsRefresh";
this.tsRefresh.Text = "Aktualisieren";
//
// tabControlDash
//
this.tabControlDash.Controls.Add(this.tabDashboard);
this.tabControlDash.Controls.Add(this.tabHistory);
this.tabControlDash.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControlDash.Location = new System.Drawing.Point(0, 27);
this.tabControlDash.Name = "tabControlDash";
this.tabControlDash.SelectedIndex = 0;
this.tabControlDash.Size = new System.Drawing.Size(1200, 623);
this.tabControlDash.TabIndex = 1;
//
// tabDashboard
//
this.tabDashboard.Controls.Add(this.picEquity);
this.tabDashboard.Controls.Add(this.pnlChartsBottom);
this.tabDashboard.Controls.Add(this.flpKpis);
this.tabDashboard.Location = new System.Drawing.Point(4, 24);
this.tabDashboard.Name = "tabDashboard";
this.tabDashboard.Padding = new System.Windows.Forms.Padding(3);
this.tabDashboard.Size = new System.Drawing.Size(1192, 595);
this.tabDashboard.TabIndex = 0;
this.tabDashboard.Text = "Dashboard";
this.tabDashboard.UseVisualStyleBackColor = true;
//
// picEquity
//
this.picEquity.BackColor = System.Drawing.Color.White;
this.picEquity.Dock = System.Windows.Forms.DockStyle.Fill;
this.picEquity.Location = new System.Drawing.Point(3, 79);
this.picEquity.Name = "picEquity";
this.picEquity.Size = new System.Drawing.Size(1186, 273);
this.picEquity.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.picEquity.TabIndex = 2;
this.picEquity.TabStop = false;
//
// pnlChartsBottom
//
this.pnlChartsBottom.Controls.Add(this.picDay);
this.pnlChartsBottom.Controls.Add(this.picModule);
this.pnlChartsBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnlChartsBottom.Location = new System.Drawing.Point(3, 352);
this.pnlChartsBottom.Name = "pnlChartsBottom";
this.pnlChartsBottom.Size = new System.Drawing.Size(1186, 240);
this.pnlChartsBottom.TabIndex = 1;
//
// picDay
//
this.picDay.BackColor = System.Drawing.Color.White;
this.picDay.Dock = System.Windows.Forms.DockStyle.Fill;
this.picDay.Location = new System.Drawing.Point(593, 0);
this.picDay.Name = "picDay";
this.picDay.Size = new System.Drawing.Size(593, 240);
this.picDay.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.picDay.TabIndex = 1;
this.picDay.TabStop = false;
//
// picModule
//
this.picModule.BackColor = System.Drawing.Color.White;
this.picModule.Dock = System.Windows.Forms.DockStyle.Left;
this.picModule.Location = new System.Drawing.Point(0, 0);
this.picModule.Name = "picModule";
this.picModule.Size = new System.Drawing.Size(593, 240);
this.picModule.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
this.picModule.TabIndex = 0;
this.picModule.TabStop = false;
//
// flpKpis
//
this.flpKpis.Controls.Add(this.lblKpiPnl);
this.flpKpis.Controls.Add(this.lblKpiWin);
this.flpKpis.Controls.Add(this.lblKpiTrades);
this.flpKpis.Controls.Add(this.lblKpiAvg);
this.flpKpis.Controls.Add(this.lblKpiPf);
this.flpKpis.Dock = System.Windows.Forms.DockStyle.Top;
this.flpKpis.Location = new System.Drawing.Point(3, 3);
this.flpKpis.Name = "flpKpis";
this.flpKpis.Padding = new System.Windows.Forms.Padding(4);
this.flpKpis.Size = new System.Drawing.Size(1186, 76);
this.flpKpis.TabIndex = 0;
this.flpKpis.WrapContents = false;
//
// lblKpiPnl
//
this.lblKpiPnl.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.lblKpiPnl.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold);
this.lblKpiPnl.Margin = new System.Windows.Forms.Padding(4);
this.lblKpiPnl.MinimumSize = new System.Drawing.Size(190, 56);
this.lblKpiPnl.Name = "lblKpiPnl";
this.lblKpiPnl.Padding = new System.Windows.Forms.Padding(8);
this.lblKpiPnl.Size = new System.Drawing.Size(190, 56);
this.lblKpiPnl.TabIndex = 0;
this.lblKpiPnl.Text = "Netto-PnL\n—";
this.lblKpiPnl.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// lblKpiWin
//
this.lblKpiWin.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.lblKpiWin.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold);
this.lblKpiWin.Margin = new System.Windows.Forms.Padding(4);
this.lblKpiWin.MinimumSize = new System.Drawing.Size(150, 56);
this.lblKpiWin.Name = "lblKpiWin";
this.lblKpiWin.Padding = new System.Windows.Forms.Padding(8);
this.lblKpiWin.Size = new System.Drawing.Size(150, 56);
this.lblKpiWin.TabIndex = 1;
this.lblKpiWin.Text = "Winrate\n—";
this.lblKpiWin.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// lblKpiTrades
//
this.lblKpiTrades.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.lblKpiTrades.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold);
this.lblKpiTrades.Margin = new System.Windows.Forms.Padding(4);
this.lblKpiTrades.MinimumSize = new System.Drawing.Size(130, 56);
this.lblKpiTrades.Name = "lblKpiTrades";
this.lblKpiTrades.Padding = new System.Windows.Forms.Padding(8);
this.lblKpiTrades.Size = new System.Drawing.Size(130, 56);
this.lblKpiTrades.TabIndex = 2;
this.lblKpiTrades.Text = "Trades\n—";
this.lblKpiTrades.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// lblKpiAvg
//
this.lblKpiAvg.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.lblKpiAvg.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold);
this.lblKpiAvg.Margin = new System.Windows.Forms.Padding(4);
this.lblKpiAvg.MinimumSize = new System.Drawing.Size(170, 56);
this.lblKpiAvg.Name = "lblKpiAvg";
this.lblKpiAvg.Padding = new System.Windows.Forms.Padding(8);
this.lblKpiAvg.Size = new System.Drawing.Size(170, 56);
this.lblKpiAvg.TabIndex = 3;
this.lblKpiAvg.Text = "Ø PnL/Trade\n—";
this.lblKpiAvg.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// lblKpiPf
//
this.lblKpiPf.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.lblKpiPf.Font = new System.Drawing.Font("Segoe UI", 10F, System.Drawing.FontStyle.Bold);
this.lblKpiPf.Margin = new System.Windows.Forms.Padding(4);
this.lblKpiPf.MinimumSize = new System.Drawing.Size(150, 56);
this.lblKpiPf.Name = "lblKpiPf";
this.lblKpiPf.Padding = new System.Windows.Forms.Padding(8);
this.lblKpiPf.Size = new System.Drawing.Size(150, 56);
this.lblKpiPf.TabIndex = 4;
this.lblKpiPf.Text = "Profit-Faktor\n—";
this.lblKpiPf.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// tabHistory
//
this.tabHistory.Controls.Add(this.dgvTrades);
this.tabHistory.Controls.Add(this.pnlHistFilters);
this.tabHistory.Location = new System.Drawing.Point(4, 24);
this.tabHistory.Name = "tabHistory";
this.tabHistory.Padding = new System.Windows.Forms.Padding(3);
this.tabHistory.Size = new System.Drawing.Size(1192, 595);
this.tabHistory.TabIndex = 1;
this.tabHistory.Text = "Tradehistorie";
this.tabHistory.UseVisualStyleBackColor = true;
//
// dgvTrades
//
@@ -71,23 +296,14 @@ namespace PolyTraderSharp.Ui.Views
this.dgvTrades.AutoGenerateColumns = false;
this.dgvTrades.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgvTrades.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.colModule,
this.colAccount,
this.colMarket,
this.colOutcome,
this.colSide,
this.colEntry,
this.colExit,
this.colSize,
this.colPnl,
this.colPnlPct,
this.colClosedAt});
this.colModule, this.colAccount, this.colMarket, this.colOutcome, this.colSide,
this.colEntry, this.colExit, this.colSize, this.colPnl, this.colPnlPct, this.colClosedAt});
this.dgvTrades.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgvTrades.Location = new System.Drawing.Point(0, 40);
this.dgvTrades.Location = new System.Drawing.Point(3, 39);
this.dgvTrades.Name = "dgvTrades";
this.dgvTrades.ReadOnly = true;
this.dgvTrades.RowHeadersVisible = false;
this.dgvTrades.Size = new System.Drawing.Size(1100, 560);
this.dgvTrades.Size = new System.Drawing.Size(1186, 553);
this.dgvTrades.TabIndex = 1;
//
// colModule
@@ -167,26 +383,108 @@ namespace PolyTraderSharp.Ui.Views
this.colClosedAt.Name = "colClosedAt";
this.colClosedAt.Width = 140;
//
// pnlHistFilters
//
this.pnlHistFilters.Controls.Add(this.cbWinLoss);
this.pnlHistFilters.Controls.Add(this.lblErgebnis);
this.pnlHistFilters.Controls.Add(this.tbSearch);
this.pnlHistFilters.Controls.Add(this.lblSuche);
this.pnlHistFilters.Dock = System.Windows.Forms.DockStyle.Top;
this.pnlHistFilters.Location = new System.Drawing.Point(3, 3);
this.pnlHistFilters.Name = "pnlHistFilters";
this.pnlHistFilters.Size = new System.Drawing.Size(1186, 36);
this.pnlHistFilters.TabIndex = 0;
//
// lblSuche
//
this.lblSuche.AutoSize = true;
this.lblSuche.Location = new System.Drawing.Point(6, 9);
this.lblSuche.Name = "lblSuche";
this.lblSuche.Size = new System.Drawing.Size(45, 15);
this.lblSuche.TabIndex = 0;
this.lblSuche.Text = "Suche:";
//
// tbSearch
//
this.tbSearch.Location = new System.Drawing.Point(57, 6);
this.tbSearch.Name = "tbSearch";
this.tbSearch.PlaceholderText = "Markt / Outcome …";
this.tbSearch.Size = new System.Drawing.Size(280, 23);
this.tbSearch.TabIndex = 1;
//
// lblErgebnis
//
this.lblErgebnis.AutoSize = true;
this.lblErgebnis.Location = new System.Drawing.Point(360, 9);
this.lblErgebnis.Name = "lblErgebnis";
this.lblErgebnis.Size = new System.Drawing.Size(58, 15);
this.lblErgebnis.TabIndex = 2;
this.lblErgebnis.Text = "Ergebnis:";
//
// cbWinLoss
//
this.cbWinLoss.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cbWinLoss.Location = new System.Drawing.Point(424, 6);
this.cbWinLoss.Name = "cbWinLoss";
this.cbWinLoss.Size = new System.Drawing.Size(150, 23);
this.cbWinLoss.TabIndex = 3;
//
// DashboardView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.dgvTrades);
this.Controls.Add(this.pnlTop);
this.Controls.Add(this.tabControlDash);
this.Controls.Add(this.toolStripDash);
this.ClientSize = new System.Drawing.Size(1200, 650);
this.Name = "DashboardView";
this.Text = "Dashboard";
this.pnlTop.ResumeLayout(false);
this.pnlTop.PerformLayout();
this.toolStripDash.ResumeLayout(false);
this.toolStripDash.PerformLayout();
this.tabControlDash.ResumeLayout(false);
this.tabDashboard.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.picEquity)).EndInit();
this.pnlChartsBottom.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.picDay)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picModule)).EndInit();
this.flpKpis.ResumeLayout(false);
this.tabHistory.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.dgvTrades)).EndInit();
this.pnlHistFilters.ResumeLayout(false);
this.pnlHistFilters.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel pnlTop;
private System.Windows.Forms.Button btnRefresh;
private System.Windows.Forms.Label lblSummary;
private System.Windows.Forms.ToolStrip toolStripDash;
private System.Windows.Forms.ToolStripLabel tslKonto;
private System.Windows.Forms.ToolStripComboBox cbAccount;
private System.Windows.Forms.ToolStripLabel tslModul;
private System.Windows.Forms.ToolStripComboBox cbModule;
private System.Windows.Forms.ToolStripLabel tslArt;
private System.Windows.Forms.ToolStripComboBox cbMode;
private System.Windows.Forms.ToolStripLabel tslZeit;
private System.Windows.Forms.ToolStripComboBox cbRange;
private System.Windows.Forms.ToolStripButton tsRefresh;
private System.Windows.Forms.TabControl tabControlDash;
private System.Windows.Forms.TabPage tabDashboard;
private System.Windows.Forms.FlowLayoutPanel flpKpis;
private System.Windows.Forms.Label lblKpiPnl;
private System.Windows.Forms.Label lblKpiWin;
private System.Windows.Forms.Label lblKpiTrades;
private System.Windows.Forms.Label lblKpiAvg;
private System.Windows.Forms.Label lblKpiPf;
private System.Windows.Forms.Panel pnlChartsBottom;
private System.Windows.Forms.PictureBox picModule;
private System.Windows.Forms.PictureBox picDay;
private System.Windows.Forms.PictureBox picEquity;
private System.Windows.Forms.TabPage tabHistory;
private System.Windows.Forms.Panel pnlHistFilters;
private System.Windows.Forms.Label lblSuche;
private System.Windows.Forms.TextBox tbSearch;
private System.Windows.Forms.Label lblErgebnis;
private System.Windows.Forms.ComboBox cbWinLoss;
private System.Windows.Forms.DataGridView dgvTrades;
private System.Windows.Forms.DataGridViewTextBoxColumn colModule;
private System.Windows.Forms.DataGridViewTextBoxColumn colAccount;