diff --git a/src/PolyTrader.Modules.Accounting/AccountingModule.cs b/src/PolyTrader.Modules.Accounting/AccountingModule.cs index 107ac02..5a73860 100644 --- a/src/PolyTrader.Modules.Accounting/AccountingModule.cs +++ b/src/PolyTrader.Modules.Accounting/AccountingModule.cs @@ -49,21 +49,22 @@ namespace PolyTrader.Modules.Accounting services.AddHostedService(sp => sp.GetRequiredService()); } - public void RegisterUi(IModuleUiHost host, System.IServiceProvider services) + /// + /// Aktuell ohne Ansicht: Die WinForms-UI wurde mit der Linux-Portierung entfernt, die + /// Avalonia-Ansicht folgt (Stufe L3/L4). Die Fachlogik dieses Moduls laeuft davon + /// unabhaengig weiter – die Shell zeigt schlicht kein Fenster fuer das Modul an. + /// + /// Beim Nachbau zu erhalten (Spezifikation: docs/UI-SPEZIFIKATION-WinForms.md, + /// Originalcode: Git-Tag winforms-final): + /// + /// View-ID accounting.main (stabil – Launcher-Button und Symbol haengen daran) + /// Titel Accounting, Gruppe Accounting, Order 400 + /// Ein Fenster fuers ganze Modul: AccountingMainForm mit Tabs: Uebersicht+BWA / Ledger / Abruf+Status + /// + /// + public void RegisterUi(IModuleUiHost host, IServiceProvider services) { - host.RegisterView(new ModuleView - { - Id = "accounting.main", - Title = "Accounting", - Group = "Accounting", - Order = 400, - CreateView = () => - { - var form = new Ui.AccountingMainForm(); - form.Initialize(services); - return form; - } - }); + // Bewusst leer, bis die Avalonia-Ansicht steht (siehe Doku oben). } public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; diff --git a/src/PolyTrader.Modules.Accounting/Logic/PdfExporter.cs b/src/PolyTrader.Modules.Accounting/Logic/PdfExporter.cs index 7b2e533..bd39773 100644 --- a/src/PolyTrader.Modules.Accounting/Logic/PdfExporter.cs +++ b/src/PolyTrader.Modules.Accounting/Logic/PdfExporter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -28,9 +28,15 @@ namespace PolyTrader.Modules.Accounting.Logic decimal V(decimal usdc) => Math.Round(usdc * currencyFactor, 2, MidpointRounding.AwayFromZero); string M(decimal usdc) => V(usdc).ToString("N2") + " " + currencyCode; + // Schriftauflösung sicherstellen: der PDFsharp-Core-Build findet ohne Resolver keine + // Systemschriften (siehe PdfFontResolver). Idempotent, kostet nach dem ersten Mal nichts. + PdfFontResolver.EnsureRegistered(); + var doc = new Document(); doc.Info.Title = "Buchhalterische Abrechnung"; var style = doc.Styles["Normal"]; + // Wunschschrift; der Resolver weicht auf eine verfügbare aus, wenn es sie nicht gibt + // (auf Linux z.B. DejaVu Sans). style.Font.Name = "Segoe UI"; style.Font.Size = 9; diff --git a/src/PolyTrader.Modules.Accounting/Logic/PdfFontResolver.cs b/src/PolyTrader.Modules.Accounting/Logic/PdfFontResolver.cs new file mode 100644 index 0000000..c02a2f8 --- /dev/null +++ b/src/PolyTrader.Modules.Accounting/Logic/PdfFontResolver.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using PdfSharp.Fonts; + +namespace PolyTrader.Modules.Accounting.Logic +{ + /// + /// Schriftauflösung für den PDF-Export. Nötig, seit der plattformneutrale PDFsharp-Core-Build + /// verwendet wird: der frühere -GDI-Build zog Systemschriften über + /// System.Drawing.Common, das seit .NET 7 Windows-only ist. Der Core-Build bringt keine + /// eigene Schriftsuche mit und braucht deshalb diesen Resolver. + /// + /// Der Resolver durchsucht die üblichen Schriftverzeichnisse des Betriebssystems nach einer + /// Kandidatenliste (Windows: Segoe UI/Arial, Linux: DejaVu/Liberation/Noto). Damit sind keine + /// Schriftdateien im Repository nötig und die Lizenzfrage der Schriften bleibt beim System. + /// + /// Voraussetzung auf Linux: mindestens eine der Kandidatenschriften muss installiert + /// sein. Auf Desktop-Distributionen ist das der Normalfall; auf schlanken Servern/Containern + /// genügt apt install fonts-dejavu-core (bzw. fonts-liberation). Fehlt jede Schrift, + /// wirft beim ersten Export eine Meldung mit genau diesem Hinweis – + /// besser als eine kryptische Meldung aus dem Renderer-Inneren. + /// + public sealed class PdfFontResolver : IFontResolver + { + /// Bevorzugte Schriftfamilien in Reihenfolge – erste gefundene gewinnt. + private static readonly string[] PreferredFamilies = + { + "Segoe UI", "DejaVu Sans", "Liberation Sans", "Noto Sans", "Arial", "FreeSans" + }; + + /// Dateinamens-Kandidaten je Familie und Schnitt (klein geschrieben, ohne Endung). + private static readonly Dictionary FileNames = new(StringComparer.OrdinalIgnoreCase) + { + ["Segoe UI"] = ("segoeui", "segoeuib"), + ["DejaVu Sans"] = ("DejaVuSans", "DejaVuSans-Bold"), + ["Liberation Sans"] = ("LiberationSans-Regular", "LiberationSans-Bold"), + ["Noto Sans"] = ("NotoSans-Regular", "NotoSans-Bold"), + ["Arial"] = ("arial", "arialbd"), + ["FreeSans"] = ("FreeSans", "FreeSansBold"), + }; + + private static readonly ConcurrentDictionary Cache = new(); + private static readonly object RegisterLock = new(); + private static bool _registered; + + /// + /// Registriert den Resolver einmalig global. Muss vor dem ersten Rendern laufen; mehrfache + /// Aufrufe sind unschädlich (PDFsharp erlaubt nur eine Zuweisung pro Prozess). + /// + public static void EnsureRegistered() + { + if (_registered) return; + lock (RegisterLock) + { + if (_registered) return; + if (FindAnyAvailableFamily() == null) + { + throw new InvalidOperationException( + "Keine geeignete Schriftart gefunden. Der PDF-Export braucht mindestens eine von: " + + string.Join(", ", PreferredFamilies) + ". " + + "Auf schlanken Linux-Systemen nachinstallieren, z.B. 'apt install fonts-dejavu-core'."); + } + GlobalFontSettings.FontResolver = new PdfFontResolver(); + _registered = true; + } + } + + /// Erste verfügbare Familie aus , sonst null. + internal static string? FindAnyAvailableFamily() => + PreferredFamilies.FirstOrDefault(f => LocateFile(f, bold: false) != null); + + public FontResolverInfo? ResolveTypeface(string familyName, bool isBold, bool isItalic) + { + // Angeforderte Familie bevorzugen, sonst die erste verfügbare (z.B. "Segoe UI" auf Linux). + string? family = LocateFile(familyName, isBold) != null ? familyName : FindAnyAvailableFamily(); + if (family == null) return null; + + // Kursiv wird bewusst nicht aufgelöst: der Bericht nutzt es nicht, und ein fehlender + // Kursiv-Schnitt wäre sonst ein harter Fehler statt einer kleinen Abweichung. + return new FontResolverInfo($"{family}|{(isBold ? "b" : "r")}"); + } + + public byte[]? GetFont(string faceName) + { + return Cache.GetOrAdd(faceName, key => + { + var parts = key.Split('|'); + string family = parts[0]; + bool bold = parts.Length > 1 && parts[1] == "b"; + + string? path = LocateFile(family, bold) ?? LocateFile(family, bold: false); + return path != null ? File.ReadAllBytes(path) : Array.Empty(); + }); + } + + /// Sucht die Datei zu Familie + Schnitt in allen Schriftverzeichnissen des Systems. + private static string? LocateFile(string family, bool bold) + { + if (!FileNames.TryGetValue(family, out var names)) return null; + string stem = bold ? names.Bold : names.Regular; + + foreach (string dir in FontDirectories()) + { + if (!Directory.Exists(dir)) continue; + foreach (string ext in new[] { ".ttf", ".otf" }) + { + try + { + // Rekursiv, weil Linux die Schriften in Unterordnern ablegt (truetype/dejavu/…). + var hit = Directory.EnumerateFiles(dir, stem + ext, SearchOption.AllDirectories) + .FirstOrDefault(); + if (hit != null) return hit; + } + catch (UnauthorizedAccessException) { /* einzelne Ordner ohne Zugriff überspringen */ } + catch (IOException) { /* z.B. defekter Symlink */ } + } + } + return null; + } + + /// Schriftverzeichnisse je Plattform. + private static IEnumerable FontDirectories() + { + if (OperatingSystem.IsWindows()) + { + yield return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Fonts"); + yield break; + } + + if (OperatingSystem.IsMacOS()) + { + yield return "/System/Library/Fonts"; + yield return "/Library/Fonts"; + yield break; + } + + // Linux/Unix + yield return "/usr/share/fonts"; + yield return "/usr/local/share/fonts"; + string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + if (!string.IsNullOrEmpty(home)) + { + yield return Path.Combine(home, ".fonts"); + yield return Path.Combine(home, ".local", "share", "fonts"); + } + } + } +} diff --git a/src/PolyTrader.Modules.Accounting/PolyTrader.Modules.Accounting.csproj b/src/PolyTrader.Modules.Accounting/PolyTrader.Modules.Accounting.csproj index cf0c4a4..c5d7c71 100644 --- a/src/PolyTrader.Modules.Accounting/PolyTrader.Modules.Accounting.csproj +++ b/src/PolyTrader.Modules.Accounting/PolyTrader.Modules.Accounting.csproj @@ -1,11 +1,14 @@ - + - + + all @@ -21,11 +24,12 @@ - net8.0-windows + + net8.0 enable enable - - true diff --git a/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.Designer.cs b/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.Designer.cs deleted file mode 100644 index aabe7ad..0000000 --- a/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.Designer.cs +++ /dev/null @@ -1,609 +0,0 @@ -namespace PolyTrader.Modules.Accounting.Ui -{ - partial class AccountingMainForm - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AccountingMainForm)); - tabControlAcc = new TabControl(); - tabUebersicht = new TabPage(); - dgvMonthly = new DataGridView(); - flpKpis = new FlowLayoutPanel(); - lblKpiNet = new Label(); - lblKpiClosing = new Label(); - lblKpiDeposits = new Label(); - lblKpiWithdrawals = new Label(); - lblKpiFees = new Label(); - lblKpiRewards = new Label(); - lblKpiVolume = new Label(); - lblKpiTrades = new Label(); - pnlOverviewTop = new Panel(); - btnExportPdf = new Button(); - btnExportCsv = new Button(); - btnCalc = new Button(); - cbCurrency = new ComboBox(); - lblWaehrung = new Label(); - dtTo = new DateTimePicker(); - lblBis = new Label(); - dtFrom = new DateTimePicker(); - lblVon = new Label(); - cbOvAccount = new ComboBox(); - lblOvKonto = new Label(); - tabLedger = new TabPage(); - dgvLedger = new DataGridView(); - toolStripLedger = new ToolStrip(); - lblLedgerKonto = new ToolStripLabel(); - cbLedgerAccount = new ToolStripComboBox(); - sepLedger = new ToolStripSeparator(); - btnLedgerRefresh = new ToolStripButton(); - tabStatus = new TabPage(); - dgvRuns = new DataGridView(); - toolStripStatus = new ToolStrip(); - lblStatusKonto = new ToolStripLabel(); - cbStatusAccount = new ToolStripComboBox(); - sepStatus = new ToolStripSeparator(); - btnIncremental = new ToolStripButton(); - btnBackfill = new ToolStripButton(); - sepStatus2 = new ToolStripSeparator(); - btnStatusRefresh = new ToolStripButton(); - lblAccStatus = new Label(); - tabControlAcc.SuspendLayout(); - tabUebersicht.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvMonthly).BeginInit(); - flpKpis.SuspendLayout(); - pnlOverviewTop.SuspendLayout(); - tabLedger.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvLedger).BeginInit(); - toolStripLedger.SuspendLayout(); - tabStatus.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvRuns).BeginInit(); - toolStripStatus.SuspendLayout(); - SuspendLayout(); - // - // tabControlAcc - // - tabControlAcc.Controls.Add(tabUebersicht); - tabControlAcc.Controls.Add(tabLedger); - tabControlAcc.Controls.Add(tabStatus); - tabControlAcc.Dock = DockStyle.Fill; - tabControlAcc.Location = new Point(0, 0); - tabControlAcc.Margin = new Padding(4, 5, 4, 5); - tabControlAcc.Name = "tabControlAcc"; - tabControlAcc.SelectedIndex = 0; - tabControlAcc.Size = new Size(1571, 1030); - tabControlAcc.TabIndex = 0; - // - // tabUebersicht - // - tabUebersicht.Controls.Add(dgvMonthly); - tabUebersicht.Controls.Add(flpKpis); - tabUebersicht.Controls.Add(pnlOverviewTop); - tabUebersicht.Location = new Point(4, 34); - tabUebersicht.Margin = new Padding(4, 5, 4, 5); - tabUebersicht.Name = "tabUebersicht"; - tabUebersicht.Padding = new Padding(4, 5, 4, 5); - tabUebersicht.Size = new Size(1563, 992); - tabUebersicht.TabIndex = 0; - tabUebersicht.Text = "Übersicht / BWA"; - tabUebersicht.UseVisualStyleBackColor = true; - // - // dgvMonthly - // - dgvMonthly.AllowUserToAddRows = false; - dgvMonthly.AllowUserToDeleteRows = false; - dgvMonthly.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvMonthly.Dock = DockStyle.Fill; - dgvMonthly.Location = new Point(4, 222); - dgvMonthly.Margin = new Padding(4, 5, 4, 5); - dgvMonthly.Name = "dgvMonthly"; - dgvMonthly.ReadOnly = true; - dgvMonthly.RowHeadersVisible = false; - dgvMonthly.RowHeadersWidth = 62; - dgvMonthly.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvMonthly.Size = new Size(1555, 765); - dgvMonthly.TabIndex = 2; - // - // flpKpis - // - flpKpis.Controls.Add(lblKpiNet); - flpKpis.Controls.Add(lblKpiClosing); - flpKpis.Controls.Add(lblKpiDeposits); - flpKpis.Controls.Add(lblKpiWithdrawals); - flpKpis.Controls.Add(lblKpiFees); - flpKpis.Controls.Add(lblKpiRewards); - flpKpis.Controls.Add(lblKpiVolume); - flpKpis.Controls.Add(lblKpiTrades); - flpKpis.Dock = DockStyle.Top; - flpKpis.Location = new Point(4, 65); - flpKpis.Margin = new Padding(4, 5, 4, 5); - flpKpis.Name = "flpKpis"; - flpKpis.Padding = new Padding(6, 7, 6, 7); - flpKpis.Size = new Size(1555, 157); - flpKpis.TabIndex = 1; - // - // lblKpiNet - // - lblKpiNet.BorderStyle = BorderStyle.FixedSingle; - lblKpiNet.Font = new Font("Segoe UI", 10F, FontStyle.Bold); - lblKpiNet.Location = new Point(12, 14); - lblKpiNet.Margin = new Padding(6, 7, 6, 7); - lblKpiNet.MinimumSize = new Size(285, 122); - lblKpiNet.Name = "lblKpiNet"; - lblKpiNet.Padding = new Padding(11, 13, 11, 13); - lblKpiNet.Size = new Size(285, 122); - lblKpiNet.TabIndex = 0; - lblKpiNet.Text = "Netto-Handelsergebnis\n—"; - lblKpiNet.TextAlign = ContentAlignment.MiddleLeft; - // - // lblKpiClosing - // - lblKpiClosing.BorderStyle = BorderStyle.FixedSingle; - lblKpiClosing.Font = new Font("Segoe UI", 10F, FontStyle.Bold); - lblKpiClosing.Location = new Point(309, 14); - lblKpiClosing.Margin = new Padding(6, 7, 6, 7); - lblKpiClosing.MinimumSize = new Size(256, 122); - lblKpiClosing.Name = "lblKpiClosing"; - lblKpiClosing.Padding = new Padding(11, 13, 11, 13); - lblKpiClosing.Size = new Size(256, 122); - lblKpiClosing.TabIndex = 1; - lblKpiClosing.Text = "Endsaldo\n—"; - lblKpiClosing.TextAlign = ContentAlignment.MiddleLeft; - // - // lblKpiDeposits - // - lblKpiDeposits.BorderStyle = BorderStyle.FixedSingle; - lblKpiDeposits.Font = new Font("Segoe UI", 10F, FontStyle.Bold); - lblKpiDeposits.Location = new Point(577, 14); - lblKpiDeposits.Margin = new Padding(6, 7, 6, 7); - lblKpiDeposits.MinimumSize = new Size(213, 122); - lblKpiDeposits.Name = "lblKpiDeposits"; - lblKpiDeposits.Padding = new Padding(11, 13, 11, 13); - lblKpiDeposits.Size = new Size(213, 122); - lblKpiDeposits.TabIndex = 2; - lblKpiDeposits.Text = "Einzahlungen\n—"; - lblKpiDeposits.TextAlign = ContentAlignment.MiddleLeft; - // - // lblKpiWithdrawals - // - lblKpiWithdrawals.BorderStyle = BorderStyle.FixedSingle; - lblKpiWithdrawals.Font = new Font("Segoe UI", 10F, FontStyle.Bold); - lblKpiWithdrawals.Location = new Point(802, 14); - lblKpiWithdrawals.Margin = new Padding(6, 7, 6, 7); - lblKpiWithdrawals.MinimumSize = new Size(213, 122); - lblKpiWithdrawals.Name = "lblKpiWithdrawals"; - lblKpiWithdrawals.Padding = new Padding(11, 13, 11, 13); - lblKpiWithdrawals.Size = new Size(213, 122); - lblKpiWithdrawals.TabIndex = 3; - lblKpiWithdrawals.Text = "Auszahlungen\n—"; - lblKpiWithdrawals.TextAlign = ContentAlignment.MiddleLeft; - // - // lblKpiFees - // - lblKpiFees.BorderStyle = BorderStyle.FixedSingle; - lblKpiFees.Font = new Font("Segoe UI", 10F, FontStyle.Bold); - lblKpiFees.Location = new Point(1027, 14); - lblKpiFees.Margin = new Padding(6, 7, 6, 7); - lblKpiFees.MinimumSize = new Size(199, 122); - lblKpiFees.Name = "lblKpiFees"; - lblKpiFees.Padding = new Padding(11, 13, 11, 13); - lblKpiFees.Size = new Size(199, 122); - lblKpiFees.TabIndex = 4; - lblKpiFees.Text = "Fees\n—"; - lblKpiFees.TextAlign = ContentAlignment.MiddleLeft; - // - // lblKpiRewards - // - lblKpiRewards.BorderStyle = BorderStyle.FixedSingle; - lblKpiRewards.Font = new Font("Segoe UI", 10F, FontStyle.Bold); - lblKpiRewards.Location = new Point(1238, 14); - lblKpiRewards.Margin = new Padding(6, 7, 6, 7); - lblKpiRewards.MinimumSize = new Size(199, 122); - lblKpiRewards.Name = "lblKpiRewards"; - lblKpiRewards.Padding = new Padding(11, 13, 11, 13); - lblKpiRewards.Size = new Size(199, 122); - lblKpiRewards.TabIndex = 5; - lblKpiRewards.Text = "Rewards\n—"; - lblKpiRewards.TextAlign = ContentAlignment.MiddleLeft; - // - // lblKpiVolume - // - lblKpiVolume.BorderStyle = BorderStyle.FixedSingle; - lblKpiVolume.Font = new Font("Segoe UI", 10F, FontStyle.Bold); - lblKpiVolume.Location = new Point(12, 150); - lblKpiVolume.Margin = new Padding(6, 7, 6, 7); - lblKpiVolume.MinimumSize = new Size(228, 122); - lblKpiVolume.Name = "lblKpiVolume"; - lblKpiVolume.Padding = new Padding(11, 13, 11, 13); - lblKpiVolume.Size = new Size(228, 122); - lblKpiVolume.TabIndex = 6; - lblKpiVolume.Text = "Handelsvolumen\n—"; - lblKpiVolume.TextAlign = ContentAlignment.MiddleLeft; - // - // lblKpiTrades - // - lblKpiTrades.BorderStyle = BorderStyle.FixedSingle; - lblKpiTrades.Font = new Font("Segoe UI", 10F, FontStyle.Bold); - lblKpiTrades.Location = new Point(252, 150); - lblKpiTrades.Margin = new Padding(6, 7, 6, 7); - lblKpiTrades.MinimumSize = new Size(171, 122); - lblKpiTrades.Name = "lblKpiTrades"; - lblKpiTrades.Padding = new Padding(11, 13, 11, 13); - lblKpiTrades.Size = new Size(171, 122); - lblKpiTrades.TabIndex = 7; - lblKpiTrades.Text = "Trades\n—"; - lblKpiTrades.TextAlign = ContentAlignment.MiddleLeft; - // - // pnlOverviewTop - // - pnlOverviewTop.Controls.Add(btnExportPdf); - pnlOverviewTop.Controls.Add(btnExportCsv); - pnlOverviewTop.Controls.Add(btnCalc); - pnlOverviewTop.Controls.Add(cbCurrency); - pnlOverviewTop.Controls.Add(lblWaehrung); - pnlOverviewTop.Controls.Add(dtTo); - pnlOverviewTop.Controls.Add(lblBis); - pnlOverviewTop.Controls.Add(dtFrom); - pnlOverviewTop.Controls.Add(lblVon); - pnlOverviewTop.Controls.Add(cbOvAccount); - pnlOverviewTop.Controls.Add(lblOvKonto); - pnlOverviewTop.Dock = DockStyle.Top; - pnlOverviewTop.Location = new Point(4, 5); - pnlOverviewTop.Margin = new Padding(4, 5, 4, 5); - pnlOverviewTop.Name = "pnlOverviewTop"; - pnlOverviewTop.Size = new Size(1555, 60); - pnlOverviewTop.TabIndex = 0; - // - // btnExportPdf - // - btnExportPdf.Location = new Point(1334, 8); - btnExportPdf.Margin = new Padding(4, 5, 4, 5); - btnExportPdf.Name = "btnExportPdf"; - btnExportPdf.Size = new Size(129, 43); - btnExportPdf.TabIndex = 10; - btnExportPdf.Text = "PDF-Export"; - btnExportPdf.UseVisualStyleBackColor = true; - // - // btnExportCsv - // - btnExportCsv.Location = new Point(1197, 8); - btnExportCsv.Margin = new Padding(4, 5, 4, 5); - btnExportCsv.Name = "btnExportCsv"; - btnExportCsv.Size = new Size(129, 43); - btnExportCsv.TabIndex = 9; - btnExportCsv.Text = "CSV-Export"; - btnExportCsv.UseVisualStyleBackColor = true; - // - // btnCalc - // - btnCalc.Location = new Point(1046, 8); - btnCalc.Margin = new Padding(4, 5, 4, 5); - btnCalc.Name = "btnCalc"; - btnCalc.Size = new Size(143, 43); - btnCalc.TabIndex = 8; - btnCalc.Text = "Berechnen"; - btnCalc.UseVisualStyleBackColor = true; - // - // cbCurrency - // - cbCurrency.DropDownStyle = ComboBoxStyle.DropDownList; - cbCurrency.Items.AddRange(new object[] { "USDC", "USD", "EUR" }); - cbCurrency.Location = new Point(921, 10); - cbCurrency.Margin = new Padding(4, 5, 4, 5); - cbCurrency.Name = "cbCurrency"; - cbCurrency.Size = new Size(113, 33); - cbCurrency.TabIndex = 7; - // - // lblWaehrung - // - lblWaehrung.AutoSize = true; - lblWaehrung.Location = new Point(821, 15); - lblWaehrung.Margin = new Padding(4, 0, 4, 0); - lblWaehrung.Name = "lblWaehrung"; - lblWaehrung.Size = new Size(88, 25); - lblWaehrung.TabIndex = 6; - lblWaehrung.Text = "Währung:"; - // - // dtTo - // - dtTo.Format = DateTimePickerFormat.Short; - dtTo.Location = new Point(636, 10); - dtTo.Margin = new Padding(4, 5, 4, 5); - dtTo.Name = "dtTo"; - dtTo.Size = new Size(155, 31); - dtTo.TabIndex = 5; - // - // lblBis - // - lblBis.AutoSize = true; - lblBis.Location = new Point(593, 15); - lblBis.Margin = new Padding(4, 0, 4, 0); - lblBis.Name = "lblBis"; - lblBis.Size = new Size(38, 25); - lblBis.TabIndex = 4; - lblBis.Text = "Bis:"; - // - // dtFrom - // - dtFrom.Format = DateTimePickerFormat.Short; - dtFrom.Location = new Point(429, 10); - dtFrom.Margin = new Padding(4, 5, 4, 5); - dtFrom.Name = "dtFrom"; - dtFrom.Size = new Size(155, 31); - dtFrom.TabIndex = 3; - // - // lblVon - // - lblVon.AutoSize = true; - lblVon.Location = new Point(381, 15); - lblVon.Margin = new Padding(4, 0, 4, 0); - lblVon.Name = "lblVon"; - lblVon.Size = new Size(47, 25); - lblVon.TabIndex = 2; - lblVon.Text = "Von:"; - // - // cbOvAccount - // - cbOvAccount.DropDownStyle = ComboBoxStyle.DropDownList; - cbOvAccount.Location = new Point(79, 10); - cbOvAccount.Margin = new Padding(4, 5, 4, 5); - cbOvAccount.Name = "cbOvAccount"; - cbOvAccount.Size = new Size(284, 33); - cbOvAccount.TabIndex = 1; - // - // lblOvKonto - // - lblOvKonto.AutoSize = true; - lblOvKonto.Location = new Point(9, 15); - lblOvKonto.Margin = new Padding(4, 0, 4, 0); - lblOvKonto.Name = "lblOvKonto"; - lblOvKonto.Size = new Size(64, 25); - lblOvKonto.TabIndex = 0; - lblOvKonto.Text = "Konto:"; - // - // tabLedger - // - tabLedger.Controls.Add(dgvLedger); - tabLedger.Controls.Add(toolStripLedger); - tabLedger.Location = new Point(4, 34); - tabLedger.Margin = new Padding(4, 5, 4, 5); - tabLedger.Name = "tabLedger"; - tabLedger.Padding = new Padding(4, 5, 4, 5); - tabLedger.Size = new Size(1563, 992); - tabLedger.TabIndex = 1; - tabLedger.Text = "Ledger"; - tabLedger.UseVisualStyleBackColor = true; - // - // dgvLedger - // - dgvLedger.AllowUserToAddRows = false; - dgvLedger.AllowUserToDeleteRows = false; - dgvLedger.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvLedger.Dock = DockStyle.Fill; - dgvLedger.Location = new Point(4, 39); - dgvLedger.Margin = new Padding(4, 5, 4, 5); - dgvLedger.Name = "dgvLedger"; - dgvLedger.ReadOnly = true; - dgvLedger.RowHeadersVisible = false; - dgvLedger.RowHeadersWidth = 62; - dgvLedger.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvLedger.Size = new Size(1555, 948); - dgvLedger.TabIndex = 1; - // - // toolStripLedger - // - toolStripLedger.ImageScalingSize = new Size(24, 24); - toolStripLedger.Items.AddRange(new ToolStripItem[] { lblLedgerKonto, cbLedgerAccount, sepLedger, btnLedgerRefresh }); - toolStripLedger.Location = new Point(4, 5); - toolStripLedger.Name = "toolStripLedger"; - toolStripLedger.Padding = new Padding(0, 0, 3, 0); - toolStripLedger.Size = new Size(1555, 34); - toolStripLedger.TabIndex = 0; - // - // lblLedgerKonto - // - lblLedgerKonto.Name = "lblLedgerKonto"; - lblLedgerKonto.Size = new Size(64, 29); - lblLedgerKonto.Text = "Konto:"; - // - // cbLedgerAccount - // - cbLedgerAccount.DropDownStyle = ComboBoxStyle.DropDownList; - cbLedgerAccount.Name = "cbLedgerAccount"; - cbLedgerAccount.Size = new Size(341, 34); - // - // sepLedger - // - sepLedger.Name = "sepLedger"; - sepLedger.Size = new Size(6, 34); - // - // btnLedgerRefresh - // - btnLedgerRefresh.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnLedgerRefresh.Name = "btnLedgerRefresh"; - btnLedgerRefresh.Size = new Size(116, 29); - btnLedgerRefresh.Text = "Aktualisieren"; - // - // tabStatus - // - tabStatus.Controls.Add(dgvRuns); - tabStatus.Controls.Add(toolStripStatus); - tabStatus.Location = new Point(4, 34); - tabStatus.Margin = new Padding(4, 5, 4, 5); - tabStatus.Name = "tabStatus"; - tabStatus.Padding = new Padding(4, 5, 4, 5); - tabStatus.Size = new Size(1563, 992); - tabStatus.TabIndex = 2; - tabStatus.Text = "Abruf / Status"; - tabStatus.UseVisualStyleBackColor = true; - // - // dgvRuns - // - dgvRuns.AllowUserToAddRows = false; - dgvRuns.AllowUserToDeleteRows = false; - dgvRuns.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvRuns.Dock = DockStyle.Fill; - dgvRuns.Location = new Point(4, 39); - dgvRuns.Margin = new Padding(4, 5, 4, 5); - dgvRuns.Name = "dgvRuns"; - dgvRuns.ReadOnly = true; - dgvRuns.RowHeadersVisible = false; - dgvRuns.RowHeadersWidth = 62; - dgvRuns.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvRuns.Size = new Size(1555, 948); - dgvRuns.TabIndex = 1; - // - // toolStripStatus - // - toolStripStatus.ImageScalingSize = new Size(24, 24); - toolStripStatus.Items.AddRange(new ToolStripItem[] { lblStatusKonto, cbStatusAccount, sepStatus, btnIncremental, btnBackfill, sepStatus2, btnStatusRefresh }); - toolStripStatus.Location = new Point(4, 5); - toolStripStatus.Name = "toolStripStatus"; - toolStripStatus.Padding = new Padding(0, 0, 3, 0); - toolStripStatus.Size = new Size(1555, 34); - toolStripStatus.TabIndex = 0; - // - // lblStatusKonto - // - lblStatusKonto.Name = "lblStatusKonto"; - lblStatusKonto.Size = new Size(64, 29); - lblStatusKonto.Text = "Konto:"; - // - // cbStatusAccount - // - cbStatusAccount.DropDownStyle = ComboBoxStyle.DropDownList; - cbStatusAccount.Name = "cbStatusAccount"; - cbStatusAccount.Size = new Size(341, 34); - // - // sepStatus - // - sepStatus.Name = "sepStatus"; - sepStatus.Size = new Size(6, 34); - // - // btnIncremental - // - btnIncremental.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnIncremental.Name = "btnIncremental"; - btnIncremental.Size = new Size(134, 29); - btnIncremental.Text = "Inkrement jetzt"; - btnIncremental.ToolTipText = "Nur neue Ereignisse seit dem letzten Stand abrufen (mit Lookback-Überlappung)."; - // - // btnBackfill - // - btnBackfill.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnBackfill.Name = "btnBackfill"; - btnBackfill.Size = new Size(188, 29); - btnBackfill.Text = "Backfill (volle Historie)"; - btnBackfill.ToolTipText = "Komplette Historie neu abrufen (idempotent – bucht nichts doppelt)."; - // - // sepStatus2 - // - sepStatus2.Name = "sepStatus2"; - sepStatus2.Size = new Size(6, 34); - // - // btnStatusRefresh - // - btnStatusRefresh.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnStatusRefresh.Name = "btnStatusRefresh"; - btnStatusRefresh.Size = new Size(116, 29); - btnStatusRefresh.Text = "Aktualisieren"; - // - // lblAccStatus - // - lblAccStatus.Dock = DockStyle.Bottom; - lblAccStatus.Location = new Point(0, 1030); - lblAccStatus.Margin = new Padding(4, 0, 4, 0); - lblAccStatus.Name = "lblAccStatus"; - lblAccStatus.Padding = new Padding(9, 3, 9, 3); - lblAccStatus.Size = new Size(1571, 37); - lblAccStatus.TabIndex = 1; - // - // AccountingMainForm - // - AutoScaleDimensions = new SizeF(10F, 25F); - AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1571, 1067); - Controls.Add(tabControlAcc); - Controls.Add(lblAccStatus); - Icon = (Icon)resources.GetObject("$this.Icon"); - Margin = new Padding(4, 5, 4, 5); - Name = "AccountingMainForm"; - StartPosition = FormStartPosition.CenterScreen; - Text = "Accounting"; - tabControlAcc.ResumeLayout(false); - tabUebersicht.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)dgvMonthly).EndInit(); - flpKpis.ResumeLayout(false); - pnlOverviewTop.ResumeLayout(false); - pnlOverviewTop.PerformLayout(); - tabLedger.ResumeLayout(false); - tabLedger.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)dgvLedger).EndInit(); - toolStripLedger.ResumeLayout(false); - toolStripLedger.PerformLayout(); - tabStatus.ResumeLayout(false); - tabStatus.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)dgvRuns).EndInit(); - toolStripStatus.ResumeLayout(false); - toolStripStatus.PerformLayout(); - ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.TabControl tabControlAcc; - private System.Windows.Forms.TabPage tabUebersicht; - private System.Windows.Forms.Panel pnlOverviewTop; - private System.Windows.Forms.Label lblOvKonto; - private System.Windows.Forms.ComboBox cbOvAccount; - private System.Windows.Forms.Label lblVon; - private System.Windows.Forms.DateTimePicker dtFrom; - private System.Windows.Forms.Label lblBis; - private System.Windows.Forms.DateTimePicker dtTo; - private System.Windows.Forms.Label lblWaehrung; - private System.Windows.Forms.ComboBox cbCurrency; - private System.Windows.Forms.Button btnCalc; - private System.Windows.Forms.Button btnExportCsv; - private System.Windows.Forms.Button btnExportPdf; - private System.Windows.Forms.FlowLayoutPanel flpKpis; - private System.Windows.Forms.Label lblKpiNet; - private System.Windows.Forms.Label lblKpiClosing; - private System.Windows.Forms.Label lblKpiDeposits; - private System.Windows.Forms.Label lblKpiWithdrawals; - private System.Windows.Forms.Label lblKpiFees; - private System.Windows.Forms.Label lblKpiRewards; - private System.Windows.Forms.Label lblKpiVolume; - private System.Windows.Forms.Label lblKpiTrades; - private System.Windows.Forms.DataGridView dgvMonthly; - private System.Windows.Forms.TabPage tabLedger; - private System.Windows.Forms.ToolStrip toolStripLedger; - private System.Windows.Forms.ToolStripLabel lblLedgerKonto; - private System.Windows.Forms.ToolStripComboBox cbLedgerAccount; - private System.Windows.Forms.ToolStripSeparator sepLedger; - private System.Windows.Forms.ToolStripButton btnLedgerRefresh; - private System.Windows.Forms.DataGridView dgvLedger; - private System.Windows.Forms.TabPage tabStatus; - private System.Windows.Forms.ToolStrip toolStripStatus; - private System.Windows.Forms.ToolStripLabel lblStatusKonto; - private System.Windows.Forms.ToolStripComboBox cbStatusAccount; - private System.Windows.Forms.ToolStripSeparator sepStatus; - private System.Windows.Forms.ToolStripButton btnIncremental; - private System.Windows.Forms.ToolStripButton btnBackfill; - private System.Windows.Forms.ToolStripSeparator sepStatus2; - private System.Windows.Forms.ToolStripButton btnStatusRefresh; - private System.Windows.Forms.DataGridView dgvRuns; - private System.Windows.Forms.Label lblAccStatus; - } -} diff --git a/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.cs b/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.cs deleted file mode 100644 index be2b479..0000000 --- a/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.cs +++ /dev/null @@ -1,322 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Windows.Forms; -using Microsoft.Extensions.DependencyInjection; -using PolyTrader.Modules.Accounting.Logic; -using PolyTrader.Modules.Accounting.Persistence; -using PolyTrader.Modules.Accounting.Services; -using PolyTraderSharp; - -namespace PolyTrader.Modules.Accounting.Ui -{ - /// - /// Hauptfenster des Accounting-Moduls: Tab „Übersicht / BWA" (neutrale Periodenabrechnung + KPIs + - /// Monatsvergleich, Währung USDC/USD/EUR, CSV-Export), „Ledger" (Buchungssätze) und „Abruf / Status" - /// (Ingest-Läufe, manueller Backfill/Inkrement). Layout im Designer; Aggregation pur im - /// . Die US-Steuerschicht (A-3) ist bewusst NICHT hier – sie hängt an - /// den CPA-Antworten. - /// - public partial class AccountingMainForm : Form - { - private ILedgerRepository? _ledger; - private IIngestRunRepository? _runs; - private AccountingIngestService? _ingest; - private AccountingReportService? _report; - private TradingState? _state; - - public AccountingMainForm() - { - InitializeComponent(); - - // Übersicht / BWA - btnCalc.Click += (_, _) => Recalculate(); - btnExportCsv.Click += (_, _) => ExportCsv(); - btnExportPdf.Click += (_, _) => ExportPdf(); - cbOvAccount.SelectedIndexChanged += (_, _) => Recalculate(); - cbCurrency.SelectedIndexChanged += (_, _) => Recalculate(); - - // Ledger + Status - btnLedgerRefresh.Click += (_, _) => LoadLedger(); - cbLedgerAccount.SelectedIndexChanged += (_, _) => LoadLedger(); - btnStatusRefresh.Click += (_, _) => LoadRuns(); - btnIncremental.Click += async (_, _) => await RunIngestAsync(backfill: false); - btnBackfill.Click += async (_, _) => await RunIngestAsync(backfill: true); - } - - public void Initialize(IServiceProvider services) - { - _ledger = services.GetRequiredService(); - _runs = services.GetRequiredService(); - _ingest = services.GetRequiredService(); - _report = services.GetRequiredService(); - _state = services.GetRequiredService(); - - // Standard-Zeitraum: laufender Monat. - var now = DateTime.Now; - dtFrom.Value = new DateTime(now.Year, now.Month, 1); - dtTo.Value = now; - if (cbCurrency.Items.Count > 0) cbCurrency.SelectedIndex = 0; // USDC - - PopulateAccounts(); - Recalculate(); - LoadLedger(); - LoadRuns(); - } - - // ---------------- Konten-Filter ---------------- - - private void PopulateAccounts() - { - var items = new List { new(null, "Alle Live-Konten") }; - if (_state != null) - items.AddRange(_state.Accounts.Values - .Where(a => !a.IsDemo && !string.IsNullOrWhiteSpace(a.WalletAddress)) - .OrderBy(a => a.AccountId) - .Select(a => new AccountItem(a.AccountId, string.IsNullOrEmpty(a.Name) ? $"#{a.AccountId}" : $"{a.Name} (#{a.AccountId})"))); - - cbOvAccount.DisplayMember = nameof(AccountItem.Label); - cbOvAccount.DataSource = new List(items); - foreach (var combo in new[] { cbLedgerAccount, cbStatusAccount }) - { - combo.ComboBox.DisplayMember = nameof(AccountItem.Label); - combo.ComboBox.DataSource = new List(items); - } - } - - private static int? IdOf(object? item) => item is AccountItem it ? it.Id : null; - - // ---------------- Übersicht / BWA ---------------- - - private void Recalculate() - { - if (_report == null) return; - try - { - DateTime from = dtFrom.Value.Date; - DateTime to = dtTo.Value.Date.AddDays(1).AddTicks(-1); // inklusive gewählter Bis-Tag - int? accId = IdOf(cbOvAccount.SelectedItem); - - var statement = _report.BuildStatement(accId, from, to); - var monthly = _report.BuildMonthly(accId, from, to); - var cur = _report.ResolveCurrency(cbCurrency.SelectedItem?.ToString() ?? "USDC", to); - - UpdateKpis(statement, cur); - dgvMonthly.DataSource = monthly.Select(m => new MonthlyRow(m, cur)).ToList(); - - lblAccStatus.Text = cur.Available - ? $"Währung {cur.Code}: {cur.Note}" - : $"⚠️ {cur.Note} (Anzeige in USDC)."; - } - catch (Exception ex) - { - lblAccStatus.Text = $"Abrechnung nicht möglich (acc_-Migration angewendet?): {ex.Message}"; - } - } - - private void UpdateKpis(PeriodStatement s, CurrencyContext cur) - { - CurrencyContext view = cur.Available ? cur : new CurrencyContext("USDC", 1m, true, ""); - string unit = view.Code; - decimal V(decimal usdc) => AccountingReportService.Convert(usdc, view); - - lblKpiNet.Text = $"Netto-Handelsergebnis\n{V(s.NetTradingResultUsdc):N2} {unit}"; - lblKpiNet.ForeColor = s.NetTradingResultUsdc >= 0 ? System.Drawing.Color.ForestGreen : System.Drawing.Color.Firebrick; - lblKpiClosing.Text = $"Endsaldo\n{V(s.ClosingBalanceUsdc):N2} {unit}"; - lblKpiDeposits.Text = $"Einzahlungen\n{V(s.Deposits):N2} {unit}"; - lblKpiWithdrawals.Text = $"Auszahlungen\n{V(s.Withdrawals):N2} {unit}"; - lblKpiFees.Text = $"Fees\n{V(s.Fees):N2} {unit}"; - lblKpiRewards.Text = $"Rewards\n{V(s.Rewards):N2} {unit}"; - lblKpiVolume.Text = $"Handelsvolumen\n{V(s.TradeVolume):N2} {unit}"; - lblKpiTrades.Text = $"Trades\n{s.TradeCount}"; - } - - private void ExportCsv() - { - if (_ledger == null || _report == null) return; - DateTime from = dtFrom.Value.Date; - DateTime to = dtTo.Value.Date.AddDays(1).AddTicks(-1); - int? accId = IdOf(cbOvAccount.SelectedItem); - - using var dlg = new SaveFileDialog - { - Filter = "CSV-Datei (*.csv)|*.csv", - FileName = $"accounting_{(accId?.ToString() ?? "alle")}_{from:yyyyMMdd}-{dtTo.Value:yyyyMMdd}.csv" - }; - if (dlg.ShowDialog(this) != DialogResult.OK) return; - - try - { - var statement = _report.BuildStatement(accId, from, to); - var entries = _ledger.Query(accId, from, to, 100000); - string csv = CsvExporter.Statement(statement) + Environment.NewLine + CsvExporter.Ledger(entries); - System.IO.File.WriteAllText(dlg.FileName, csv, new System.Text.UTF8Encoding(true)); - lblAccStatus.Text = $"CSV exportiert: {dlg.FileName} ({entries.Count} Buchungen)."; - } - catch (Exception ex) - { - lblAccStatus.Text = $"CSV-Export fehlgeschlagen: {ex.Message}"; - } - } - - private void ExportPdf() - { - if (_ledger == null || _report == null) return; - DateTime from = dtFrom.Value.Date; - DateTime to = dtTo.Value.Date.AddDays(1).AddTicks(-1); - int? accId = IdOf(cbOvAccount.SelectedItem); - - using var dlg = new SaveFileDialog - { - Filter = "PDF-Datei (*.pdf)|*.pdf", - FileName = $"abrechnung_{(accId?.ToString() ?? "alle")}_{from:yyyyMMdd}-{dtTo.Value:yyyyMMdd}.pdf" - }; - if (dlg.ShowDialog(this) != DialogResult.OK) return; - - try - { - var statement = _report.BuildStatement(accId, from, to); - var monthly = _report.BuildMonthly(accId, from, to); - var entries = _ledger.Query(accId, from, to, 100000); - var cur = _report.ResolveCurrency(cbCurrency.SelectedItem?.ToString() ?? "USDC", to); - CurrencyContext view = cur.Available ? cur : new CurrencyContext("USDC", 1m, true, "Native Buchungswährung."); - - byte[] pdf = PdfExporter.Render(statement, monthly, entries, view.Code, view.Factor, view.Note); - System.IO.File.WriteAllBytes(dlg.FileName, pdf); - lblAccStatus.Text = $"PDF exportiert: {dlg.FileName} ({entries.Count} Buchungen, {view.Code})."; - } - catch (Exception ex) - { - lblAccStatus.Text = $"PDF-Export fehlgeschlagen: {ex.Message}"; - } - } - - // ---------------- Ledger ---------------- - - private void LoadLedger() - { - if (_ledger == null) return; - try - { - var rows = _ledger.Query(IdOf(cbLedgerAccount.SelectedItem), null, null, 1000); - dgvLedger.DataSource = rows.Select(e => new LedgerRow(e)).ToList(); - lblAccStatus.Text = rows.Count == 0 - ? "Noch keine Buchungen. (Ingest-Quellen sind offline bis zur Live-Anbindung im Zielland.)" - : $"{rows.Count} Buchungssätze angezeigt."; - } - catch (Exception ex) - { - lblAccStatus.Text = $"Ledger nicht lesbar (acc_-Migration angewendet?): {ex.Message}"; - } - } - - // ---------------- Abruf / Status ---------------- - - private void LoadRuns() - { - if (_runs == null) return; - try - { - dgvRuns.DataSource = _runs.GetRecent(IdOf(cbStatusAccount.SelectedItem), 100); - } - catch (Exception ex) - { - lblAccStatus.Text = $"Ingest-Läufe nicht lesbar: {ex.Message}"; - } - } - - private async System.Threading.Tasks.Task RunIngestAsync(bool backfill) - { - if (_ingest == null) return; - btnBackfill.Enabled = false; - btnIncremental.Enabled = false; - lblAccStatus.Text = backfill ? "Backfill läuft …" : "Inkrementeller Abruf läuft …"; - try - { - await System.Threading.Tasks.Task.Run(() => _ingest.IngestAllAsync(backfill, CancellationToken.None)); - lblAccStatus.Text = "Abruf abgeschlossen."; - LoadRuns(); - LoadLedger(); - Recalculate(); - } - catch (Exception ex) - { - lblAccStatus.Text = $"Abruf-Fehler: {ex.Message}"; - } - finally - { - btnBackfill.Enabled = true; - btnIncremental.Enabled = true; - } - } - - private sealed record AccountItem(int? Id, string Label); - - /// Anzeige-Zeile des Monatsvergleichs (Beträge in der gewählten Währung). - private sealed class MonthlyRow - { - public MonthlyRow(PeriodStatement m, CurrencyContext cur) - { - CurrencyContext view = cur.Available ? cur : new CurrencyContext("USDC", 1m, true, ""); - decimal V(decimal usdc) => AccountingReportService.Convert(usdc, view); - Monat = m.From.ToString("yyyy-MM"); - Anfangssaldo = V(m.OpeningBalanceUsdc); - Einzahlungen = V(m.Deposits); - Auszahlungen = V(m.Withdrawals); - Handelsvolumen = V(m.TradeVolume); - Rewards = V(m.Rewards); - Fees = V(m.Fees); - Handelsergebnis = V(m.NetTradingResultUsdc); - Endsaldo = V(m.ClosingBalanceUsdc); - Trades = m.TradeCount; - } - - public string Monat { get; } - public decimal Anfangssaldo { get; } - public decimal Einzahlungen { get; } - public decimal Auszahlungen { get; } - public decimal Handelsvolumen { get; } - public decimal Rewards { get; } - public decimal Fees { get; } - public decimal Handelsergebnis { get; } - public decimal Endsaldo { get; } - public int Trades { get; } - } - - /// Anzeige-Zeile fürs Ledger-Grid. - private sealed class LedgerRow - { - public LedgerRow(Models.LedgerEntry e) - { - Zeit = e.Timestamp; - Konto = e.AccountId; - Typ = e.EventType.ToString(); - Markt = e.MarketSlug; - Outcome = e.Outcome; - Side = e.Side; - Size = e.Size; - Preis = e.PriceUsdc; - Brutto = e.GrossUsdc; - Fee = e.FeeUsdc; - Netto = e.NetUsdc; - TxHash = e.TxHash; - Quelle = e.Source; - } - - public DateTime Zeit { get; } - public int Konto { get; } - public string Typ { get; } - public string Markt { get; } - public string Outcome { get; } - public string Side { get; } - public decimal Size { get; } - public decimal Preis { get; } - public decimal Brutto { get; } - public decimal Fee { get; } - public decimal Netto { get; } - public string TxHash { get; } - public string Quelle { get; } - } - } -} diff --git a/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.resx b/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.resx deleted file mode 100644 index 8039ae0..0000000 --- a/src/PolyTrader.Modules.Accounting/Ui/AccountingMainForm.resx +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - - 206, 17 - - - - - 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 - AABJRU5ErkJggg== - - - \ No newline at end of file diff --git a/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs b/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs index 907e77e..90339e4 100644 --- a/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs +++ b/src/PolyTrader.Modules.CopyTrading/CopyTradingModule.cs @@ -10,7 +10,6 @@ using PolyTrader.Core.Modularity; using PolyTrader.Core.Streaming; using PolyTrader.Modules.CopyTrading.Persistence; using PolyTrader.Modules.CopyTrading.Persistence.Ef; -using PolyTrader.Modules.CopyTrading.Ui; using PolyTraderSharp; using PolyTraderSharp.Models; using PolyTraderSharp.Services; @@ -81,24 +80,22 @@ namespace PolyTrader.Modules.CopyTrading services.AddHostedService(sp => sp.GetRequiredService()); } + /// + /// Aktuell ohne Ansicht: Die WinForms-UI wurde mit der Linux-Portierung entfernt, die + /// Avalonia-Ansicht folgt (Stufe L3/L4). Die Fachlogik dieses Moduls laeuft davon + /// unabhaengig weiter – die Shell zeigt schlicht kein Fenster fuer das Modul an. + /// + /// Beim Nachbau zu erhalten (Spezifikation: docs/UI-SPEZIFIKATION-WinForms.md, + /// Originalcode: Git-Tag winforms-final): + /// + /// View-ID copytrading.main (stabil – Launcher-Button und Symbol haengen daran) + /// Titel Copytrading, Gruppe CopyTrading, Order 100 + /// Ein Fenster fuers ganze Modul: CopyTradingMainForm mit Tabs: Master-Trader / Offene Trades / Geschlossene Trades / Account-Einstellungen + /// + /// public void RegisterUi(IModuleUiHost host, IServiceProvider services) { - // EIN Fenster fürs ganze Modul: die einzelnen Ansichten sind Tabs im - // CopyTradingMainForm (Master-Trader / geschlossene Trades / Account-Einstellungen). - // So bleibt der Launcher schlank – ein Button je Modul statt je View. - host.RegisterView(new ModuleView - { - Id = "copytrading.main", - Title = "Copytrading", - Group = "CopyTrading", - Order = 100, - CreateView = () => - { - var form = new CopyTradingMainForm(); - form.Initialize(services); - return form; - } - }); + // Bewusst leer, bis die Avalonia-Ansicht steht (siehe Doku oben). } public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; diff --git a/src/PolyTrader.Modules.CopyTrading/PolyTrader.Modules.CopyTrading.csproj b/src/PolyTrader.Modules.CopyTrading/PolyTrader.Modules.CopyTrading.csproj index 78298e6..ed8bb23 100644 --- a/src/PolyTrader.Modules.CopyTrading/PolyTrader.Modules.CopyTrading.csproj +++ b/src/PolyTrader.Modules.CopyTrading/PolyTrader.Modules.CopyTrading.csproj @@ -1,4 +1,4 @@ - + @@ -20,11 +20,12 @@ - net8.0-windows + + net8.0 enable enable - - true diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.Designer.cs b/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.Designer.cs deleted file mode 100644 index 8ab0981..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.Designer.cs +++ /dev/null @@ -1,126 +0,0 @@ -namespace PolyTrader.Modules.CopyTrading.Ui -{ - partial class AccountSettingsView - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - private void InitializeComponent() - { - this.toolbar = new System.Windows.Forms.ToolStrip(); - this.tsAccountLabel = new System.Windows.Forms.ToolStripLabel(); - this.tsAccounts = new System.Windows.Forms.ToolStripComboBox(); - this.tsSep = new System.Windows.Forms.ToolStripSeparator(); - this.tsSave = new System.Windows.Forms.ToolStripButton(); - this.pgSettings = new System.Windows.Forms.PropertyGrid(); - this.statusPanel = new System.Windows.Forms.Panel(); - this.lblHint = new System.Windows.Forms.Label(); - this.toolbar.SuspendLayout(); - this.statusPanel.SuspendLayout(); - this.SuspendLayout(); - // - // toolbar - // - this.toolbar.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - this.toolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.tsAccountLabel, - this.tsAccounts, - this.tsSep, - this.tsSave}); - this.toolbar.Location = new System.Drawing.Point(0, 0); - this.toolbar.Name = "toolbar"; - this.toolbar.Size = new System.Drawing.Size(560, 25); - this.toolbar.TabIndex = 0; - // - // tsAccountLabel - // - this.tsAccountLabel.Name = "tsAccountLabel"; - this.tsAccountLabel.Size = new System.Drawing.Size(56, 22); - this.tsAccountLabel.Text = "Account:"; - // - // tsAccounts - // - this.tsAccounts.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.tsAccounts.Name = "tsAccounts"; - this.tsAccounts.Size = new System.Drawing.Size(320, 25); - // - // tsSep - // - this.tsSep.Name = "tsSep"; - this.tsSep.Size = new System.Drawing.Size(6, 25); - // - // tsSave - // - this.tsSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.tsSave.Name = "tsSave"; - this.tsSave.Size = new System.Drawing.Size(69, 22); - this.tsSave.Text = "Speichern"; - // - // pgSettings - // - this.pgSettings.Dock = System.Windows.Forms.DockStyle.Fill; - this.pgSettings.Location = new System.Drawing.Point(0, 25); - this.pgSettings.Name = "pgSettings"; - this.pgSettings.PropertySort = System.Windows.Forms.PropertySort.Categorized; - this.pgSettings.Size = new System.Drawing.Size(560, 549); - this.pgSettings.TabIndex = 1; - this.pgSettings.ToolbarVisible = false; - // - // statusPanel - // - this.statusPanel.Controls.Add(this.lblHint); - this.statusPanel.Dock = System.Windows.Forms.DockStyle.Bottom; - this.statusPanel.Location = new System.Drawing.Point(0, 574); - this.statusPanel.Name = "statusPanel"; - this.statusPanel.Size = new System.Drawing.Size(560, 26); - this.statusPanel.TabIndex = 2; - // - // lblHint - // - this.lblHint.Dock = System.Windows.Forms.DockStyle.Fill; - this.lblHint.ForeColor = System.Drawing.Color.DimGray; - this.lblHint.Location = new System.Drawing.Point(0, 0); - this.lblHint.Name = "lblHint"; - this.lblHint.Padding = new System.Windows.Forms.Padding(8, 0, 0, 0); - this.lblHint.Size = new System.Drawing.Size(560, 26); - this.lblHint.TabIndex = 0; - this.lblHint.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // AccountSettingsView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.pgSettings); - this.Controls.Add(this.statusPanel); - this.Controls.Add(this.toolbar); - this.Name = "AccountSettingsView"; - this.Size = new System.Drawing.Size(560, 600); - this.toolbar.ResumeLayout(false); - this.toolbar.PerformLayout(); - this.statusPanel.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.ToolStrip toolbar; - private System.Windows.Forms.ToolStripLabel tsAccountLabel; - private System.Windows.Forms.ToolStripComboBox tsAccounts; - private System.Windows.Forms.ToolStripSeparator tsSep; - private System.Windows.Forms.ToolStripButton tsSave; - private System.Windows.Forms.PropertyGrid pgSettings; - private System.Windows.Forms.Panel statusPanel; - private System.Windows.Forms.Label lblHint; - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.cs b/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.cs deleted file mode 100644 index c99b5ac..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Linq; -using System.Windows.Forms; -using PolyTrader.Modules.CopyTrading.Persistence; -using PolyTraderSharp; -using PolyTraderSharp.Models; - -namespace PolyTrader.Modules.CopyTrading.Ui -{ - /// - /// Bearbeitet die copytrading-spezifischen Detail-Einstellungen je Account - /// (Investment-/Zeit-Limits, ). Persistiert über - /// das Repo und aktualisiert den Hot-Path-State (). - /// Layout im Designer (AccountSettingsView.Designer.cs), Daten/Logik hier. - /// - public partial class AccountSettingsView : UserControl - { - private ICopyTradingAccountSettingsRepository? _repo; - private TradingState? _state; - private CopyTradingState? _copyState; - - private CopyTradingAccountSettings? _current; - - // Parameterloser Konstruktor für den WinForms-Designer. - public AccountSettingsView() - { - InitializeComponent(); - - tsAccounts.SelectedIndexChanged += (_, _) => LoadSelected(); - tsSave.Click += (_, _) => Save(); - } - - /// Injiziert die Abhängigkeiten (nach der DI-Auflösung) und füllt die Auswahl. - public void Initialize(ICopyTradingAccountSettingsRepository repo, TradingState state, CopyTradingState copyState) - { - _repo = repo; - _state = state; - _copyState = copyState; - PopulateAccounts(); - } - - private void PopulateAccounts() - { - if (_state == null) return; - - var items = _state.Accounts.Values - .OrderBy(a => a.AccountId) - .Select(a => new AccountItem(a.AccountId, string.IsNullOrEmpty(a.Name) ? $"#{a.AccountId}" : $"{a.Name} (#{a.AccountId}){(a.IsDemo ? " · Demo" : "")}")) - .ToList(); - - tsAccounts.ComboBox.DisplayMember = nameof(AccountItem.Label); - tsAccounts.ComboBox.ValueMember = nameof(AccountItem.Id); - tsAccounts.ComboBox.DataSource = items; - - if (items.Count > 0) LoadSelected(); - else lblHint.Text = "Keine Accounts vorhanden."; - } - - private void LoadSelected() - { - if (_repo == null || tsAccounts.SelectedItem is not AccountItem item) return; - _current = _repo.Get(item.Id) ?? new CopyTradingAccountSettings { AccountId = item.Id }; - pgSettings.SelectedObject = _current; - lblHint.Text = $"Einstellungen für Account #{item.Id}."; - } - - private void Save() - { - if (_current == null || _repo == null || _copyState == null) return; - _repo.Upsert(_current); - _copyState.AccountSettings[_current.AccountId] = _current; - lblHint.Text = $"Gespeichert für Account #{_current.AccountId} um {DateTime.Now:HH:mm:ss}."; - } - - private sealed record AccountItem(int Id, string Label); - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.resx b/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.resx deleted file mode 100644 index 8b2ff64..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/AccountSettingsView.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/ClosedTradesView.Designer.cs b/src/PolyTrader.Modules.CopyTrading/Ui/ClosedTradesView.Designer.cs deleted file mode 100644 index d3c3494..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/ClosedTradesView.Designer.cs +++ /dev/null @@ -1,392 +0,0 @@ -namespace PolyTrader.Modules.CopyTrading.Ui -{ - partial class ClosedTradesView - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - private void InitializeComponent() - { - this.toolbar = new System.Windows.Forms.ToolStrip(); - this.tsRefresh = new System.Windows.Forms.ToolStripButton(); - this.dgvTrades = new System.Windows.Forms.DataGridView(); - this.colTradeId = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colAccount = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colTrader = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colMarket = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colOutcome = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colSide = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colEntry = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colExit = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colSize = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colPnl = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colPnlPct = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colOpenedAt = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colClosedAt = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.statusPanel = new System.Windows.Forms.Panel(); - this.lblSummary = new System.Windows.Forms.Label(); - this.pnlFilters = new System.Windows.Forms.Panel(); - this.lblMarkt = new System.Windows.Forms.Label(); - this.tbMarket = new System.Windows.Forms.TextBox(); - this.lblMaster = new System.Windows.Forms.Label(); - this.cbMaster = new System.Windows.Forms.ComboBox(); - this.lblErgebnis = new System.Windows.Forms.Label(); - this.cbResult = new System.Windows.Forms.ComboBox(); - this.lblVon = new System.Windows.Forms.Label(); - this.dtFrom = new System.Windows.Forms.DateTimePicker(); - this.lblBis = new System.Windows.Forms.Label(); - this.dtTo = new System.Windows.Forms.DateTimePicker(); - this.btnReset = new System.Windows.Forms.Button(); - this.toolbar.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.dgvTrades)).BeginInit(); - this.statusPanel.SuspendLayout(); - this.pnlFilters.SuspendLayout(); - this.SuspendLayout(); - // - // toolbar - // - this.toolbar.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - this.toolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.tsRefresh}); - this.toolbar.Location = new System.Drawing.Point(0, 0); - this.toolbar.Name = "toolbar"; - this.toolbar.Size = new System.Drawing.Size(1100, 25); - this.toolbar.TabIndex = 0; - // - // tsRefresh - // - this.tsRefresh.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.tsRefresh.Name = "tsRefresh"; - this.tsRefresh.Size = new System.Drawing.Size(90, 22); - this.tsRefresh.Text = "Aktualisieren"; - // - // dgvTrades - // - this.dgvTrades.AllowUserToAddRows = false; - this.dgvTrades.AllowUserToDeleteRows = false; - this.dgvTrades.AutoGenerateColumns = false; - this.dgvTrades.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.dgvTrades.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.colTradeId, - this.colAccount, - this.colTrader, - this.colMarket, - this.colOutcome, - this.colSide, - this.colEntry, - this.colExit, - this.colSize, - this.colPnl, - this.colPnlPct, - this.colOpenedAt, - this.colClosedAt}); - this.dgvTrades.Dock = System.Windows.Forms.DockStyle.Fill; - this.dgvTrades.Location = new System.Drawing.Point(0, 25); - this.dgvTrades.Name = "dgvTrades"; - this.dgvTrades.ReadOnly = true; - this.dgvTrades.RowHeadersVisible = false; - this.dgvTrades.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; - this.dgvTrades.Size = new System.Drawing.Size(1100, 549); - this.dgvTrades.TabIndex = 1; - // - // colTradeId - // - this.colTradeId.DataPropertyName = "TradeId"; - this.colTradeId.HeaderText = "#"; - this.colTradeId.Name = "colTradeId"; - this.colTradeId.ReadOnly = true; - this.colTradeId.Width = 60; - // - // colAccount - // - this.colAccount.DataPropertyName = "AccountName"; - this.colAccount.HeaderText = "Account"; - this.colAccount.Name = "colAccount"; - this.colAccount.ReadOnly = true; - this.colAccount.Width = 130; - // - // colTrader - // - this.colTrader.DataPropertyName = "SourceTraderName"; - this.colTrader.HeaderText = "Master-Trader"; - this.colTrader.Name = "colTrader"; - this.colTrader.ReadOnly = true; - this.colTrader.Width = 130; - // - // colMarket - // - this.colMarket.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; - this.colMarket.DataPropertyName = "MarketQuestion"; - this.colMarket.HeaderText = "Markt"; - this.colMarket.Name = "colMarket"; - this.colMarket.ReadOnly = true; - // - // colOutcome - // - this.colOutcome.DataPropertyName = "Outcome"; - this.colOutcome.HeaderText = "Outcome"; - this.colOutcome.Name = "colOutcome"; - this.colOutcome.ReadOnly = true; - this.colOutcome.Width = 80; - // - // colSide - // - this.colSide.DataPropertyName = "Side"; - this.colSide.HeaderText = "Side"; - this.colSide.Name = "colSide"; - this.colSide.ReadOnly = true; - this.colSide.Width = 60; - // - // colEntry - // - this.colEntry.DataPropertyName = "EntryPrice"; - this.colEntry.HeaderText = "Entry"; - this.colEntry.Name = "colEntry"; - this.colEntry.ReadOnly = true; - this.colEntry.Width = 70; - // - // colExit - // - this.colExit.DataPropertyName = "ExitPrice"; - this.colExit.HeaderText = "Exit"; - this.colExit.Name = "colExit"; - this.colExit.ReadOnly = true; - this.colExit.Width = 70; - // - // colSize - // - this.colSize.DataPropertyName = "Size"; - this.colSize.HeaderText = "Size"; - this.colSize.Name = "colSize"; - this.colSize.ReadOnly = true; - this.colSize.Width = 70; - // - // colPnl - // - this.colPnl.DataPropertyName = "RealizedPnl"; - this.colPnl.HeaderText = "PnL"; - this.colPnl.Name = "colPnl"; - this.colPnl.ReadOnly = true; - this.colPnl.Width = 80; - // - // colPnlPct - // - this.colPnlPct.DataPropertyName = "PnlPercent"; - this.colPnlPct.HeaderText = "PnL %"; - this.colPnlPct.Name = "colPnlPct"; - this.colPnlPct.ReadOnly = true; - this.colPnlPct.Width = 70; - // - // colOpenedAt - // - this.colOpenedAt.DataPropertyName = "OpenedAt"; - this.colOpenedAt.HeaderText = "Eröffnet"; - this.colOpenedAt.Name = "colOpenedAt"; - this.colOpenedAt.ReadOnly = true; - this.colOpenedAt.Width = 130; - // - // colClosedAt - // - this.colClosedAt.DataPropertyName = "ClosedAt"; - this.colClosedAt.HeaderText = "Geschlossen"; - this.colClosedAt.Name = "colClosedAt"; - this.colClosedAt.ReadOnly = true; - this.colClosedAt.Width = 130; - // - // statusPanel - // - this.statusPanel.Controls.Add(this.lblSummary); - this.statusPanel.Dock = System.Windows.Forms.DockStyle.Bottom; - this.statusPanel.Location = new System.Drawing.Point(0, 574); - this.statusPanel.Name = "statusPanel"; - this.statusPanel.Size = new System.Drawing.Size(1100, 26); - this.statusPanel.TabIndex = 2; - // - // lblSummary - // - this.lblSummary.Dock = System.Windows.Forms.DockStyle.Fill; - this.lblSummary.Location = new System.Drawing.Point(0, 0); - this.lblSummary.Name = "lblSummary"; - this.lblSummary.Padding = new System.Windows.Forms.Padding(8, 0, 0, 0); - this.lblSummary.Size = new System.Drawing.Size(1100, 26); - this.lblSummary.TabIndex = 0; - this.lblSummary.Text = "—"; - this.lblSummary.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // pnlFilters - // - this.pnlFilters.Controls.Add(this.lblMarkt); - this.pnlFilters.Controls.Add(this.tbMarket); - this.pnlFilters.Controls.Add(this.lblMaster); - this.pnlFilters.Controls.Add(this.cbMaster); - this.pnlFilters.Controls.Add(this.lblErgebnis); - this.pnlFilters.Controls.Add(this.cbResult); - this.pnlFilters.Controls.Add(this.lblVon); - this.pnlFilters.Controls.Add(this.dtFrom); - this.pnlFilters.Controls.Add(this.lblBis); - this.pnlFilters.Controls.Add(this.dtTo); - this.pnlFilters.Controls.Add(this.btnReset); - this.pnlFilters.Dock = System.Windows.Forms.DockStyle.Top; - this.pnlFilters.Location = new System.Drawing.Point(0, 25); - this.pnlFilters.Name = "pnlFilters"; - this.pnlFilters.Size = new System.Drawing.Size(1100, 34); - this.pnlFilters.TabIndex = 3; - // - // lblMarkt - // - this.lblMarkt.AutoSize = true; - this.lblMarkt.Location = new System.Drawing.Point(6, 9); - this.lblMarkt.Name = "lblMarkt"; - this.lblMarkt.Size = new System.Drawing.Size(41, 15); - this.lblMarkt.Text = "Markt:"; - // - // tbMarket - // - this.tbMarket.Location = new System.Drawing.Point(51, 6); - this.tbMarket.Name = "tbMarket"; - this.tbMarket.PlaceholderText = "Suchtext …"; - this.tbMarket.Size = new System.Drawing.Size(200, 23); - this.tbMarket.TabIndex = 0; - // - // lblMaster - // - this.lblMaster.AutoSize = true; - this.lblMaster.Location = new System.Drawing.Point(263, 9); - this.lblMaster.Name = "lblMaster"; - this.lblMaster.Size = new System.Drawing.Size(48, 15); - this.lblMaster.Text = "Master:"; - // - // cbMaster - // - this.cbMaster.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.cbMaster.Location = new System.Drawing.Point(315, 6); - this.cbMaster.Name = "cbMaster"; - this.cbMaster.Size = new System.Drawing.Size(170, 23); - this.cbMaster.TabIndex = 1; - // - // lblErgebnis - // - this.lblErgebnis.AutoSize = true; - this.lblErgebnis.Location = new System.Drawing.Point(497, 9); - this.lblErgebnis.Name = "lblErgebnis"; - this.lblErgebnis.Size = new System.Drawing.Size(58, 15); - this.lblErgebnis.Text = "Ergebnis:"; - // - // cbResult - // - this.cbResult.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.cbResult.Items.AddRange(new object[] { "Alle", "Gewinner", "Verlierer" }); - this.cbResult.Location = new System.Drawing.Point(559, 6); - this.cbResult.Name = "cbResult"; - this.cbResult.Size = new System.Drawing.Size(110, 23); - this.cbResult.TabIndex = 2; - // - // lblVon - // - this.lblVon.AutoSize = true; - this.lblVon.Location = new System.Drawing.Point(681, 9); - this.lblVon.Name = "lblVon"; - this.lblVon.Size = new System.Drawing.Size(31, 15); - this.lblVon.Text = "Von:"; - // - // dtFrom - // - this.dtFrom.Checked = false; - this.dtFrom.Format = System.Windows.Forms.DateTimePickerFormat.Short; - this.dtFrom.Location = new System.Drawing.Point(714, 6); - this.dtFrom.Name = "dtFrom"; - this.dtFrom.ShowCheckBox = true; - this.dtFrom.Size = new System.Drawing.Size(120, 23); - this.dtFrom.TabIndex = 3; - // - // lblBis - // - this.lblBis.AutoSize = true; - this.lblBis.Location = new System.Drawing.Point(840, 9); - this.lblBis.Name = "lblBis"; - this.lblBis.Size = new System.Drawing.Size(26, 15); - this.lblBis.Text = "Bis:"; - // - // dtTo - // - this.dtTo.Checked = false; - this.dtTo.Format = System.Windows.Forms.DateTimePickerFormat.Short; - this.dtTo.Location = new System.Drawing.Point(868, 6); - this.dtTo.Name = "dtTo"; - this.dtTo.ShowCheckBox = true; - this.dtTo.Size = new System.Drawing.Size(120, 23); - this.dtTo.TabIndex = 4; - // - // btnReset - // - this.btnReset.Location = new System.Drawing.Point(994, 5); - this.btnReset.Name = "btnReset"; - this.btnReset.Size = new System.Drawing.Size(90, 25); - this.btnReset.TabIndex = 5; - this.btnReset.Text = "Zurücksetzen"; - this.btnReset.UseVisualStyleBackColor = true; - // - // ClosedTradesView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.dgvTrades); - this.Controls.Add(this.statusPanel); - this.Controls.Add(this.pnlFilters); - this.Controls.Add(this.toolbar); - this.Name = "ClosedTradesView"; - this.Size = new System.Drawing.Size(1100, 600); - this.toolbar.ResumeLayout(false); - this.toolbar.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.dgvTrades)).EndInit(); - this.statusPanel.ResumeLayout(false); - this.pnlFilters.ResumeLayout(false); - this.pnlFilters.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.ToolStrip toolbar; - private System.Windows.Forms.ToolStripButton tsRefresh; - private System.Windows.Forms.DataGridView dgvTrades; - private System.Windows.Forms.DataGridViewTextBoxColumn colTradeId; - private System.Windows.Forms.DataGridViewTextBoxColumn colAccount; - private System.Windows.Forms.DataGridViewTextBoxColumn colTrader; - private System.Windows.Forms.DataGridViewTextBoxColumn colMarket; - private System.Windows.Forms.DataGridViewTextBoxColumn colOutcome; - private System.Windows.Forms.DataGridViewTextBoxColumn colSide; - private System.Windows.Forms.DataGridViewTextBoxColumn colEntry; - private System.Windows.Forms.DataGridViewTextBoxColumn colExit; - private System.Windows.Forms.DataGridViewTextBoxColumn colSize; - private System.Windows.Forms.DataGridViewTextBoxColumn colPnl; - private System.Windows.Forms.DataGridViewTextBoxColumn colPnlPct; - private System.Windows.Forms.DataGridViewTextBoxColumn colOpenedAt; - private System.Windows.Forms.DataGridViewTextBoxColumn colClosedAt; - private System.Windows.Forms.Panel statusPanel; - private System.Windows.Forms.Label lblSummary; - private System.Windows.Forms.Panel pnlFilters; - private System.Windows.Forms.Label lblMarkt; - private System.Windows.Forms.TextBox tbMarket; - private System.Windows.Forms.Label lblMaster; - private System.Windows.Forms.ComboBox cbMaster; - private System.Windows.Forms.Label lblErgebnis; - private System.Windows.Forms.ComboBox cbResult; - private System.Windows.Forms.Label lblVon; - private System.Windows.Forms.DateTimePicker dtFrom; - private System.Windows.Forms.Label lblBis; - private System.Windows.Forms.DateTimePicker dtTo; - private System.Windows.Forms.Button btnReset; - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/ClosedTradesView.cs b/src/PolyTrader.Modules.CopyTrading/Ui/ClosedTradesView.cs deleted file mode 100644 index 76221e8..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/ClosedTradesView.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Windows.Forms; -using PolyTrader.Modules.CopyTrading.Logic; -using PolyTrader.Modules.CopyTrading.Persistence; -using PolyTraderSharp; -using PolyTraderSharp.Models; - -namespace PolyTrader.Modules.CopyTrading.Ui -{ - /// - /// Zeigt die geschlossenen Copytrades des Moduls (mod_copytrading_closed_trades) mit - /// aufgelösten Account-/Master-Trader-Namen und einer Kurzauswertung. - /// Layout im Designer (ClosedTradesView.Designer.cs), Daten/Logik hier. - /// - public partial class ClosedTradesView : UserControl - { - private ICopyTradeLogRepository? _tradeLog; - private TradingState? _state; - private CopyTradingState? _copyState; - - private List _allRows = new(); - private bool _loading; - - // Parameterloser Konstruktor für den WinForms-Designer. - public ClosedTradesView() - { - InitializeComponent(); - - colEntry.DefaultCellStyle.Format = "F3"; - colExit.DefaultCellStyle.Format = "F3"; - colSize.DefaultCellStyle.Format = "F2"; - colPnl.DefaultCellStyle.Format = "F2"; - colPnlPct.DefaultCellStyle.Format = "F1"; - colOpenedAt.DefaultCellStyle.Format = "dd.MM.yyyy HH:mm"; - colClosedAt.DefaultCellStyle.Format = "dd.MM.yyyy HH:mm"; - - tsRefresh.Click += (_, _) => LoadData(); - - // Zeilenfärbung nach PnL-% (grün/hellgrün/rot) nach jedem (Neu-)Binden. - dgvTrades.DataBindingComplete += (_, _) => ColorRows(); - - // Filter: Markt (Text), Master (Combo), Ergebnis (Win/Loss), Datum (Von/Bis, optional). - tbMarket.TextChanged += (_, _) => ApplyFilter(); - cbMaster.SelectedIndexChanged += (_, _) => ApplyFilter(); - cbResult.SelectedIndexChanged += (_, _) => ApplyFilter(); - dtFrom.ValueChanged += (_, _) => ApplyFilter(); - dtTo.ValueChanged += (_, _) => ApplyFilter(); - btnReset.Click += (_, _) => ResetFilters(); - if (cbResult.Items.Count > 0) cbResult.SelectedIndex = 0; - } - - /// Injiziert die Abhängigkeiten (nach der DI-Auflösung) und lädt die Daten. - public void Initialize(ICopyTradeLogRepository tradeLog, TradingState state, CopyTradingState copyState) - { - _tradeLog = tradeLog; - _state = state; - _copyState = copyState; - LoadData(); - } - - private void LoadData() - { - if (_tradeLog == null) return; - - _allRows = _tradeLog.Find(_ => true) - .OrderByDescending(t => t.ClosedAt) - .Select(t => new ClosedTradeRow - { - TradeId = t.TradeId, - AccountId = t.AccountId, - SourceTraderId = t.SourceTraderId, - IsDemo = t.IsDemo, - TokenId = t.TokenId, - MarketSlug = t.MarketSlug, - MarketQuestion = t.MarketQuestion, - Outcome = t.Outcome, - Side = t.Side, - EntryPrice = t.EntryPrice, - ExitPrice = t.ExitPrice, - Size = t.Size, - RealizedPnl = t.RealizedPnl, - PnlPercent = t.PnlPercent, - TotalFees = t.TotalFees, - OpenedAt = t.OpenedAt, - ClosedAt = t.ClosedAt, - ExitReason = t.ExitReason, - AccountName = ResolveAccount(t.AccountId, t.IsDemo), - SourceTraderName = ResolveTrader(t.SourceTraderId) - }) - .ToList(); - - PopulateMasters(); - ApplyFilter(); - } - - private void PopulateMasters() - { - _loading = true; - string prev = cbMaster.SelectedItem as string ?? "Alle"; - cbMaster.Items.Clear(); - cbMaster.Items.Add("Alle"); - foreach (var m in _allRows.Select(r => r.SourceTraderName) - .Where(s => !string.IsNullOrEmpty(s)).Distinct().OrderBy(s => s)) - cbMaster.Items.Add(m); - int idx = cbMaster.Items.IndexOf(prev); - cbMaster.SelectedIndex = idx >= 0 ? idx : 0; - _loading = false; - } - - private void ApplyFilter() - { - if (_loading) return; - - IEnumerable q = _allRows; - - string market = tbMarket.Text.Trim(); - if (market.Length > 0) - q = q.Where(r => (r.MarketQuestion?.Contains(market, StringComparison.OrdinalIgnoreCase) ?? false) - || (r.MarketSlug?.Contains(market, StringComparison.OrdinalIgnoreCase) ?? false)); - - if (cbMaster.SelectedItem is string master && master != "Alle") - q = q.Where(r => r.SourceTraderName == master); - - string result = cbResult.SelectedItem as string ?? "Alle"; - if (result == "Gewinner") q = q.Where(r => r.RealizedPnl > 0m); - else if (result == "Verlierer") q = q.Where(r => r.RealizedPnl < 0m); - - if (dtFrom.Checked) { DateTime f = dtFrom.Value.Date; q = q.Where(r => r.ClosedAt >= f); } - if (dtTo.Checked) { DateTime t = dtTo.Value.Date.AddDays(1).AddTicks(-1); q = q.Where(r => r.ClosedAt <= t); } - - var rows = q.ToList(); - dgvTrades.DataSource = new BindingList(rows); - - decimal totalPnl = rows.Sum(x => x.RealizedPnl); - int wins = rows.Count(x => x.RealizedPnl > 0); - double winrate = rows.Count > 0 ? (double)wins / rows.Count * 100 : 0; - lblSummary.Text = $"{rows.Count} / {_allRows.Count} Trades | PnL: {totalPnl:F2} USDC | Winrate: {winrate:F1}%"; - } - - private void ResetFilters() - { - _loading = true; - tbMarket.Text = string.Empty; - if (cbMaster.Items.Count > 0) cbMaster.SelectedIndex = 0; - if (cbResult.Items.Count > 0) cbResult.SelectedIndex = 0; - dtFrom.Checked = false; - dtTo.Checked = false; - _loading = false; - ApplyFilter(); - } - - private void ColorRows() - { - foreach (DataGridViewRow row in dgvTrades.Rows) - if (row.DataBoundItem is ClosedTradeRow r) - row.DefaultCellStyle.BackColor = TradeRowPalette.ForPnlPercent(r.PnlPercent); - } - - private string ResolveAccount(int accountId, bool isDemo) - { - string suffix = isDemo ? " (Demo)" : ""; - if (_state != null && _state.Accounts.TryGetValue(accountId, out var acc) && !string.IsNullOrEmpty(acc.Name)) - return acc.Name + suffix; - return $"#{accountId}{suffix}"; - } - - private string ResolveTrader(int traderId) - { - if (_copyState != null && _copyState.Traders.TryGetValue(traderId, out var t) && !string.IsNullOrEmpty(t.DisplayName)) - return t.DisplayName; - return traderId > 0 ? $"#{traderId}" : "Unbekannt"; - } - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.Designer.cs b/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.Designer.cs deleted file mode 100644 index b06b408..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.Designer.cs +++ /dev/null @@ -1,167 +0,0 @@ -namespace PolyTrader.Modules.CopyTrading.Ui -{ - partial class CopyTradingMainForm - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CopyTradingMainForm)); - tabControl = new TabControl(); - tabMasters = new TabPage(); - masterTradersView = new MasterTradersView(); - tabOpen = new TabPage(); - openTradesView = new OpenTradesView(); - tabClosed = new TabPage(); - closedTradesView = new ClosedTradesView(); - tabSettings = new TabPage(); - accountSettingsView = new AccountSettingsView(); - tabControl.SuspendLayout(); - tabMasters.SuspendLayout(); - tabOpen.SuspendLayout(); - tabClosed.SuspendLayout(); - tabSettings.SuspendLayout(); - SuspendLayout(); - // - // tabControl - // - tabControl.Controls.Add(tabMasters); - tabControl.Controls.Add(tabOpen); - tabControl.Controls.Add(tabClosed); - tabControl.Controls.Add(tabSettings); - tabControl.Dock = DockStyle.Fill; - tabControl.Location = new Point(0, 0); - tabControl.Margin = new Padding(4, 5, 4, 5); - tabControl.Name = "tabControl"; - tabControl.SelectedIndex = 0; - tabControl.Size = new Size(1714, 1167); - tabControl.TabIndex = 0; - // - // tabMasters - // - tabMasters.Controls.Add(masterTradersView); - tabMasters.Location = new Point(4, 34); - tabMasters.Margin = new Padding(4, 5, 4, 5); - tabMasters.Name = "tabMasters"; - tabMasters.Padding = new Padding(4, 5, 4, 5); - tabMasters.Size = new Size(1706, 1129); - tabMasters.TabIndex = 0; - tabMasters.Text = "Master-Trader"; - tabMasters.UseVisualStyleBackColor = true; - // - // masterTradersView - // - masterTradersView.Dock = DockStyle.Fill; - masterTradersView.Location = new Point(4, 5); - masterTradersView.Margin = new Padding(6, 8, 6, 8); - masterTradersView.Name = "masterTradersView"; - masterTradersView.Size = new Size(1698, 1119); - masterTradersView.TabIndex = 0; - // - // tabOpen - // - tabOpen.Controls.Add(openTradesView); - tabOpen.Location = new Point(4, 34); - tabOpen.Margin = new Padding(4, 5, 4, 5); - tabOpen.Name = "tabOpen"; - tabOpen.Padding = new Padding(4, 5, 4, 5); - tabOpen.Size = new Size(1706, 1129); - tabOpen.TabIndex = 3; - tabOpen.Text = "Offene Trades"; - tabOpen.UseVisualStyleBackColor = true; - // - // openTradesView - // - openTradesView.Dock = DockStyle.Fill; - openTradesView.Location = new Point(4, 5); - openTradesView.Margin = new Padding(6, 8, 6, 8); - openTradesView.Name = "openTradesView"; - openTradesView.Size = new Size(1698, 1119); - openTradesView.TabIndex = 0; - // - // tabClosed - // - tabClosed.Controls.Add(closedTradesView); - tabClosed.Location = new Point(4, 34); - tabClosed.Margin = new Padding(4, 5, 4, 5); - tabClosed.Name = "tabClosed"; - tabClosed.Padding = new Padding(4, 5, 4, 5); - tabClosed.Size = new Size(1706, 1129); - tabClosed.TabIndex = 1; - tabClosed.Text = "Geschlossene Trades"; - tabClosed.UseVisualStyleBackColor = true; - // - // closedTradesView - // - closedTradesView.Dock = DockStyle.Fill; - closedTradesView.Location = new Point(4, 5); - closedTradesView.Margin = new Padding(6, 8, 6, 8); - closedTradesView.Name = "closedTradesView"; - closedTradesView.Size = new Size(1698, 1119); - closedTradesView.TabIndex = 0; - // - // tabSettings - // - tabSettings.Controls.Add(accountSettingsView); - tabSettings.Location = new Point(4, 34); - tabSettings.Margin = new Padding(4, 5, 4, 5); - tabSettings.Name = "tabSettings"; - tabSettings.Padding = new Padding(4, 5, 4, 5); - tabSettings.Size = new Size(1706, 1129); - tabSettings.TabIndex = 2; - tabSettings.Text = "Account-Einstellungen"; - tabSettings.UseVisualStyleBackColor = true; - // - // accountSettingsView - // - accountSettingsView.Dock = DockStyle.Fill; - accountSettingsView.Location = new Point(4, 5); - accountSettingsView.Margin = new Padding(6, 8, 6, 8); - accountSettingsView.Name = "accountSettingsView"; - accountSettingsView.Size = new Size(1698, 1119); - accountSettingsView.TabIndex = 0; - // - // CopyTradingMainForm - // - AutoScaleDimensions = new SizeF(10F, 25F); - AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1714, 1167); - Controls.Add(tabControl); - Icon = (Icon)resources.GetObject("$this.Icon"); - Margin = new Padding(4, 5, 4, 5); - MinimumSize = new Size(1162, 763); - Name = "CopyTradingMainForm"; - StartPosition = FormStartPosition.CenterScreen; - Text = "Copytrading"; - tabControl.ResumeLayout(false); - tabMasters.ResumeLayout(false); - tabOpen.ResumeLayout(false); - tabClosed.ResumeLayout(false); - tabSettings.ResumeLayout(false); - ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.TabControl tabControl; - private System.Windows.Forms.TabPage tabMasters; - private System.Windows.Forms.TabPage tabOpen; - private System.Windows.Forms.TabPage tabClosed; - private System.Windows.Forms.TabPage tabSettings; - private MasterTradersView masterTradersView; - private OpenTradesView openTradesView; - private ClosedTradesView closedTradesView; - private AccountSettingsView accountSettingsView; - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.cs b/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.cs deleted file mode 100644 index 345c82d..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Windows.Forms; -using Microsoft.Extensions.DependencyInjection; -using PolyTrader.Modules.CopyTrading.Persistence; -using PolyTraderSharp; - -namespace PolyTrader.Modules.CopyTrading.Ui -{ - /// - /// Das Hauptfenster des Copytrading-Moduls. Bündelt alle Modul-Ansichten in einem - /// TabControl (Master-Trader, geschlossene Trades, Account-Einstellungen), sodass der - /// Launcher nur EINEN "Copytrading"-Button braucht und nicht je View ein eigenes Fenster - /// öffnet. Layout im Designer (CopyTradingMainForm.Designer.cs). - /// - public partial class CopyTradingMainForm : Form - { - // Parameterloser Konstruktor für den WinForms-Designer. - public CopyTradingMainForm() - { - InitializeComponent(); - } - - /// Versorgt die einzelnen Tab-Ansichten mit ihren Abhängigkeiten (aus dem DI-Container). - public void Initialize(IServiceProvider services) - { - var state = services.GetRequiredService(); - var copyState = services.GetRequiredService(); - - masterTradersView.Initialize( - services.GetRequiredService(), state, copyState); - - openTradesView.Initialize(state, copyState); - - closedTradesView.Initialize( - services.GetRequiredService(), state, copyState); - - accountSettingsView.Initialize( - services.GetRequiredService(), state, copyState); - } - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.resx b/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.resx deleted file mode 100644 index d099850..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/CopyTradingMainForm.resx +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - AAABAAMAEBAAAAAAIAAWAwAANgAAABgYAAAAACAAuQQAAEwDAAAgIAAAAAAgALUDAAAFCAAAiVBORw0K - GgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC3UlEQVR4nFVTz0tUURT+7n33vTvvjTpvppn8gYoU - tooaoxEyC5QoMGhjP5btXfVXtJJo5SqJNv0JCRJpuUuRoiAtEWwUZ6BFzTjPmef9EeeNiR0491zeu/fc - 7zvnO2x0dLTr2fPnnwuFwlAcx5ZzzgDAWmtSUrJKdf/N+Nj4PQDGWssYYxanjFcqlXQ2DPO93T3IZbM4 - k8shzITo6+nlSilbvFS8u7q6+npmZqZjYWHBW1tbcwEkj5AJWpTSRmlNEVobMMagjYH0PP5tczMujow8 - mtzb+zg1NfWMztN/QkNARfsD4AoB4XB4nodarY7d3TLS6TRxEd9/fDcpz7v/dvldJwyatyYnZxlj2hjD - 2gkAOFJCpDsgpMSvchkDA/3EEJxzbozG+Nj1a34QXFNaYW19vXT1ypWHJwjgOOC1P8B+BRAOnKgB4UrE - rRaMaVP6/admosNI/yyX7UixOP1hZeX18PDwY4EoAkulgO1tqJUVOMS/Lw9cvAxXKYCaYpEg8VM+P5PL - 2Z2dHZPLZqePPO+JQBDANhqQpRK6SiVIAO7GJlgrAqdiGZOQpH18GCHb0YnOMMM3t7Zq9uCgXYOkinSw - fgBICULFzxYgcjl6nAoJGx+BSS/pjuEczBietDGiUnGuwbmSgW9d12XMFZxpw+O5OZhWC6wrA+fceahP - 60mC9I2bYIV88pDwfZ/6ERIO1yWNACkpwYSAf/sOjNbUY7B0Gm5fL4w18Hp6YCsVEH0RAPXFxcXZ98vL - 3VprEk/UFYZjD6anL6lMaIg+rAG0Ac52J11xHA7s7p5WNE6kTcuL+fmnNAvNw2YcRZFp+2ESG42G1kqZ - L1+//h4cHOxNLpAsj90hz4ShR5RkSiYU255KYhAEnDsO0XUb1h4rsT1hbGlpyU5MTOiXr17Vvm1sROpI - KftPbP/MWksJqtXqrwv9/epkqk4bQas3m0PNet1C/H//eAK57/sH+Xx+4y94l0zUCV+eDAAAAABJRU5E - rkJggolQTkcNChoKAAAADUlIRFIAAAAYAAAAGAgGAAAA4Hc9+AAABIBJREFUeJyFVk1sVFUU/u659703 - A5b+iTEpEMFkVFyKJJiS2JpoWmPUEDUuXbg3bsCFobPUhRFcsEGLSGlYmioBQugQReJKNvzYDcgwrSQU - 69DH/Lx37zHnzl+nxXKSk/vmvXvPd875zjl3FAAcn5r6aNu2bd8ardk5p0SwSqy1rqenR91bXPz9+OTk - G9PT0+XPraW8Ug6Pk2+OHPmSmbleT2oPlpd5OY7bGscPuVx+wM4xzy8spHEc88+nT8/u3r17E5TCwYMH - aT3bxnuXJCpJUyzcvavqtRo6ASj/XKvXsHVoCH9cuaJffmmXGx8be1UBP30xOTk+MTER5/P59QG8KaWQ - iTLQRCsAGmICgyAI0NfXh9vF27R4/34yOjq6t5IkpwqFwttzc3O6VCrZQqHg8vm8eyQAmCXitor3Ilpr - pDZF/DDGc7kcisUiyuV/yQSBg3ODIyMjKYC0Y4aFQl4LAAWjNZzVPgJmRhAGuP1XEfMLJZDWyEQRokxG - oOnS5cvix84fZ2Z+ccyuv7ePiqU7R5VS38/NzUW5XK7WDSCek2qoUiAQ0iTF/N/zGN47DDDATpz2zinZ - l4minijKDAtSPUnw9M2bw4cOHUpzudzU7OyskehWRCDpMNCZRgSKCJyk0DoQqnFvcRFEEllnv1QeM7vB - gQH8+tslvDk2Ror5xOHDh93IyMg0M5MHaJ0hRcDSP5BFjKo0BUM4U57k1QCSbOeclvfyvXinxENbtqZj - 4+MnvuvtFRKnGxFY6z12t27hwaefQBsNShmpseAPP4CKRqF4SfLS4r6ZVfnB3vjWLUO48ecNlc1m3St7 - 9phz58/vUkqdbABo7fMbvvgCNp8924imWRp08SJQrcAEQZurTo4AMgbLyzF2PLMDO7Y/iygwKnWOk1rN - V1YXB1SvgytVb4TFW2uBalVyB6Ju71eKY4f7S0twziIMQ/T39zcqZTWA0gYUNjwVg2y1bwrZSWCw7RDg - j/s9zkcrDSpfBWClNAGcN6I1wZJuAGiSMOAZl28DT4K08kYamQe4noJC0y4SWXVq1wIoVjJFfde2a0rK - RTFcUofOZBGfmELl5A+gIAAnCaivHxv270f5swOeQ++mtRj86muonc+DJb0tAEdEQRDIGxtFUXs6SrJ0 - GJJLair7zlvIvP5ax3+ZWT2b0HfsWJt5ZgczOOgLpgXqAQKiWmlhQVtrdWMmddhkZpAYyGbBG5/oLqEk - BTY/1XnjGJLZ1SlS586cOVW4cGH+YbXaJj3Qmowx8bv79h2Iomh7pVp1ZO2K400nknq3M2G0BoBnZmau - ArjRLP+WyHNl3/vvfayU2m60YW7T+WgRAGNk+kq2G1PbG1RKWSKqE1FVlJlrzCwrDGmZN83x8XhtF0jz - VvAAYkCqqKUtDmSuy1alVBqYIA3DcF2NosjfDcaYlJt3QlejPUqMMRtkSdLU0Nr/At0pah6RJs1mMr5j - /w+glWx99dq1o9euX99VqVSgWDpvfWEi17NxI5bL5fOthl9PpJjFCSmNxxpfIcKA3Gj1/wAymArsY369 - TAAAAABJRU5ErkJggolQTkcNChoKAAAADUlIRFIAAAAgAAAAIAgGAAAAc3p69AAAA3xJREFUeJy9V0tP - 1FAU/u5jGhSQqBGGCYkY5ZG4VDdA8Ae4Irx09B/5NwwLoMzAxoVxi48dC7YyJBiZmUR5ZWaEttfc29va - ae8wLT5OclN6es8533z3fKeFCCFACOF2qVQGIc+E50Ggm8kdBJQQeVObn5sbAXDRNcyYSqhy/XapJK5i - 1WpVrNr2VwC5q9Tn+tqjgWCvsi8Z6Qr63uhdvFlZwatiEbNTU4XV9fXK0sLCaFYmqL6SgHZKaaoV7P2y - V8FQPo/Z6enCqm1XsjJBEw7KwNjlS+7xYRMUCsMhiKczMwW7XM50HDzukPR3OgLfL5976n5yfBybW1vq - 74+fP6G4vCzP5w6AXgBH2QAI/xAYMwOQdHuOh7PGqVLBt8NDTExMYHJyMoxvtlrBditN8XYAQSFCEwDk - vaR+Z3cHtXpdNWHQtG37KAWjFGu2XYVK0V2qPJkkyYD89UfHx6jW63i+uIisVqvVBmWDLs3PJ1TC0zAg - farz/4FUaTyQMArCGUgu5y/Lv8rOF7ro35QqjQNgVg9Y3wD4jX5/9feD9/WC9vWBMJZBqjo1IRgezrdL - tVQKpcoTDFgWapz4PaTayF+NMQa8LnWVaphHPx97cB+lzU11fNsfttVxAAilyuOB1HUxLF9QUR+AH8en - EO/fXSrVdgAUJydnePLosVpR8/xesswMeA7Q9MLz9imgQKsBOE7HRk0iAJrNBpqNhroV+h2bzw+FzWwE - QGWk3BDZRKU0Iz6TVM0Yfu9Rs8OwhyeCaDIxiVGeioEkGuPw4nEHJbLTRXIOKH8AiKqpp46mzTRL+p3R - /sgDPK87AMZIlH0fgKZcRKRKeq4hgimsAccF5ByJYRMuIFrN7gCIgVrpo4x0lGrUhoRA1ZBDgh88dy4B - QPwgOUTaKND+th4wSDUoAhfId3gmWudAjpkB0GByRYpGzbKsEERCqoYeSECQoNQZWUYAotVo7G6Uyw/V - kIg1QTD5eDCKDVKNF4s3ss6U8HB9/fmyWHwB4LY8BXNW5NZs+20nqV7VuL7KcbUP4NAI07ebl0k1nXVm - wAFwkjaNSaqpyht6i2dPY070fwCQDlLNGB9VGc8S302qV8nDM8QJ13EONsrlEZNUU5mcqITAdd2DoIuJ - /u84TfgAAPlBecv0KZfB5DT6DkB+Gx5nASC/4a7rUfYng0D+8nMt/YtfpUqCfHEGzEEAAAAASUVORK5C - YII= - - - \ No newline at end of file diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.Designer.cs b/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.Designer.cs deleted file mode 100644 index 01544e0..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.Designer.cs +++ /dev/null @@ -1,348 +0,0 @@ -namespace PolyTrader.Modules.CopyTrading.Ui -{ - partial class MasterTradersView - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - private void InitializeComponent() - { - this.toolbar = new System.Windows.Forms.ToolStrip(); - this.tsNew = new System.Windows.Forms.ToolStripButton(); - this.tsSave = new System.Windows.Forms.ToolStripButton(); - this.tsDelete = new System.Windows.Forms.ToolStripButton(); - this.tsSep = new System.Windows.Forms.ToolStripSeparator(); - this.tsRefresh = new System.Windows.Forms.ToolStripButton(); - this.grid = new System.Windows.Forms.DataGridView(); - this.colId = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colWallet = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colName = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colCategory = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colActive = new System.Windows.Forms.DataGridViewCheckBoxColumn(); - this.colTrades = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colWinrate = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colPnl = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colCopyPnl = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colCopyPf = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colCopyAvg = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colCopyCount = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.splitter = new System.Windows.Forms.Splitter(); - this.rightPanel = new System.Windows.Forms.Panel(); - this.pgDetail = new System.Windows.Forms.PropertyGrid(); - this.grpAccounts = new System.Windows.Forms.GroupBox(); - this.clbAccounts = new System.Windows.Forms.CheckedListBox(); - this.statusPanel = new System.Windows.Forms.Panel(); - this.lblHint = new System.Windows.Forms.Label(); - this.toolbar.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit(); - this.rightPanel.SuspendLayout(); - this.grpAccounts.SuspendLayout(); - this.statusPanel.SuspendLayout(); - this.SuspendLayout(); - // - // toolbar - // - this.toolbar.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - this.toolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.tsNew, - this.tsSave, - this.tsDelete, - this.tsSep, - this.tsRefresh}); - this.toolbar.Location = new System.Drawing.Point(0, 0); - this.toolbar.Name = "toolbar"; - this.toolbar.Size = new System.Drawing.Size(1180, 25); - this.toolbar.TabIndex = 0; - // - // tsNew - // - this.tsNew.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.tsNew.Name = "tsNew"; - this.tsNew.Size = new System.Drawing.Size(35, 22); - this.tsNew.Text = "Neu"; - // - // tsSave - // - this.tsSave.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.tsSave.Name = "tsSave"; - this.tsSave.Size = new System.Drawing.Size(69, 22); - this.tsSave.Text = "Speichern"; - // - // tsDelete - // - this.tsDelete.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.tsDelete.Name = "tsDelete"; - this.tsDelete.Size = new System.Drawing.Size(57, 22); - this.tsDelete.Text = "Löschen"; - // - // tsSep - // - this.tsSep.Name = "tsSep"; - this.tsSep.Size = new System.Drawing.Size(6, 25); - // - // tsRefresh - // - this.tsRefresh.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.tsRefresh.Name = "tsRefresh"; - this.tsRefresh.Size = new System.Drawing.Size(90, 22); - this.tsRefresh.Text = "Aktualisieren"; - // - // grid - // - this.grid.AllowUserToAddRows = false; - this.grid.AllowUserToDeleteRows = false; - this.grid.AutoGenerateColumns = false; - this.grid.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; - this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.grid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.colId, - this.colWallet, - this.colName, - this.colCategory, - this.colActive, - this.colTrades, - this.colWinrate, - this.colPnl, - this.colCopyPnl, - this.colCopyPf, - this.colCopyAvg, - this.colCopyCount}); - this.grid.Dock = System.Windows.Forms.DockStyle.Fill; - this.grid.Location = new System.Drawing.Point(0, 25); - this.grid.MultiSelect = false; - this.grid.Name = "grid"; - this.grid.ReadOnly = true; - this.grid.RowHeadersVisible = false; - this.grid.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; - this.grid.Size = new System.Drawing.Size(715, 589); - this.grid.TabIndex = 4; - // - // colId - // - this.colId.DataPropertyName = "Id"; - this.colId.HeaderText = "#"; - this.colId.Name = "colId"; - this.colId.ReadOnly = true; - this.colId.Width = 50; - // - // colWallet - // - this.colWallet.DataPropertyName = "WalletAddress"; - this.colWallet.HeaderText = "Wallet"; - this.colWallet.Name = "colWallet"; - this.colWallet.ReadOnly = true; - this.colWallet.Width = 170; - // - // colName - // - this.colName.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill; - this.colName.DataPropertyName = "DisplayName"; - this.colName.HeaderText = "Name"; - this.colName.Name = "colName"; - this.colName.ReadOnly = true; - // - // colCategory - // - this.colCategory.DataPropertyName = "Category"; - this.colCategory.HeaderText = "Kategorie"; - this.colCategory.Name = "colCategory"; - this.colCategory.ReadOnly = true; - this.colCategory.Width = 110; - // - // colActive - // - this.colActive.DataPropertyName = "IsActive"; - this.colActive.HeaderText = "Aktiv"; - this.colActive.Name = "colActive"; - this.colActive.ReadOnly = true; - this.colActive.Width = 50; - // - // colTrades - // - this.colTrades.DataPropertyName = "TotalTrades"; - this.colTrades.HeaderText = "Trades (7T)"; - this.colTrades.Name = "colTrades"; - this.colTrades.ReadOnly = true; - this.colTrades.Width = 90; - // - // colWinrate - // - this.colWinrate.DataPropertyName = "Winrate30t"; - this.colWinrate.HeaderText = "Winrate %"; - this.colWinrate.Name = "colWinrate"; - this.colWinrate.ReadOnly = true; - this.colWinrate.Width = 90; - // - // colPnl - // - this.colPnl.DataPropertyName = "TotalPnl"; - this.colPnl.HeaderText = "PnL (7T)"; - this.colPnl.Name = "colPnl"; - this.colPnl.ReadOnly = true; - this.colPnl.Width = 100; - // - // colCopyPnl - // - this.colCopyPnl.DataPropertyName = "CopyPnl30d"; - this.colCopyPnl.HeaderText = "Copy-PnL (30T)"; - this.colCopyPnl.Name = "colCopyPnl"; - this.colCopyPnl.ReadOnly = true; - this.colCopyPnl.Width = 110; - // - // colCopyPf - // - this.colCopyPf.DataPropertyName = "CopyProfitFactor"; - this.colCopyPf.HeaderText = "Profit-Faktor"; - this.colCopyPf.Name = "colCopyPf"; - this.colCopyPf.ReadOnly = true; - this.colCopyPf.Width = 100; - // - // colCopyAvg - // - this.colCopyAvg.DataPropertyName = "CopyAvgPnlPerTrade"; - this.colCopyAvg.HeaderText = "Ø PnL/Trade"; - this.colCopyAvg.Name = "colCopyAvg"; - this.colCopyAvg.ReadOnly = true; - this.colCopyAvg.Width = 100; - // - // colCopyCount - // - this.colCopyCount.DataPropertyName = "CopyTradeCount30d"; - this.colCopyCount.HeaderText = "Copy-Trades"; - this.colCopyCount.Name = "colCopyCount"; - this.colCopyCount.ReadOnly = true; - this.colCopyCount.Width = 90; - // - // splitter - // - this.splitter.Dock = System.Windows.Forms.DockStyle.Right; - this.splitter.Location = new System.Drawing.Point(715, 25); - this.splitter.Name = "splitter"; - this.splitter.Size = new System.Drawing.Size(5, 589); - this.splitter.TabIndex = 3; - this.splitter.TabStop = false; - // - // rightPanel - // - this.rightPanel.Controls.Add(this.pgDetail); - this.rightPanel.Controls.Add(this.grpAccounts); - this.rightPanel.Dock = System.Windows.Forms.DockStyle.Right; - this.rightPanel.Location = new System.Drawing.Point(720, 25); - this.rightPanel.Name = "rightPanel"; - this.rightPanel.Padding = new System.Windows.Forms.Padding(6, 0, 0, 0); - this.rightPanel.Size = new System.Drawing.Size(460, 589); - this.rightPanel.TabIndex = 2; - // - // pgDetail - // - this.pgDetail.Dock = System.Windows.Forms.DockStyle.Fill; - this.pgDetail.Location = new System.Drawing.Point(6, 0); - this.pgDetail.Name = "pgDetail"; - this.pgDetail.PropertySort = System.Windows.Forms.PropertySort.Categorized; - this.pgDetail.Size = new System.Drawing.Size(454, 399); - this.pgDetail.TabIndex = 0; - this.pgDetail.ToolbarVisible = false; - // - // grpAccounts - // - this.grpAccounts.Controls.Add(this.clbAccounts); - this.grpAccounts.Dock = System.Windows.Forms.DockStyle.Bottom; - this.grpAccounts.Location = new System.Drawing.Point(6, 399); - this.grpAccounts.Name = "grpAccounts"; - this.grpAccounts.Padding = new System.Windows.Forms.Padding(8); - this.grpAccounts.Size = new System.Drawing.Size(454, 190); - this.grpAccounts.TabIndex = 1; - this.grpAccounts.TabStop = false; - this.grpAccounts.Text = "Zugewiesene Accounts (kopieren diesen Trader)"; - // - // clbAccounts - // - this.clbAccounts.CheckOnClick = true; - this.clbAccounts.Dock = System.Windows.Forms.DockStyle.Fill; - this.clbAccounts.IntegralHeight = false; - this.clbAccounts.Location = new System.Drawing.Point(8, 24); - this.clbAccounts.Name = "clbAccounts"; - this.clbAccounts.Size = new System.Drawing.Size(438, 158); - this.clbAccounts.TabIndex = 0; - // - // statusPanel - // - this.statusPanel.Controls.Add(this.lblHint); - this.statusPanel.Dock = System.Windows.Forms.DockStyle.Bottom; - this.statusPanel.Location = new System.Drawing.Point(0, 614); - this.statusPanel.Name = "statusPanel"; - this.statusPanel.Size = new System.Drawing.Size(1180, 26); - this.statusPanel.TabIndex = 1; - // - // lblHint - // - this.lblHint.Dock = System.Windows.Forms.DockStyle.Fill; - this.lblHint.ForeColor = System.Drawing.Color.DimGray; - this.lblHint.Location = new System.Drawing.Point(0, 0); - this.lblHint.Name = "lblHint"; - this.lblHint.Padding = new System.Windows.Forms.Padding(8, 0, 0, 0); - this.lblHint.Size = new System.Drawing.Size(1180, 26); - this.lblHint.TabIndex = 0; - this.lblHint.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // MasterTradersView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.grid); - this.Controls.Add(this.splitter); - this.Controls.Add(this.rightPanel); - this.Controls.Add(this.statusPanel); - this.Controls.Add(this.toolbar); - this.Name = "MasterTradersView"; - this.Size = new System.Drawing.Size(1180, 640); - this.toolbar.ResumeLayout(false); - this.toolbar.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit(); - this.rightPanel.ResumeLayout(false); - this.grpAccounts.ResumeLayout(false); - this.statusPanel.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.ToolStrip toolbar; - private System.Windows.Forms.ToolStripButton tsNew; - private System.Windows.Forms.ToolStripButton tsSave; - private System.Windows.Forms.ToolStripButton tsDelete; - private System.Windows.Forms.ToolStripSeparator tsSep; - private System.Windows.Forms.ToolStripButton tsRefresh; - private System.Windows.Forms.DataGridView grid; - private System.Windows.Forms.DataGridViewTextBoxColumn colId; - private System.Windows.Forms.DataGridViewTextBoxColumn colWallet; - private System.Windows.Forms.DataGridViewTextBoxColumn colName; - private System.Windows.Forms.DataGridViewTextBoxColumn colCategory; - private System.Windows.Forms.DataGridViewCheckBoxColumn colActive; - private System.Windows.Forms.DataGridViewTextBoxColumn colTrades; - private System.Windows.Forms.DataGridViewTextBoxColumn colWinrate; - private System.Windows.Forms.DataGridViewTextBoxColumn colPnl; - private System.Windows.Forms.DataGridViewTextBoxColumn colCopyPnl; - private System.Windows.Forms.DataGridViewTextBoxColumn colCopyPf; - private System.Windows.Forms.DataGridViewTextBoxColumn colCopyAvg; - private System.Windows.Forms.DataGridViewTextBoxColumn colCopyCount; - private System.Windows.Forms.Splitter splitter; - private System.Windows.Forms.Panel rightPanel; - private System.Windows.Forms.PropertyGrid pgDetail; - private System.Windows.Forms.GroupBox grpAccounts; - private System.Windows.Forms.CheckedListBox clbAccounts; - private System.Windows.Forms.Panel statusPanel; - private System.Windows.Forms.Label lblHint; - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.cs b/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.cs deleted file mode 100644 index 0493ef0..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Windows.Forms; -using PolyTrader.Modules.CopyTrading.Persistence; -using PolyTraderSharp; -using PolyTraderSharp.Models; - -namespace PolyTrader.Modules.CopyTrading.Ui -{ - /// - /// Verwaltung der Master-Trader (mod_copytrading_traders): Liste, Detail-Editor - /// (PropertyGrid) und Account-Zuweisung (welche Accounts diesen Trader kopieren). - /// Persistiert über das Repo und hält den Hot-Path-State - /// () synchron. - /// Layout im Designer (MasterTradersView.Designer.cs), Daten/Logik hier. - /// - public partial class MasterTradersView : UserControl - { - private ITrackedTraderRepository? _repo; - private TradingState? _state; - private CopyTradingState? _copyState; - - private BindingList _binding = new(); - private TrackedTrader? _current; - - // Parameterloser Konstruktor für den WinForms-Designer. - public MasterTradersView() - { - InitializeComponent(); - - colWinrate.DefaultCellStyle.Format = "F1"; - colPnl.DefaultCellStyle.Format = "F2"; - colCopyPnl.DefaultCellStyle.Format = "F2"; - colCopyPf.DefaultCellStyle.Format = "F2"; - colCopyAvg.DefaultCellStyle.Format = "F2"; - - // Spaltenbreiten proportional (grid-weites Fill): keine überlaufenden Fixbreiten mehr, - // die Spalten teilen sich immer exakt die verfügbare Breite (Fix des „verbuggten" Grids). - colId.FillWeight = 40; - colWallet.FillWeight = 150; - colName.FillWeight = 200; - colCategory.FillWeight = 90; - colActive.FillWeight = 50; - colTrades.FillWeight = 85; - colWinrate.FillWeight = 90; - colPnl.FillWeight = 90; - colCopyPnl.FillWeight = 110; - colCopyPf.FillWeight = 95; - colCopyAvg.FillWeight = 95; - colCopyCount.FillWeight = 95; - - tsNew.Click += (_, _) => AddNew(); - tsSave.Click += (_, _) => SaveCurrent(); - tsDelete.Click += (_, _) => DeleteCurrent(); - tsRefresh.Click += (_, _) => LoadData(); - grid.SelectionChanged += (_, _) => OnSelectionChanged(); - } - - /// Injiziert die Abhängigkeiten (nach der DI-Auflösung) und lädt die Trader. - public void Initialize(ITrackedTraderRepository repo, TradingState state, CopyTradingState copyState) - { - _repo = repo; - _state = state; - _copyState = copyState; - LoadData(); - } - - private void LoadData() - { - if (_repo == null) return; - - var traders = _repo.GetAll().OrderBy(t => t.Id).ToList(); - _binding = new BindingList(traders); - grid.DataSource = _binding; - if (traders.Count > 0) - grid.CurrentCell = grid.Rows[0].Cells[0]; - else - ClearDetail(); - lblHint.Text = $"{traders.Count} Master-Trader geladen."; - } - - private void OnSelectionChanged() - { - if (grid.CurrentRow?.DataBoundItem is TrackedTrader t) - BindDetail(t); - } - - private void BindDetail(TrackedTrader trader) - { - _current = trader; - pgDetail.SelectedObject = trader; - - clbAccounts.Items.Clear(); - if (_state == null) return; - foreach (var acc in _state.Accounts.Values.OrderBy(a => a.AccountId)) - { - string label = string.IsNullOrEmpty(acc.Name) ? $"#{acc.AccountId}" : $"{acc.Name} (#{acc.AccountId}){(acc.IsDemo ? " · Demo" : "")}"; - int idx = clbAccounts.Items.Add(new AccountItem(acc.AccountId, label)); - clbAccounts.SetItemChecked(idx, trader.AssignedAccountIds.Contains(acc.AccountId)); - } - } - - private void ClearDetail() - { - _current = null; - pgDetail.SelectedObject = null; - clbAccounts.Items.Clear(); - } - - private void AddNew() - { - int nextId = _binding.Count > 0 ? _binding.Max(t => t.Id) + 1 : 1; - var trader = new TrackedTrader { Id = nextId, DisplayName = $"Neuer Trader {nextId}" }; - _binding.Add(trader); - grid.CurrentCell = grid.Rows[_binding.Count - 1].Cells[0]; - lblHint.Text = $"Neuer Master-Trader #{nextId} – Felder ausfüllen und Speichern."; - } - - private void SaveCurrent() - { - if (_current == null || _repo == null || _copyState == null) { lblHint.Text = "Kein Trader ausgewählt."; return; } - - _current.AssignedAccountIds = clbAccounts.CheckedItems.Cast().Select(a => a.Id).ToHashSet(); - - _repo.Upsert(_current); - _copyState.Traders[_current.Id] = _current; - grid.Refresh(); - lblHint.Text = $"Gespeichert: #{_current.Id} {_current.DisplayName} ({_current.AssignedAccountIds.Count} Account(s)) um {DateTime.Now:HH:mm:ss}."; - } - - private void DeleteCurrent() - { - if (_current == null || _repo == null || _copyState == null) { lblHint.Text = "Kein Trader ausgewählt."; return; } - var id = _current.Id; - if (MessageBox.Show($"Master-Trader #{id} ({_current.DisplayName}) wirklich löschen?", - "Löschen bestätigen", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes) - return; - - _repo.Delete(id); - _copyState.Traders.TryRemove(id, out _); - _binding.Remove(_current); - ClearDetail(); - lblHint.Text = $"Master-Trader #{id} gelöscht."; - } - - private sealed record AccountItem(int Id, string Label) - { - public override string ToString() => Label; - } - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.resx b/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.resx deleted file mode 100644 index 1af7de1..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/OpenTradesView.Designer.cs b/src/PolyTrader.Modules.CopyTrading/Ui/OpenTradesView.Designer.cs deleted file mode 100644 index 4c79126..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/OpenTradesView.Designer.cs +++ /dev/null @@ -1,241 +0,0 @@ -namespace PolyTrader.Modules.CopyTrading.Ui -{ - partial class OpenTradesView - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - private void InitializeComponent() - { - this.toolbar = new System.Windows.Forms.ToolStrip(); - this.tsRefresh = new System.Windows.Forms.ToolStripButton(); - this.dgvOpen = new System.Windows.Forms.DataGridView(); - this.colAccount = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colTrader = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colMarket = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colOutcome = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colSide = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colEntry = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colCurrent = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colSize = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colAmount = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colValue = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colUnrealized = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colUnrealizedPct = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.colStatus = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.statusPanel = new System.Windows.Forms.Panel(); - this.lblSummary = new System.Windows.Forms.Label(); - this.toolbar.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.dgvOpen)).BeginInit(); - this.statusPanel.SuspendLayout(); - this.SuspendLayout(); - // - // toolbar - // - this.toolbar.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; - this.toolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.tsRefresh }); - this.toolbar.Location = new System.Drawing.Point(0, 0); - this.toolbar.Name = "toolbar"; - this.toolbar.Size = new System.Drawing.Size(1100, 25); - this.toolbar.TabIndex = 0; - // - // tsRefresh - // - this.tsRefresh.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; - this.tsRefresh.Name = "tsRefresh"; - this.tsRefresh.Size = new System.Drawing.Size(90, 22); - this.tsRefresh.Text = "Aktualisieren"; - // - // dgvOpen - // - this.dgvOpen.AllowUserToAddRows = false; - this.dgvOpen.AllowUserToDeleteRows = false; - this.dgvOpen.AutoGenerateColumns = false; - this.dgvOpen.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; - this.dgvOpen.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.dgvOpen.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { - this.colAccount, this.colTrader, this.colMarket, this.colOutcome, this.colSide, - this.colEntry, this.colCurrent, this.colSize, this.colAmount, this.colValue, - this.colUnrealized, this.colUnrealizedPct, this.colStatus}); - this.dgvOpen.Dock = System.Windows.Forms.DockStyle.Fill; - this.dgvOpen.Location = new System.Drawing.Point(0, 25); - this.dgvOpen.Name = "dgvOpen"; - this.dgvOpen.ReadOnly = true; - this.dgvOpen.RowHeadersVisible = false; - this.dgvOpen.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; - this.dgvOpen.Size = new System.Drawing.Size(1100, 549); - this.dgvOpen.TabIndex = 1; - // - // colAccount - // - this.colAccount.DataPropertyName = "AccountName"; - this.colAccount.HeaderText = "Account"; - this.colAccount.Name = "colAccount"; - this.colAccount.ReadOnly = true; - this.colAccount.FillWeight = 120; - // - // colTrader - // - this.colTrader.DataPropertyName = "SourceTraderName"; - this.colTrader.HeaderText = "Master-Trader"; - this.colTrader.Name = "colTrader"; - this.colTrader.ReadOnly = true; - this.colTrader.FillWeight = 120; - // - // colMarket - // - this.colMarket.DataPropertyName = "MarketQuestion"; - this.colMarket.HeaderText = "Markt"; - this.colMarket.Name = "colMarket"; - this.colMarket.ReadOnly = true; - this.colMarket.FillWeight = 240; - // - // colOutcome - // - this.colOutcome.DataPropertyName = "Outcome"; - this.colOutcome.HeaderText = "Outcome"; - this.colOutcome.Name = "colOutcome"; - this.colOutcome.ReadOnly = true; - this.colOutcome.FillWeight = 80; - // - // colSide - // - this.colSide.DataPropertyName = "Side"; - this.colSide.HeaderText = "Side"; - this.colSide.Name = "colSide"; - this.colSide.ReadOnly = true; - this.colSide.FillWeight = 55; - // - // colEntry - // - this.colEntry.DataPropertyName = "EntryPrice"; - this.colEntry.HeaderText = "Entry"; - this.colEntry.Name = "colEntry"; - this.colEntry.ReadOnly = true; - this.colEntry.FillWeight = 65; - // - // colCurrent - // - this.colCurrent.DataPropertyName = "CurrentPrice"; - this.colCurrent.HeaderText = "Aktuell"; - this.colCurrent.Name = "colCurrent"; - this.colCurrent.ReadOnly = true; - this.colCurrent.FillWeight = 65; - // - // colSize - // - this.colSize.DataPropertyName = "Size"; - this.colSize.HeaderText = "Size"; - this.colSize.Name = "colSize"; - this.colSize.ReadOnly = true; - this.colSize.FillWeight = 70; - // - // colAmount - // - this.colAmount.DataPropertyName = "AmountUsd"; - this.colAmount.HeaderText = "Einsatz"; - this.colAmount.Name = "colAmount"; - this.colAmount.ReadOnly = true; - this.colAmount.FillWeight = 80; - // - // colValue - // - this.colValue.DataPropertyName = "CurrentValueUsd"; - this.colValue.HeaderText = "Wert"; - this.colValue.Name = "colValue"; - this.colValue.ReadOnly = true; - this.colValue.FillWeight = 80; - // - // colUnrealized - // - this.colUnrealized.DataPropertyName = "UnrealizedPnl"; - this.colUnrealized.HeaderText = "Buchgewinn"; - this.colUnrealized.Name = "colUnrealized"; - this.colUnrealized.ReadOnly = true; - this.colUnrealized.FillWeight = 90; - // - // colUnrealizedPct - // - this.colUnrealizedPct.DataPropertyName = "UnrealizedPct"; - this.colUnrealizedPct.HeaderText = "Buchgew. %"; - this.colUnrealizedPct.Name = "colUnrealizedPct"; - this.colUnrealizedPct.ReadOnly = true; - this.colUnrealizedPct.FillWeight = 80; - // - // colStatus - // - this.colStatus.DataPropertyName = "Status"; - this.colStatus.HeaderText = "Status"; - this.colStatus.Name = "colStatus"; - this.colStatus.ReadOnly = true; - this.colStatus.FillWeight = 90; - // - // statusPanel - // - this.statusPanel.Controls.Add(this.lblSummary); - this.statusPanel.Dock = System.Windows.Forms.DockStyle.Bottom; - this.statusPanel.Location = new System.Drawing.Point(0, 574); - this.statusPanel.Name = "statusPanel"; - this.statusPanel.Size = new System.Drawing.Size(1100, 26); - this.statusPanel.TabIndex = 2; - // - // lblSummary - // - this.lblSummary.Dock = System.Windows.Forms.DockStyle.Fill; - this.lblSummary.Location = new System.Drawing.Point(0, 0); - this.lblSummary.Name = "lblSummary"; - this.lblSummary.Padding = new System.Windows.Forms.Padding(8, 0, 0, 0); - this.lblSummary.Size = new System.Drawing.Size(1100, 26); - this.lblSummary.TabIndex = 0; - this.lblSummary.Text = "—"; - this.lblSummary.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; - // - // OpenTradesView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.dgvOpen); - this.Controls.Add(this.statusPanel); - this.Controls.Add(this.toolbar); - this.Name = "OpenTradesView"; - this.Size = new System.Drawing.Size(1100, 600); - this.toolbar.ResumeLayout(false); - this.toolbar.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.dgvOpen)).EndInit(); - this.statusPanel.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); - } - - #endregion - - private System.Windows.Forms.ToolStrip toolbar; - private System.Windows.Forms.ToolStripButton tsRefresh; - private System.Windows.Forms.DataGridView dgvOpen; - private System.Windows.Forms.DataGridViewTextBoxColumn colAccount; - private System.Windows.Forms.DataGridViewTextBoxColumn colTrader; - private System.Windows.Forms.DataGridViewTextBoxColumn colMarket; - private System.Windows.Forms.DataGridViewTextBoxColumn colOutcome; - private System.Windows.Forms.DataGridViewTextBoxColumn colSide; - private System.Windows.Forms.DataGridViewTextBoxColumn colEntry; - private System.Windows.Forms.DataGridViewTextBoxColumn colCurrent; - private System.Windows.Forms.DataGridViewTextBoxColumn colSize; - private System.Windows.Forms.DataGridViewTextBoxColumn colAmount; - private System.Windows.Forms.DataGridViewTextBoxColumn colValue; - private System.Windows.Forms.DataGridViewTextBoxColumn colUnrealized; - private System.Windows.Forms.DataGridViewTextBoxColumn colUnrealizedPct; - private System.Windows.Forms.DataGridViewTextBoxColumn colStatus; - private System.Windows.Forms.Panel statusPanel; - private System.Windows.Forms.Label lblSummary; - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/OpenTradesView.cs b/src/PolyTrader.Modules.CopyTrading/Ui/OpenTradesView.cs deleted file mode 100644 index 37d03ef..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/OpenTradesView.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Windows.Forms; -using PolyTrader.Modules.CopyTrading.Logic; -using PolyTraderSharp; -using PolyTraderSharp.Models; - -namespace PolyTrader.Modules.CopyTrading.Ui -{ - /// - /// Listet ALLE aktuell offenen Positionen (Portfolios der Accounts) mit Buchgewinn/-verlust. - /// Quelle ist der Laufzeit-State (), nicht die DB – so ist die - /// Anzeige live. Zeilenfärbung nach Buchgewinn-% (). - /// Layout im Designer (OpenTradesView.Designer.cs). - /// - public partial class OpenTradesView : UserControl - { - private TradingState? _state; - private CopyTradingState? _copyState; - - public OpenTradesView() - { - InitializeComponent(); - - colEntry.DefaultCellStyle.Format = "F3"; - colCurrent.DefaultCellStyle.Format = "F3"; - colSize.DefaultCellStyle.Format = "F2"; - colAmount.DefaultCellStyle.Format = "F2"; - colValue.DefaultCellStyle.Format = "F2"; - colUnrealized.DefaultCellStyle.Format = "F2"; - colUnrealizedPct.DefaultCellStyle.Format = "F1"; - - tsRefresh.Click += (_, _) => LoadData(); - dgvOpen.DataBindingComplete += (_, _) => ColorRows(); - } - - public void Initialize(TradingState state, CopyTradingState copyState) - { - _state = state; - _copyState = copyState; - LoadData(); - } - - private void LoadData() - { - if (_state == null) return; - - var rows = _state.Accounts.Values - .SelectMany(a => a.OpenPositions.Values.Select(p => (acc: a, pos: p))) - .OrderByDescending(x => x.pos.CurrentValueUsd) - .Select(x => - { - decimal unrealized = x.pos.CurrentValueUsd - x.pos.AmountUsd; - decimal pct = x.pos.AmountUsd > 0m ? unrealized / x.pos.AmountUsd * 100m : 0m; - return new OpenTradeRow - { - AccountName = ResolveAccount(x.acc.AccountId, x.pos.IsDemo), - SourceTraderName = ResolveTrader(x.pos.SourceTraderId, x.pos.SourceTraderName), - MarketQuestion = x.pos.MarketQuestion, - Outcome = x.pos.Outcome, - Side = x.pos.Side, - EntryPrice = x.pos.EntryPrice, - CurrentPrice = x.pos.CurrentPrice, - Size = x.pos.Size, - AmountUsd = x.pos.AmountUsd, - CurrentValueUsd = x.pos.CurrentValueUsd, - UnrealizedPnl = unrealized, - UnrealizedPct = pct, - Status = x.pos.ExitPending ? "Exit läuft" : "offen" - }; - }) - .ToList(); - - dgvOpen.DataSource = new BindingList(rows); - - decimal totalValue = rows.Sum(r => r.CurrentValueUsd); - decimal totalUnrealized = rows.Sum(r => r.UnrealizedPnl); - lblSummary.Text = $"{rows.Count} offene Positionen | Wert: {totalValue:F2} USDC | Buchgewinn: {totalUnrealized:F2} USDC"; - } - - private void ColorRows() - { - foreach (DataGridViewRow row in dgvOpen.Rows) - if (row.DataBoundItem is OpenTradeRow r) - row.DefaultCellStyle.BackColor = TradeRowPalette.ForPnlPercent(r.UnrealizedPct); - } - - private string ResolveAccount(int accountId, bool isDemo) - { - string suffix = isDemo ? " (Demo)" : ""; - if (_state != null && _state.Accounts.TryGetValue(accountId, out var acc) && !string.IsNullOrEmpty(acc.Name)) - return acc.Name + suffix; - return $"#{accountId}{suffix}"; - } - - private string ResolveTrader(int traderId, string fallback) - { - if (_copyState != null && _copyState.Traders.TryGetValue(traderId, out var t) && !string.IsNullOrEmpty(t.DisplayName)) - return t.DisplayName; - return !string.IsNullOrEmpty(fallback) ? fallback : (traderId > 0 ? $"#{traderId}" : "System"); - } - - /// Anzeige-Zeile für offene Positionen. - private sealed class OpenTradeRow - { - public string AccountName { get; set; } = string.Empty; - public string SourceTraderName { get; set; } = string.Empty; - public string MarketQuestion { get; set; } = string.Empty; - public string Outcome { get; set; } = string.Empty; - public string Side { get; set; } = string.Empty; - public decimal EntryPrice { get; set; } - public decimal CurrentPrice { get; set; } - public decimal Size { get; set; } - public decimal AmountUsd { get; set; } - public decimal CurrentValueUsd { get; set; } - public decimal UnrealizedPnl { get; set; } - public decimal UnrealizedPct { get; set; } - public string Status { get; set; } = string.Empty; - } - } -} diff --git a/src/PolyTrader.Modules.CopyTrading/Ui/TradeRowPalette.cs b/src/PolyTrader.Modules.CopyTrading/Ui/TradeRowPalette.cs deleted file mode 100644 index a74cd0c..0000000 --- a/src/PolyTrader.Modules.CopyTrading/Ui/TradeRowPalette.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Drawing; -using PolyTrader.Modules.CopyTrading.Logic; - -namespace PolyTrader.Modules.CopyTrading.Ui -{ - /// - /// WinForms-Farbpalette zu den -Kategorien. Die Schwellenlogik liegt - /// (getestet) in ; hier steht nur noch, wie die Kategorien aussehen. - /// Die Avalonia-UI bekommt später ihre eigene Palette zu denselben Kategorien. - /// - internal static class TradeRowPalette - { - public static readonly Color Loss = Color.FromArgb(245, 200, 200); // rot - public static readonly Color SmallWin = Color.FromArgb(212, 240, 212); // hellgrün - public static readonly Color BigWin = Color.FromArgb(140, 214, 140); // grün - - public static Color For(TradeRowTint tint) => tint switch - { - TradeRowTint.Loss => Loss, - TradeRowTint.BigWin => BigWin, - _ => SmallWin - }; - - /// Bequemlichkeit für die Grids: PnL-Prozent direkt in die Zeilenfarbe. - public static Color ForPnlPercent(decimal pnlPercent) => For(TradeRowColoring.ForPnlPercent(pnlPercent)); - } -} diff --git a/src/PolyTrader.Modules.ResolutionFarming/PolyTrader.Modules.ResolutionFarming.csproj b/src/PolyTrader.Modules.ResolutionFarming/PolyTrader.Modules.ResolutionFarming.csproj index 152d146..b951b08 100644 --- a/src/PolyTrader.Modules.ResolutionFarming/PolyTrader.Modules.ResolutionFarming.csproj +++ b/src/PolyTrader.Modules.ResolutionFarming/PolyTrader.Modules.ResolutionFarming.csproj @@ -1,4 +1,4 @@ - + @@ -20,11 +20,12 @@ - net8.0-windows + + net8.0 enable enable - - true diff --git a/src/PolyTrader.Modules.ResolutionFarming/ResolutionFarmingModule.cs b/src/PolyTrader.Modules.ResolutionFarming/ResolutionFarmingModule.cs index 9c69e3b..bf3a2fe 100644 --- a/src/PolyTrader.Modules.ResolutionFarming/ResolutionFarmingModule.cs +++ b/src/PolyTrader.Modules.ResolutionFarming/ResolutionFarmingModule.cs @@ -54,22 +54,22 @@ namespace PolyTrader.Modules.ResolutionFarming // Live-Marktquelle, Live-Execution, On-Chain-Auto-Redeem und Kalibrierung folgen (Zielland). } - public void RegisterUi(IModuleUiHost host, System.IServiceProvider services) + /// + /// Aktuell ohne Ansicht: Die WinForms-UI wurde mit der Linux-Portierung entfernt, die + /// Avalonia-Ansicht folgt (Stufe L3/L4). Die Fachlogik dieses Moduls laeuft davon + /// unabhaengig weiter – die Shell zeigt schlicht kein Fenster fuer das Modul an. + /// + /// Beim Nachbau zu erhalten (Spezifikation: docs/UI-SPEZIFIKATION-WinForms.md, + /// Originalcode: Git-Tag winforms-final): + /// + /// View-ID resolutionfarming.main (stabil – Launcher-Button und Symbol haengen daran) + /// Titel ResolutionFarming, Gruppe ResolutionFarming, Order 200 + /// Ein Fenster fuers ganze Modul: ResolutionFarmingMainForm mit Tabs: Kandidaten / Positionen / Historie+Statistik / Settings + /// + /// + public void RegisterUi(IModuleUiHost host, IServiceProvider services) { - // EIN Fenster fürs ganze Modul (Tabs: Kandidaten/Positionen/Historie/Settings). - host.RegisterView(new ModuleView - { - Id = "resolutionfarming.main", - Title = "ResolutionFarming", - Group = "ResolutionFarming", - Order = 200, - CreateView = () => - { - var form = new Ui.ResolutionFarmingMainForm(); - form.Initialize(services); - return form; - } - }); + // Bewusst leer, bis die Avalonia-Ansicht steht (siehe Doku oben). } public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; diff --git a/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.Designer.cs b/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.Designer.cs deleted file mode 100644 index 8542cde..0000000 --- a/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.Designer.cs +++ /dev/null @@ -1,379 +0,0 @@ -namespace PolyTrader.Modules.ResolutionFarming.Ui -{ - partial class ResolutionFarmingMainForm - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ResolutionFarmingMainForm)); - tabControlRf = new TabControl(); - tabKandidaten = new TabPage(); - dgvCandidates = new DataGridView(); - pnlCandTop = new Panel(); - btnCandRefresh = new Button(); - cbCandAccount = new ComboBox(); - lblCandKonto = new Label(); - tabPositionen = new TabPage(); - dgvPositions = new DataGridView(); - pnlPosTop = new Panel(); - btnPosRefresh = new Button(); - tabHistorie = new TabPage(); - dgvHistory = new DataGridView(); - lblHistSummary = new Label(); - pnlHistTop = new Panel(); - btnHistRefresh = new Button(); - tabSettings = new TabPage(); - pgSettings = new PropertyGrid(); - pnlSetTop = new Panel(); - btnSettingsSave = new Button(); - cbSettingsAccount = new ComboBox(); - lblSetKonto = new Label(); - lblRfStatus = new Label(); - tabControlRf.SuspendLayout(); - tabKandidaten.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvCandidates).BeginInit(); - pnlCandTop.SuspendLayout(); - tabPositionen.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvPositions).BeginInit(); - pnlPosTop.SuspendLayout(); - tabHistorie.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvHistory).BeginInit(); - pnlHistTop.SuspendLayout(); - tabSettings.SuspendLayout(); - pnlSetTop.SuspendLayout(); - SuspendLayout(); - // - // tabControlRf - // - tabControlRf.Controls.Add(tabKandidaten); - tabControlRf.Controls.Add(tabPositionen); - tabControlRf.Controls.Add(tabHistorie); - tabControlRf.Controls.Add(tabSettings); - tabControlRf.Dock = DockStyle.Fill; - tabControlRf.Location = new Point(0, 0); - tabControlRf.Margin = new Padding(4, 5, 4, 5); - tabControlRf.Name = "tabControlRf"; - tabControlRf.SelectedIndex = 0; - tabControlRf.Size = new Size(1429, 993); - tabControlRf.TabIndex = 0; - // - // tabKandidaten - // - tabKandidaten.Controls.Add(dgvCandidates); - tabKandidaten.Controls.Add(pnlCandTop); - tabKandidaten.Location = new Point(4, 34); - tabKandidaten.Margin = new Padding(4, 5, 4, 5); - tabKandidaten.Name = "tabKandidaten"; - tabKandidaten.Padding = new Padding(4, 5, 4, 5); - tabKandidaten.Size = new Size(1421, 955); - tabKandidaten.TabIndex = 0; - tabKandidaten.Text = "Kandidaten"; - tabKandidaten.UseVisualStyleBackColor = true; - // - // dgvCandidates - // - dgvCandidates.AllowUserToAddRows = false; - dgvCandidates.AllowUserToDeleteRows = false; - dgvCandidates.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvCandidates.Dock = DockStyle.Fill; - dgvCandidates.Location = new Point(4, 62); - dgvCandidates.Margin = new Padding(4, 5, 4, 5); - dgvCandidates.Name = "dgvCandidates"; - dgvCandidates.ReadOnly = true; - dgvCandidates.RowHeadersVisible = false; - dgvCandidates.RowHeadersWidth = 62; - dgvCandidates.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvCandidates.Size = new Size(1413, 888); - dgvCandidates.TabIndex = 1; - // - // pnlCandTop - // - pnlCandTop.Controls.Add(btnCandRefresh); - pnlCandTop.Controls.Add(cbCandAccount); - pnlCandTop.Controls.Add(lblCandKonto); - pnlCandTop.Dock = DockStyle.Top; - pnlCandTop.Location = new Point(4, 5); - pnlCandTop.Margin = new Padding(4, 5, 4, 5); - pnlCandTop.Name = "pnlCandTop"; - pnlCandTop.Size = new Size(1413, 57); - pnlCandTop.TabIndex = 0; - // - // btnCandRefresh - // - btnCandRefresh.Location = new Point(464, 7); - btnCandRefresh.Margin = new Padding(4, 5, 4, 5); - btnCandRefresh.Name = "btnCandRefresh"; - btnCandRefresh.Size = new Size(157, 43); - btnCandRefresh.TabIndex = 2; - btnCandRefresh.Text = "Aktualisieren"; - btnCandRefresh.UseVisualStyleBackColor = true; - // - // cbCandAccount - // - cbCandAccount.DropDownStyle = ComboBoxStyle.DropDownList; - cbCandAccount.Location = new Point(79, 8); - cbCandAccount.Margin = new Padding(4, 5, 4, 5); - cbCandAccount.Name = "cbCandAccount"; - cbCandAccount.Size = new Size(370, 33); - cbCandAccount.TabIndex = 1; - // - // lblCandKonto - // - lblCandKonto.AutoSize = true; - lblCandKonto.Location = new Point(9, 15); - lblCandKonto.Margin = new Padding(4, 0, 4, 0); - lblCandKonto.Name = "lblCandKonto"; - lblCandKonto.Size = new Size(64, 25); - lblCandKonto.TabIndex = 0; - lblCandKonto.Text = "Konto:"; - // - // tabPositionen - // - tabPositionen.Controls.Add(dgvPositions); - tabPositionen.Controls.Add(pnlPosTop); - tabPositionen.Location = new Point(4, 34); - tabPositionen.Margin = new Padding(4, 5, 4, 5); - tabPositionen.Name = "tabPositionen"; - tabPositionen.Padding = new Padding(4, 5, 4, 5); - tabPositionen.Size = new Size(1421, 955); - tabPositionen.TabIndex = 1; - tabPositionen.Text = "Positionen"; - tabPositionen.UseVisualStyleBackColor = true; - // - // dgvPositions - // - dgvPositions.AllowUserToAddRows = false; - dgvPositions.AllowUserToDeleteRows = false; - dgvPositions.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvPositions.Dock = DockStyle.Fill; - dgvPositions.Location = new Point(4, 62); - dgvPositions.Margin = new Padding(4, 5, 4, 5); - dgvPositions.Name = "dgvPositions"; - dgvPositions.ReadOnly = true; - dgvPositions.RowHeadersVisible = false; - dgvPositions.RowHeadersWidth = 62; - dgvPositions.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvPositions.Size = new Size(1413, 888); - dgvPositions.TabIndex = 1; - // - // pnlPosTop - // - pnlPosTop.Controls.Add(btnPosRefresh); - pnlPosTop.Dock = DockStyle.Top; - pnlPosTop.Location = new Point(4, 5); - pnlPosTop.Margin = new Padding(4, 5, 4, 5); - pnlPosTop.Name = "pnlPosTop"; - pnlPosTop.Size = new Size(1413, 57); - pnlPosTop.TabIndex = 0; - // - // btnPosRefresh - // - btnPosRefresh.Location = new Point(9, 7); - btnPosRefresh.Margin = new Padding(4, 5, 4, 5); - btnPosRefresh.Name = "btnPosRefresh"; - btnPosRefresh.Size = new Size(157, 43); - btnPosRefresh.TabIndex = 0; - btnPosRefresh.Text = "Aktualisieren"; - btnPosRefresh.UseVisualStyleBackColor = true; - // - // tabHistorie - // - tabHistorie.Controls.Add(dgvHistory); - tabHistorie.Controls.Add(lblHistSummary); - tabHistorie.Controls.Add(pnlHistTop); - tabHistorie.Location = new Point(4, 34); - tabHistorie.Margin = new Padding(4, 5, 4, 5); - tabHistorie.Name = "tabHistorie"; - tabHistorie.Padding = new Padding(4, 5, 4, 5); - tabHistorie.Size = new Size(1421, 955); - tabHistorie.TabIndex = 2; - tabHistorie.Text = "Historie / Statistik"; - tabHistorie.UseVisualStyleBackColor = true; - // - // dgvHistory - // - dgvHistory.AllowUserToAddRows = false; - dgvHistory.AllowUserToDeleteRows = false; - dgvHistory.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvHistory.Dock = DockStyle.Fill; - dgvHistory.Location = new Point(4, 142); - dgvHistory.Margin = new Padding(4, 5, 4, 5); - dgvHistory.Name = "dgvHistory"; - dgvHistory.ReadOnly = true; - dgvHistory.RowHeadersVisible = false; - dgvHistory.RowHeadersWidth = 62; - dgvHistory.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvHistory.Size = new Size(1413, 808); - dgvHistory.TabIndex = 2; - // - // lblHistSummary - // - lblHistSummary.Dock = DockStyle.Top; - lblHistSummary.Location = new Point(4, 62); - lblHistSummary.Margin = new Padding(4, 0, 4, 0); - lblHistSummary.Name = "lblHistSummary"; - lblHistSummary.Padding = new Padding(9, 10, 9, 10); - lblHistSummary.Size = new Size(1413, 80); - lblHistSummary.TabIndex = 1; - // - // pnlHistTop - // - pnlHistTop.Controls.Add(btnHistRefresh); - pnlHistTop.Dock = DockStyle.Top; - pnlHistTop.Location = new Point(4, 5); - pnlHistTop.Margin = new Padding(4, 5, 4, 5); - pnlHistTop.Name = "pnlHistTop"; - pnlHistTop.Size = new Size(1413, 57); - pnlHistTop.TabIndex = 0; - // - // btnHistRefresh - // - btnHistRefresh.Location = new Point(9, 7); - btnHistRefresh.Margin = new Padding(4, 5, 4, 5); - btnHistRefresh.Name = "btnHistRefresh"; - btnHistRefresh.Size = new Size(157, 43); - btnHistRefresh.TabIndex = 0; - btnHistRefresh.Text = "Aktualisieren"; - btnHistRefresh.UseVisualStyleBackColor = true; - // - // tabSettings - // - tabSettings.Controls.Add(pgSettings); - tabSettings.Controls.Add(pnlSetTop); - tabSettings.Location = new Point(4, 34); - tabSettings.Margin = new Padding(4, 5, 4, 5); - tabSettings.Name = "tabSettings"; - tabSettings.Padding = new Padding(4, 5, 4, 5); - tabSettings.Size = new Size(1421, 955); - tabSettings.TabIndex = 3; - tabSettings.Text = "Settings"; - tabSettings.UseVisualStyleBackColor = true; - // - // pgSettings - // - pgSettings.Dock = DockStyle.Fill; - pgSettings.Location = new Point(4, 62); - pgSettings.Margin = new Padding(4, 5, 4, 5); - pgSettings.Name = "pgSettings"; - pgSettings.Size = new Size(1413, 888); - pgSettings.TabIndex = 1; - // - // pnlSetTop - // - pnlSetTop.Controls.Add(btnSettingsSave); - pnlSetTop.Controls.Add(cbSettingsAccount); - pnlSetTop.Controls.Add(lblSetKonto); - pnlSetTop.Dock = DockStyle.Top; - pnlSetTop.Location = new Point(4, 5); - pnlSetTop.Margin = new Padding(4, 5, 4, 5); - pnlSetTop.Name = "pnlSetTop"; - pnlSetTop.Size = new Size(1413, 57); - pnlSetTop.TabIndex = 0; - // - // btnSettingsSave - // - btnSettingsSave.Location = new Point(464, 7); - btnSettingsSave.Margin = new Padding(4, 5, 4, 5); - btnSettingsSave.Name = "btnSettingsSave"; - btnSettingsSave.Size = new Size(157, 43); - btnSettingsSave.TabIndex = 2; - btnSettingsSave.Text = "Speichern"; - btnSettingsSave.UseVisualStyleBackColor = true; - // - // cbSettingsAccount - // - cbSettingsAccount.DropDownStyle = ComboBoxStyle.DropDownList; - cbSettingsAccount.Location = new Point(79, 8); - cbSettingsAccount.Margin = new Padding(4, 5, 4, 5); - cbSettingsAccount.Name = "cbSettingsAccount"; - cbSettingsAccount.Size = new Size(370, 33); - cbSettingsAccount.TabIndex = 1; - // - // lblSetKonto - // - lblSetKonto.AutoSize = true; - lblSetKonto.Location = new Point(9, 15); - lblSetKonto.Margin = new Padding(4, 0, 4, 0); - lblSetKonto.Name = "lblSetKonto"; - lblSetKonto.Size = new Size(64, 25); - lblSetKonto.TabIndex = 0; - lblSetKonto.Text = "Konto:"; - // - // lblRfStatus - // - lblRfStatus.Dock = DockStyle.Bottom; - lblRfStatus.Location = new Point(0, 993); - lblRfStatus.Margin = new Padding(4, 0, 4, 0); - lblRfStatus.Name = "lblRfStatus"; - lblRfStatus.Padding = new Padding(9, 3, 9, 3); - lblRfStatus.Size = new Size(1429, 37); - lblRfStatus.TabIndex = 1; - // - // ResolutionFarmingMainForm - // - AutoScaleDimensions = new SizeF(10F, 25F); - AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1429, 1030); - Controls.Add(tabControlRf); - Controls.Add(lblRfStatus); - Icon = (Icon)resources.GetObject("$this.Icon"); - Margin = new Padding(4, 5, 4, 5); - Name = "ResolutionFarmingMainForm"; - StartPosition = FormStartPosition.CenterScreen; - Text = "ResolutionFarming"; - tabControlRf.ResumeLayout(false); - tabKandidaten.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)dgvCandidates).EndInit(); - pnlCandTop.ResumeLayout(false); - pnlCandTop.PerformLayout(); - tabPositionen.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)dgvPositions).EndInit(); - pnlPosTop.ResumeLayout(false); - tabHistorie.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)dgvHistory).EndInit(); - pnlHistTop.ResumeLayout(false); - tabSettings.ResumeLayout(false); - pnlSetTop.ResumeLayout(false); - pnlSetTop.PerformLayout(); - ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.TabControl tabControlRf; - private System.Windows.Forms.TabPage tabKandidaten; - private System.Windows.Forms.Panel pnlCandTop; - private System.Windows.Forms.Label lblCandKonto; - private System.Windows.Forms.ComboBox cbCandAccount; - private System.Windows.Forms.Button btnCandRefresh; - private System.Windows.Forms.DataGridView dgvCandidates; - private System.Windows.Forms.TabPage tabPositionen; - private System.Windows.Forms.Panel pnlPosTop; - private System.Windows.Forms.Button btnPosRefresh; - private System.Windows.Forms.DataGridView dgvPositions; - private System.Windows.Forms.TabPage tabHistorie; - private System.Windows.Forms.Panel pnlHistTop; - private System.Windows.Forms.Button btnHistRefresh; - private System.Windows.Forms.Label lblHistSummary; - private System.Windows.Forms.DataGridView dgvHistory; - private System.Windows.Forms.TabPage tabSettings; - private System.Windows.Forms.Panel pnlSetTop; - private System.Windows.Forms.Label lblSetKonto; - private System.Windows.Forms.ComboBox cbSettingsAccount; - private System.Windows.Forms.Button btnSettingsSave; - private System.Windows.Forms.PropertyGrid pgSettings; - private System.Windows.Forms.Label lblRfStatus; - } -} diff --git a/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.cs b/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.cs deleted file mode 100644 index b00f36f..0000000 --- a/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System; -using System.Linq; -using System.Windows.Forms; -using Microsoft.Extensions.DependencyInjection; -using PolyTrader.Modules.ResolutionFarming.Models; -using PolyTrader.Modules.ResolutionFarming.Persistence; -using PolyTraderSharp; - -namespace PolyTrader.Modules.ResolutionFarming.Ui -{ - /// - /// Hauptfenster des ResolutionFarming-Moduls: Tabs Kandidaten, Positionen, Historie/Statistik, - /// Settings. Layout im Designer (ResolutionFarmingMainForm.Designer.cs), Verhalten/Daten hier. - /// DB-Zugriffe defensiv (Guarded), damit die UI auch ohne angewendete rf_-Migration bedienbar bleibt. - /// - public partial class ResolutionFarmingMainForm : Form - { - private IRfCandidateRepository? _candidates; - private IRfPositionRepository? _positions; - private IRfClosedTradeRepository? _closed; - private IRfSettingsRepository? _settingsRepo; - private TradingState? _state; - - private RfSettings? _currentSettings; - - public ResolutionFarmingMainForm() - { - InitializeComponent(); - - btnCandRefresh.Click += (_, _) => RefreshCandidates(); - cbCandAccount.SelectedIndexChanged += (_, _) => RefreshCandidates(); - btnPosRefresh.Click += (_, _) => RefreshPositions(); - btnHistRefresh.Click += (_, _) => RefreshHistory(); - btnSettingsSave.Click += (_, _) => SaveSettings(); - cbSettingsAccount.SelectedIndexChanged += (_, _) => LoadSettings(); - } - - /// Injiziert Repos/State (nach DI-Auflösung) und lädt die Ansichten. - public void Initialize(IServiceProvider services) - { - _candidates = services.GetRequiredService(); - _positions = services.GetRequiredService(); - _closed = services.GetRequiredService(); - _settingsRepo = services.GetRequiredService(); - _state = services.GetRequiredService(); - - PopulateAccounts(); - RefreshCandidates(); - RefreshPositions(); - RefreshHistory(); - } - - // ---------------- Daten ---------------- - - private void PopulateAccounts() - { - if (_state == null) return; - var items = _state.Accounts.Values - .OrderBy(a => a.AccountId) - .Select(a => new AccountItem(a.AccountId, string.IsNullOrEmpty(a.Name) ? $"#{a.AccountId}" : $"{a.Name} (#{a.AccountId}){(a.IsDemo ? " · Demo" : "")}")) - .ToList(); - - foreach (var combo in new[] { cbCandAccount, cbSettingsAccount }) - { - combo.DisplayMember = nameof(AccountItem.Label); - combo.ValueMember = nameof(AccountItem.Id); - combo.DataSource = items.ToList(); - } - - if (items.Count > 0) LoadSettings(); - else SetStatus("Keine Accounts vorhanden."); - } - - private int? SelectedAccountId(ComboBox combo) => - combo.SelectedItem is AccountItem it ? it.Id : (int?)null; - - private void RefreshCandidates() - { - if (_candidates == null || SelectedAccountId(cbCandAccount) is not int accId) return; - Guarded("Kandidaten", () => dgvCandidates.DataSource = _candidates.GetRecent(accId, 200)); - } - - private void RefreshPositions() - { - if (_positions == null) return; - Guarded("Positionen", () => dgvPositions.DataSource = _positions.GetAllOpen()); - } - - private void RefreshHistory() - { - if (_closed == null) return; - Guarded("Historie", () => - { - var trades = _closed.Find(_ => true); - dgvHistory.DataSource = trades; - lblHistSummary.Text = BuildSummary(trades); - }); - } - - private static string BuildSummary(System.Collections.Generic.List trades) - { - if (trades.Count == 0) return "Noch keine abgeschlossenen Trades."; - int wins = trades.Count(t => t.RealizedPnl > 0m); - decimal pnl = trades.Sum(t => t.RealizedPnl); - decimal fees = trades.Sum(t => t.TotalFees); - double winrate = 100.0 * wins / trades.Count; - // Winrate je Preisband (Kalibrierung: realisierte Winrate sollte > Band-Mitte liegen). - var bands = trades - .GroupBy(t => $"{Math.Floor(t.EntryPrice * 20m) / 20m:F2}") // 5-¢-Bänder - .OrderBy(g => g.Key) - .Select(g => $"{g.Key}: {100.0 * g.Count(x => x.RealizedPnl > 0m) / g.Count():F0}% ({g.Count()})"); - return $"Trades: {trades.Count} | Winrate: {winrate:F1}% | Netto-PnL: {pnl:F2} USDC | Fees: {fees:F2}\n" + - $"Winrate je Preisband: {string.Join(" | ", bands)}"; - } - - private void LoadSettings() - { - if (_settingsRepo == null || SelectedAccountId(cbSettingsAccount) is not int accId) return; - Guarded("Settings", () => - { - _currentSettings = _settingsRepo.Get(accId) ?? new RfSettings { AccountId = accId }; - pgSettings.SelectedObject = _currentSettings; - SetStatus($"Einstellungen für Konto #{accId}."); - }); - } - - private void SaveSettings() - { - if (_settingsRepo == null || _currentSettings == null) return; - Guarded("Speichern", () => - { - _settingsRepo.Upsert(_currentSettings); - SetStatus($"Gespeichert für Konto #{_currentSettings.AccountId} um {DateTime.Now:HH:mm:ss}."); - }); - } - - private void Guarded(string what, Action action) - { - try { action(); } - catch (Exception ex) { SetStatus($"{what}: DB nicht bereit ({ex.Message}). Migration angewendet?"); } - } - - private void SetStatus(string text) => lblRfStatus.Text = text; - - private sealed record AccountItem(int Id, string Label); - } -} diff --git a/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.resx b/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.resx deleted file mode 100644 index 3fd6970..0000000 --- a/src/PolyTrader.Modules.ResolutionFarming/Ui/ResolutionFarmingMainForm.resx +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - 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 - RK5CYII= - - - \ No newline at end of file diff --git a/src/PolyTrader.Modules.Supervisor/PolyTrader.Modules.Supervisor.csproj b/src/PolyTrader.Modules.Supervisor/PolyTrader.Modules.Supervisor.csproj index c08ebcf..7281d6f 100644 --- a/src/PolyTrader.Modules.Supervisor/PolyTrader.Modules.Supervisor.csproj +++ b/src/PolyTrader.Modules.Supervisor/PolyTrader.Modules.Supervisor.csproj @@ -1,4 +1,4 @@ - + @@ -25,11 +25,12 @@ - net8.0-windows + + net8.0 enable enable - - true diff --git a/src/PolyTrader.Modules.Supervisor/SupervisorModule.cs b/src/PolyTrader.Modules.Supervisor/SupervisorModule.cs index d86408e..d299257 100644 --- a/src/PolyTrader.Modules.Supervisor/SupervisorModule.cs +++ b/src/PolyTrader.Modules.Supervisor/SupervisorModule.cs @@ -54,21 +54,22 @@ namespace PolyTrader.Modules.Supervisor services.AddHostedService(); } - public void RegisterUi(IModuleUiHost host, System.IServiceProvider services) + /// + /// Aktuell ohne Ansicht: Die WinForms-UI wurde mit der Linux-Portierung entfernt, die + /// Avalonia-Ansicht folgt (Stufe L3/L4). Die Fachlogik dieses Moduls laeuft davon + /// unabhaengig weiter – die Shell zeigt schlicht kein Fenster fuer das Modul an. + /// + /// Beim Nachbau zu erhalten (Spezifikation: docs/UI-SPEZIFIKATION-WinForms.md, + /// Originalcode: Git-Tag winforms-final): + /// + /// View-ID supervisor.main (stabil – Launcher-Button und Symbol haengen daran) + /// Titel Supervisor, Gruppe Supervisor, Order 300 + /// Ein Fenster fuers ganze Modul: SupervisorMainForm mit Tabs: Analyse (Chat) / Dossiers / Berichte / Counterfactual + /// + /// + public void RegisterUi(IModuleUiHost host, IServiceProvider services) { - host.RegisterView(new ModuleView - { - Id = "supervisor.main", - Title = "Supervisor", - Group = "Supervisor", - Order = 300, - CreateView = () => - { - var form = new Ui.SupervisorMainForm(); - form.Initialize(services); - return form; - } - }); + // Bewusst leer, bis die Avalonia-Ansicht steht (siehe Doku oben). } public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; diff --git a/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.Designer.cs b/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.Designer.cs deleted file mode 100644 index 3281ae1..0000000 --- a/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.Designer.cs +++ /dev/null @@ -1,524 +0,0 @@ -namespace PolyTrader.Modules.Supervisor.Ui -{ - partial class SupervisorMainForm - { - private System.ComponentModel.IContainer components = null; - - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Vom Komponenten-Designer generierter Code - - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SupervisorMainForm)); - tabControlSup = new TabControl(); - tabAnalyse = new TabPage(); - rtbChat = new RichTextBox(); - pnlChatInput = new Panel(); - tbChatInput = new TextBox(); - btnSend = new Button(); - toolStripChat = new ToolStrip(); - lblProfil = new ToolStripLabel(); - cbProfile = new ToolStripComboBox(); - lblModel = new ToolStripLabel(); - tbModel = new ToolStripTextBox(); - sepChat = new ToolStripSeparator(); - btnClearChat = new ToolStripButton(); - tabDossiers = new TabPage(); - splitDossiers = new SplitContainer(); - dgvSignals = new DataGridView(); - tbDossier = new TextBox(); - toolStripDossier = new ToolStrip(); - btnDossierRefresh = new ToolStripButton(); - sepDossier = new ToolStripSeparator(); - lblSignal = new ToolStripLabel(); - tbSignalId = new ToolStripTextBox(); - btnDossierOpen = new ToolStripButton(); - tabBerichte = new TabPage(); - splitReports = new SplitContainer(); - dgvReports = new DataGridView(); - tbReport = new TextBox(); - toolStripReports = new ToolStrip(); - btnReportsRefresh = new ToolStripButton(); - tabCounterfactual = new TabPage(); - dgvCounterfactuals = new DataGridView(); - toolStripCf = new ToolStrip(); - btnCfRefresh = new ToolStripButton(); - lblStatus = new Label(); - tabControlSup.SuspendLayout(); - tabAnalyse.SuspendLayout(); - pnlChatInput.SuspendLayout(); - toolStripChat.SuspendLayout(); - tabDossiers.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)splitDossiers).BeginInit(); - splitDossiers.Panel1.SuspendLayout(); - splitDossiers.Panel2.SuspendLayout(); - splitDossiers.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvSignals).BeginInit(); - toolStripDossier.SuspendLayout(); - tabBerichte.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)splitReports).BeginInit(); - splitReports.Panel1.SuspendLayout(); - splitReports.Panel2.SuspendLayout(); - splitReports.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvReports).BeginInit(); - toolStripReports.SuspendLayout(); - tabCounterfactual.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)dgvCounterfactuals).BeginInit(); - toolStripCf.SuspendLayout(); - SuspendLayout(); - // - // tabControlSup - // - tabControlSup.Controls.Add(tabAnalyse); - tabControlSup.Controls.Add(tabDossiers); - tabControlSup.Controls.Add(tabBerichte); - tabControlSup.Controls.Add(tabCounterfactual); - tabControlSup.Dock = DockStyle.Fill; - tabControlSup.Location = new Point(0, 0); - tabControlSup.Margin = new Padding(4, 5, 4, 5); - tabControlSup.Name = "tabControlSup"; - tabControlSup.SelectedIndex = 0; - tabControlSup.Size = new Size(1786, 1126); - tabControlSup.TabIndex = 0; - // - // tabAnalyse - // - tabAnalyse.Controls.Add(rtbChat); - tabAnalyse.Controls.Add(pnlChatInput); - tabAnalyse.Controls.Add(toolStripChat); - tabAnalyse.Location = new Point(4, 34); - tabAnalyse.Margin = new Padding(4, 5, 4, 5); - tabAnalyse.Name = "tabAnalyse"; - tabAnalyse.Padding = new Padding(4, 5, 4, 5); - tabAnalyse.Size = new Size(1778, 1088); - tabAnalyse.TabIndex = 0; - tabAnalyse.Text = "Analyse"; - tabAnalyse.UseVisualStyleBackColor = true; - // - // rtbChat - // - rtbChat.BackColor = Color.White; - rtbChat.Dock = DockStyle.Fill; - rtbChat.Font = new Font("Segoe UI", 9.5F); - rtbChat.Location = new Point(4, 39); - rtbChat.Margin = new Padding(4, 5, 4, 5); - rtbChat.Name = "rtbChat"; - rtbChat.ReadOnly = true; - rtbChat.Size = new Size(1770, 944); - rtbChat.TabIndex = 1; - rtbChat.Text = ""; - // - // pnlChatInput - // - pnlChatInput.Controls.Add(tbChatInput); - pnlChatInput.Controls.Add(btnSend); - pnlChatInput.Dock = DockStyle.Bottom; - pnlChatInput.Location = new Point(4, 983); - pnlChatInput.Margin = new Padding(4, 5, 4, 5); - pnlChatInput.Name = "pnlChatInput"; - pnlChatInput.Padding = new Padding(6, 7, 6, 7); - pnlChatInput.Size = new Size(1770, 100); - pnlChatInput.TabIndex = 2; - // - // tbChatInput - // - tbChatInput.Dock = DockStyle.Fill; - tbChatInput.Location = new Point(6, 7); - tbChatInput.Margin = new Padding(4, 5, 4, 5); - tbChatInput.Multiline = true; - tbChatInput.Name = "tbChatInput"; - tbChatInput.PlaceholderText = "Analyse-Frage stellen … (Strg+Enter zum Senden)"; - tbChatInput.Size = new Size(1601, 86); - tbChatInput.TabIndex = 0; - // - // btnSend - // - btnSend.Dock = DockStyle.Right; - btnSend.Location = new Point(1607, 7); - btnSend.Margin = new Padding(4, 5, 4, 5); - btnSend.Name = "btnSend"; - btnSend.Size = new Size(157, 86); - btnSend.TabIndex = 1; - btnSend.Text = "Senden"; - btnSend.UseVisualStyleBackColor = true; - // - // toolStripChat - // - toolStripChat.ImageScalingSize = new Size(24, 24); - toolStripChat.Items.AddRange(new ToolStripItem[] { lblProfil, cbProfile, lblModel, tbModel, sepChat, btnClearChat }); - toolStripChat.Location = new Point(4, 5); - toolStripChat.Name = "toolStripChat"; - toolStripChat.Padding = new Padding(0, 0, 3, 0); - toolStripChat.Size = new Size(1770, 34); - toolStripChat.TabIndex = 0; - // - // lblProfil - // - lblProfil.Name = "lblProfil"; - lblProfil.Size = new Size(57, 29); - lblProfil.Text = "Profil:"; - // - // cbProfile - // - cbProfile.DropDownStyle = ComboBoxStyle.DropDownList; - cbProfile.Name = "cbProfile"; - cbProfile.Size = new Size(227, 34); - // - // lblModel - // - lblModel.Name = "lblModel"; - lblModel.Size = new Size(71, 29); - lblModel.Text = "Modell:"; - // - // tbModel - // - tbModel.AutoSize = false; - tbModel.Name = "tbModel"; - tbModel.Size = new Size(313, 31); - tbModel.Text = "openrouter/auto"; - // - // sepChat - // - sepChat.Name = "sepChat"; - sepChat.Size = new Size(6, 34); - // - // btnClearChat - // - btnClearChat.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnClearChat.Name = "btnClearChat"; - btnClearChat.Size = new Size(122, 29); - btnClearChat.Text = "Verlauf leeren"; - // - // tabDossiers - // - tabDossiers.Controls.Add(splitDossiers); - tabDossiers.Controls.Add(toolStripDossier); - tabDossiers.Location = new Point(4, 34); - tabDossiers.Margin = new Padding(4, 5, 4, 5); - tabDossiers.Name = "tabDossiers"; - tabDossiers.Padding = new Padding(4, 5, 4, 5); - tabDossiers.Size = new Size(1778, 1088); - tabDossiers.TabIndex = 1; - tabDossiers.Text = "Dossiers"; - tabDossiers.UseVisualStyleBackColor = true; - // - // splitDossiers - // - splitDossiers.Dock = DockStyle.Fill; - splitDossiers.Location = new Point(4, 39); - splitDossiers.Margin = new Padding(4, 5, 4, 5); - splitDossiers.Name = "splitDossiers"; - // - // splitDossiers.Panel1 - // - splitDossiers.Panel1.Controls.Add(dgvSignals); - // - // splitDossiers.Panel2 - // - splitDossiers.Panel2.Controls.Add(tbDossier); - splitDossiers.Size = new Size(1770, 1044); - splitDossiers.SplitterDistance = 601; - splitDossiers.SplitterWidth = 6; - splitDossiers.TabIndex = 1; - // - // dgvSignals - // - dgvSignals.AllowUserToAddRows = false; - dgvSignals.AllowUserToDeleteRows = false; - dgvSignals.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvSignals.Dock = DockStyle.Fill; - dgvSignals.Location = new Point(0, 0); - dgvSignals.Margin = new Padding(4, 5, 4, 5); - dgvSignals.MultiSelect = false; - dgvSignals.Name = "dgvSignals"; - dgvSignals.ReadOnly = true; - dgvSignals.RowHeadersVisible = false; - dgvSignals.RowHeadersWidth = 62; - dgvSignals.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvSignals.Size = new Size(601, 1044); - dgvSignals.TabIndex = 0; - // - // tbDossier - // - tbDossier.Dock = DockStyle.Fill; - tbDossier.Font = new Font("Consolas", 9.5F); - tbDossier.Location = new Point(0, 0); - tbDossier.Margin = new Padding(4, 5, 4, 5); - tbDossier.Multiline = true; - tbDossier.Name = "tbDossier"; - tbDossier.ReadOnly = true; - tbDossier.ScrollBars = ScrollBars.Both; - tbDossier.Size = new Size(1163, 1044); - tbDossier.TabIndex = 0; - tbDossier.WordWrap = false; - // - // toolStripDossier - // - toolStripDossier.ImageScalingSize = new Size(24, 24); - toolStripDossier.Items.AddRange(new ToolStripItem[] { btnDossierRefresh, sepDossier, lblSignal, tbSignalId, btnDossierOpen }); - toolStripDossier.Location = new Point(4, 5); - toolStripDossier.Name = "toolStripDossier"; - toolStripDossier.Padding = new Padding(0, 0, 3, 0); - toolStripDossier.Size = new Size(1770, 34); - toolStripDossier.TabIndex = 0; - // - // btnDossierRefresh - // - btnDossierRefresh.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnDossierRefresh.Name = "btnDossierRefresh"; - btnDossierRefresh.Size = new Size(116, 29); - btnDossierRefresh.Text = "Aktualisieren"; - // - // sepDossier - // - sepDossier.Name = "sepDossier"; - sepDossier.Size = new Size(6, 34); - // - // lblSignal - // - lblSignal.Name = "lblSignal"; - lblSignal.Size = new Size(80, 29); - lblSignal.Text = "SignalId:"; - // - // tbSignalId - // - tbSignalId.AutoSize = false; - tbSignalId.Name = "tbSignalId"; - tbSignalId.Size = new Size(313, 31); - // - // btnDossierOpen - // - btnDossierOpen.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnDossierOpen.Name = "btnDossierOpen"; - btnDossierOpen.Size = new Size(132, 29); - btnDossierOpen.Text = "Dossier öffnen"; - // - // tabBerichte - // - tabBerichte.Controls.Add(splitReports); - tabBerichte.Controls.Add(toolStripReports); - tabBerichte.Location = new Point(4, 34); - tabBerichte.Margin = new Padding(4, 5, 4, 5); - tabBerichte.Name = "tabBerichte"; - tabBerichte.Padding = new Padding(4, 5, 4, 5); - tabBerichte.Size = new Size(1778, 1089); - tabBerichte.TabIndex = 2; - tabBerichte.Text = "Berichte"; - tabBerichte.UseVisualStyleBackColor = true; - // - // splitReports - // - splitReports.Dock = DockStyle.Fill; - splitReports.Location = new Point(4, 39); - splitReports.Margin = new Padding(4, 5, 4, 5); - splitReports.Name = "splitReports"; - // - // splitReports.Panel1 - // - splitReports.Panel1.Controls.Add(dgvReports); - // - // splitReports.Panel2 - // - splitReports.Panel2.Controls.Add(tbReport); - splitReports.Size = new Size(1770, 1045); - splitReports.SplitterDistance = 744; - splitReports.SplitterWidth = 6; - splitReports.TabIndex = 1; - // - // dgvReports - // - dgvReports.AllowUserToAddRows = false; - dgvReports.AllowUserToDeleteRows = false; - dgvReports.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvReports.Dock = DockStyle.Fill; - dgvReports.Location = new Point(0, 0); - dgvReports.Margin = new Padding(4, 5, 4, 5); - dgvReports.MultiSelect = false; - dgvReports.Name = "dgvReports"; - dgvReports.ReadOnly = true; - dgvReports.RowHeadersVisible = false; - dgvReports.RowHeadersWidth = 62; - dgvReports.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvReports.Size = new Size(744, 1045); - dgvReports.TabIndex = 0; - // - // tbReport - // - tbReport.Dock = DockStyle.Fill; - tbReport.Font = new Font("Segoe UI", 9.5F); - tbReport.Location = new Point(0, 0); - tbReport.Margin = new Padding(4, 5, 4, 5); - tbReport.Multiline = true; - tbReport.Name = "tbReport"; - tbReport.ReadOnly = true; - tbReport.ScrollBars = ScrollBars.Both; - tbReport.Size = new Size(1020, 1045); - tbReport.TabIndex = 0; - // - // toolStripReports - // - toolStripReports.ImageScalingSize = new Size(24, 24); - toolStripReports.Items.AddRange(new ToolStripItem[] { btnReportsRefresh }); - toolStripReports.Location = new Point(4, 5); - toolStripReports.Name = "toolStripReports"; - toolStripReports.Padding = new Padding(0, 0, 3, 0); - toolStripReports.Size = new Size(1770, 34); - toolStripReports.TabIndex = 0; - // - // btnReportsRefresh - // - btnReportsRefresh.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnReportsRefresh.Name = "btnReportsRefresh"; - btnReportsRefresh.Size = new Size(116, 29); - btnReportsRefresh.Text = "Aktualisieren"; - // - // tabCounterfactual - // - tabCounterfactual.Controls.Add(dgvCounterfactuals); - tabCounterfactual.Controls.Add(toolStripCf); - tabCounterfactual.Location = new Point(4, 34); - tabCounterfactual.Margin = new Padding(4, 5, 4, 5); - tabCounterfactual.Name = "tabCounterfactual"; - tabCounterfactual.Padding = new Padding(4, 5, 4, 5); - tabCounterfactual.Size = new Size(1778, 1089); - tabCounterfactual.TabIndex = 3; - tabCounterfactual.Text = "Counterfactual"; - tabCounterfactual.UseVisualStyleBackColor = true; - // - // dgvCounterfactuals - // - dgvCounterfactuals.AllowUserToAddRows = false; - dgvCounterfactuals.AllowUserToDeleteRows = false; - dgvCounterfactuals.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; - dgvCounterfactuals.Dock = DockStyle.Fill; - dgvCounterfactuals.Location = new Point(4, 39); - dgvCounterfactuals.Margin = new Padding(4, 5, 4, 5); - dgvCounterfactuals.MultiSelect = false; - dgvCounterfactuals.Name = "dgvCounterfactuals"; - dgvCounterfactuals.ReadOnly = true; - dgvCounterfactuals.RowHeadersVisible = false; - dgvCounterfactuals.RowHeadersWidth = 62; - dgvCounterfactuals.SelectionMode = DataGridViewSelectionMode.FullRowSelect; - dgvCounterfactuals.Size = new Size(1770, 1045); - dgvCounterfactuals.TabIndex = 1; - // - // toolStripCf - // - toolStripCf.ImageScalingSize = new Size(24, 24); - toolStripCf.Items.AddRange(new ToolStripItem[] { btnCfRefresh }); - toolStripCf.Location = new Point(4, 5); - toolStripCf.Name = "toolStripCf"; - toolStripCf.Padding = new Padding(0, 0, 3, 0); - toolStripCf.Size = new Size(1770, 34); - toolStripCf.TabIndex = 0; - // - // btnCfRefresh - // - btnCfRefresh.DisplayStyle = ToolStripItemDisplayStyle.Text; - btnCfRefresh.Name = "btnCfRefresh"; - btnCfRefresh.Size = new Size(116, 29); - btnCfRefresh.Text = "Aktualisieren"; - // - // lblStatus - // - lblStatus.Dock = DockStyle.Bottom; - lblStatus.Location = new Point(0, 1126); - lblStatus.Margin = new Padding(4, 0, 4, 0); - lblStatus.Name = "lblStatus"; - lblStatus.Padding = new Padding(9, 3, 9, 3); - lblStatus.Size = new Size(1786, 37); - lblStatus.TabIndex = 1; - // - // SupervisorMainForm - // - AutoScaleDimensions = new SizeF(10F, 25F); - AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(1786, 1163); - Controls.Add(tabControlSup); - Controls.Add(lblStatus); - Icon = (Icon)resources.GetObject("$this.Icon"); - Margin = new Padding(4, 5, 4, 5); - Name = "SupervisorMainForm"; - StartPosition = FormStartPosition.CenterScreen; - Text = "Supervisor"; - tabControlSup.ResumeLayout(false); - tabAnalyse.ResumeLayout(false); - tabAnalyse.PerformLayout(); - pnlChatInput.ResumeLayout(false); - pnlChatInput.PerformLayout(); - toolStripChat.ResumeLayout(false); - toolStripChat.PerformLayout(); - tabDossiers.ResumeLayout(false); - tabDossiers.PerformLayout(); - splitDossiers.Panel1.ResumeLayout(false); - splitDossiers.Panel2.ResumeLayout(false); - splitDossiers.Panel2.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)splitDossiers).EndInit(); - splitDossiers.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)dgvSignals).EndInit(); - toolStripDossier.ResumeLayout(false); - toolStripDossier.PerformLayout(); - tabBerichte.ResumeLayout(false); - tabBerichte.PerformLayout(); - splitReports.Panel1.ResumeLayout(false); - splitReports.Panel2.ResumeLayout(false); - splitReports.Panel2.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)splitReports).EndInit(); - splitReports.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)dgvReports).EndInit(); - toolStripReports.ResumeLayout(false); - toolStripReports.PerformLayout(); - tabCounterfactual.ResumeLayout(false); - tabCounterfactual.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)dgvCounterfactuals).EndInit(); - toolStripCf.ResumeLayout(false); - toolStripCf.PerformLayout(); - ResumeLayout(false); - } - - #endregion - - private System.Windows.Forms.TabControl tabControlSup; - private System.Windows.Forms.TabPage tabAnalyse; - private System.Windows.Forms.ToolStrip toolStripChat; - private System.Windows.Forms.ToolStripLabel lblProfil; - private System.Windows.Forms.ToolStripComboBox cbProfile; - private System.Windows.Forms.ToolStripLabel lblModel; - private System.Windows.Forms.ToolStripTextBox tbModel; - private System.Windows.Forms.ToolStripSeparator sepChat; - private System.Windows.Forms.ToolStripButton btnClearChat; - private System.Windows.Forms.RichTextBox rtbChat; - private System.Windows.Forms.Panel pnlChatInput; - private System.Windows.Forms.TextBox tbChatInput; - private System.Windows.Forms.Button btnSend; - private System.Windows.Forms.TabPage tabDossiers; - private System.Windows.Forms.ToolStrip toolStripDossier; - private System.Windows.Forms.ToolStripButton btnDossierRefresh; - private System.Windows.Forms.ToolStripSeparator sepDossier; - private System.Windows.Forms.ToolStripLabel lblSignal; - private System.Windows.Forms.ToolStripTextBox tbSignalId; - private System.Windows.Forms.ToolStripButton btnDossierOpen; - private System.Windows.Forms.SplitContainer splitDossiers; - private System.Windows.Forms.DataGridView dgvSignals; - private System.Windows.Forms.TextBox tbDossier; - private System.Windows.Forms.TabPage tabBerichte; - private System.Windows.Forms.ToolStrip toolStripReports; - private System.Windows.Forms.ToolStripButton btnReportsRefresh; - private System.Windows.Forms.SplitContainer splitReports; - private System.Windows.Forms.DataGridView dgvReports; - private System.Windows.Forms.TextBox tbReport; - private System.Windows.Forms.TabPage tabCounterfactual; - private System.Windows.Forms.ToolStrip toolStripCf; - private System.Windows.Forms.ToolStripButton btnCfRefresh; - private System.Windows.Forms.DataGridView dgvCounterfactuals; - private System.Windows.Forms.Label lblStatus; - } -} diff --git a/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.cs b/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.cs deleted file mode 100644 index d4737a6..0000000 --- a/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.cs +++ /dev/null @@ -1,205 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Windows.Forms; -using Microsoft.Extensions.DependencyInjection; -using PolyTrader.Core.Analytics; -using PolyTrader.Modules.Supervisor.Agent; -using PolyTrader.Modules.Supervisor.Persistence; -using PolyTrader.Modules.Supervisor.Services; - -namespace PolyTrader.Modules.Supervisor.Ui -{ - /// - /// Hauptfenster des Supervisor-Moduls: Tab „Analyse" (Chat mit Profil-/Modellwahl, Tool-Aufrufe - /// transparent), Tab „Dossiers" (Signal-Browser), Tab „Berichte" (gespeicherte Analysen). - /// Layout im Designer (SupervisorMainForm.Designer.cs), Verhalten/Daten hier. - /// - public partial class SupervisorMainForm : Form - { - private DossierService? _dossiers; - private SupervisorAgent? _agent; - private ISupervisorReportRepository? _reports; - private ISupervisorCounterfactualRepository? _counterfactuals; - - public SupervisorMainForm() - { - InitializeComponent(); - - foreach (var profile in SupervisorProfiles.All) - cbProfile.Items.Add(profile); - cbProfile.SelectedIndex = 0; - - btnSend.Click += async (_, _) => await SendQuestionAsync(); - tbChatInput.KeyDown += async (_, e) => - { - if (e.Control && e.KeyCode == Keys.Enter) { e.SuppressKeyPress = true; await SendQuestionAsync(); } - }; - btnClearChat.Click += (_, _) => rtbChat.Clear(); - btnDossierRefresh.Click += (_, _) => LoadSignals(); - btnDossierOpen.Click += (_, _) => OpenDossier(tbSignalId.Text.Trim()); - dgvSignals.SelectionChanged += (_, _) => OpenSelectedSignal(); - btnReportsRefresh.Click += (_, _) => LoadReports(); - dgvReports.SelectionChanged += (_, _) => ShowSelectedReport(); - btnCfRefresh.Click += (_, _) => LoadCounterfactuals(); - } - - public void Initialize(IServiceProvider services) - { - _dossiers = services.GetRequiredService(); - _agent = services.GetRequiredService(); - _reports = services.GetRequiredService(); - _counterfactuals = services.GetRequiredService(); - LoadSignals(); - LoadReports(); - LoadCounterfactuals(); - AppendChat("System", "Supervisor bereit (read-only). API-Key: POLYTRADER_OPENROUTER_KEY oder Datei openrouter.key. " + - "MCP-Light für externe Clients: POLYTRADER_MCP_PORT setzen.", System.Drawing.Color.Gray); - } - - // ===== Analyse-Chat ===== - - private async System.Threading.Tasks.Task SendQuestionAsync() - { - if (_agent == null) return; - string question = tbChatInput.Text.Trim(); - if (question.Length == 0) return; - var profile = cbProfile.SelectedItem as SupervisorProfile ?? SupervisorProfiles.Allgemein; - - tbChatInput.Text = ""; - btnSend.Enabled = false; - AppendChat($"Du ({profile.Name})", question, System.Drawing.Color.DarkBlue); - lblStatus.Text = "Analyse läuft …"; - - var progress = new Progress(msg => AppendChat("Tool", msg, System.Drawing.Color.DarkGoldenrod)); - try - { - string model = tbModel.Text; - var result = await System.Threading.Tasks.Task.Run(() => - _agent.AskAsync(question, model, progress, profile)); - AppendChat("Supervisor", result.Answer, System.Drawing.Color.Black); - lblStatus.Text = $"Fertig. {result.ToolInvocations.Count} Tool-Aufruf(e), ~{result.PromptTokens + result.CompletionTokens} Tokens."; - SaveReport(profile, model, question, result); - } - catch (Exception ex) - { - AppendChat("Fehler", ex.Message, System.Drawing.Color.Firebrick); - lblStatus.Text = "Fehler bei der Analyse."; - } - finally - { - btnSend.Enabled = true; - } - } - - private void SaveReport(SupervisorProfile profile, string model, string question, AgentResult result) - { - try - { - var calls = new List(); - foreach (var (tool, args, _) in result.ToolInvocations) - calls.Add(new { tool, args }); - _reports?.Insert(new SupervisorReport - { - Profile = profile.Name, - Model = model, - Question = question, - Answer = result.Answer, - ToolCallsJson = System.Text.Json.JsonSerializer.Serialize(calls), - ToolCallCount = result.ToolInvocations.Count, - PromptTokens = result.PromptTokens, - CompletionTokens = result.CompletionTokens - }); - LoadReports(); - } - catch { /* Bericht-Ablage ist Beiwerk – Analyse-Ergebnis steht im Chat */ } - } - - private void AppendChat(string who, string text, System.Drawing.Color color) - { - if (InvokeRequired) { BeginInvoke(() => AppendChat(who, text, color)); return; } - rtbChat.SelectionStart = rtbChat.TextLength; - rtbChat.SelectionColor = color; - rtbChat.AppendText($"[{DateTime.Now:HH:mm:ss}] {who}: {text}{Environment.NewLine}{Environment.NewLine}"); - rtbChat.ScrollToCaret(); - } - - // ===== Dossier-Browser ===== - - private void LoadSignals() - { - if (_dossiers == null) return; - try - { - List signals = _dossiers.RecentSignals(200); - dgvSignals.DataSource = signals; - lblStatus.Text = signals.Count == 0 - ? "Noch keine Journal-Einträge (Entscheidungen entstehen, sobald Signale verarbeitet werden)." - : $"{signals.Count} Signale."; - } - catch (Exception ex) - { - lblStatus.Text = $"Journal nicht lesbar: {ex.Message}"; - } - } - - private void OpenSelectedSignal() - { - if (dgvSignals.CurrentRow?.DataBoundItem is SignalSummary s) - OpenDossier(s.SignalId); - } - - private void OpenDossier(string signalId) - { - if (_dossiers == null || string.IsNullOrWhiteSpace(signalId)) return; - try - { - var dossier = _dossiers.BuildForSignal(signalId); - tbDossier.Text = DossierBuilder.ToMarkdown(dossier).Replace("\n", Environment.NewLine); - tbSignalId.Text = signalId; - } - catch (Exception ex) - { - tbDossier.Text = $"Dossier konnte nicht geladen werden: {ex.Message}"; - } - } - - // ===== Berichte ===== - - private void LoadReports() - { - if (_reports == null) return; - try - { - dgvReports.DataSource = _reports.GetRecent(100); - } - catch (Exception ex) - { - lblStatus.Text = $"Berichte nicht lesbar (sup_-Migration angewendet?): {ex.Message}"; - } - } - - // ===== Counterfactuals ===== - - private void LoadCounterfactuals() - { - if (_counterfactuals == null) return; - try - { - dgvCounterfactuals.DataSource = _counterfactuals.GetRecent(200); - } - catch (Exception ex) - { - lblStatus.Text = $"Counterfactuals nicht lesbar (Migration angewendet?): {ex.Message}"; - } - } - - private void ShowSelectedReport() - { - if (dgvReports.CurrentRow?.DataBoundItem is SupervisorReport r) - tbReport.Text = - $"[{r.CreatedAt:dd.MM.yyyy HH:mm}] Profil {r.Profile} · Modell {r.Model} · {r.ToolCallCount} Tool-Aufrufe{Environment.NewLine}{Environment.NewLine}" + - $"FRAGE:{Environment.NewLine}{r.Question}{Environment.NewLine}{Environment.NewLine}" + - $"ANTWORT:{Environment.NewLine}{r.Answer.Replace("\n", Environment.NewLine)}"; - } - } -} diff --git a/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.resx b/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.resx deleted file mode 100644 index 3d3693b..0000000 --- a/src/PolyTrader.Modules.Supervisor/Ui/SupervisorMainForm.resx +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - - 188, 17 - - - 382, 17 - - - 578, 17 - - - - - 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 - - - \ No newline at end of file diff --git a/tests/PolyTrader.Tests/PolyTrader.Tests.csproj b/tests/PolyTrader.Tests/PolyTrader.Tests.csproj index 0a15feb..7d13d7d 100644 --- a/tests/PolyTrader.Tests/PolyTrader.Tests.csproj +++ b/tests/PolyTrader.Tests/PolyTrader.Tests.csproj @@ -1,12 +1,10 @@ - + - net8.0-windows + net8.0 enable enable false - - true