docs/pruefplaene/PRUEFPLAN-Linux-Betrieb.md: Schritt-fuer-Schritt-Protokoll zum
Abarbeiten auf einer Test-VM, jeder Schritt mit erwartetem Ergebnis und der
Angabe, was zurueckzumelden ist.
Zwei Fallen vorab, die beim Vorbereiten aufgefallen sind:
1. Der Linux-Publish enthaelt appsettings.Local.json mit den echten
MySQL-Zugangsdaten. Ungeprueft auf die VM kopiert, laeuft der Test gegen die
PRODUKTIVdatenbank - und der MarketSyncService schreibt dort als
Hintergrunddienst hinein. Der Plan legt deshalb zuerst eine eigene
Testdatenbank samt eigenem Benutzer an; das Umstellen der Verbindung ist
ausdruecklich als wichtigster Schritt markiert.
2. Es gibt keine automatischen Migrationen beim Start (nachgeprueft: kein
Migrate()/EnsureCreated() im Code). Das Schema muss vorher stehen - fuenf
DbContexts, jeder mit eigenen Migrationen, ueber die Umgebungsvariable
POLYTRADER_MYSQL.
Inhaltliche Schwerpunkte des Plans:
- Die Hypothese, dass --headless OHNE GUI-Bibliotheken auskommt, weil
BuildAvaloniaApp() dort nie aufgerufen wird und Skia damit nie geladen wird.
Der Plan prueft das bewusst zuerst ohne die Pakete - das Ergebnis entscheidet,
was spaeter ins Server-Grundimage muss.
- Die WorkingDirectory-Falle aus D-11: server_settings.xml relativ zum
Arbeitsverzeichnis, master.key relativ zur Programmdatei. Bei Abweichung legt
ServerSettings.Load() kommentarlos eine neue Datei an. Wird per find ueber
frisch geaenderte Dateien nachgewiesen.
- SIGTERM-Shutdown gegen TimeoutStopSec=45 gemessen, Restart=on-failure
per pkill -9 gegengetestet.
- T2 (TerminalLogger stempelt DateTime.Now statt AppTimeZone) wird auf einer
UTC-VM erstmals nachweisbar statt nur behauptet.
- Logrotate mit copytruncate, weil die App die Logdatei offen haelt.
- Master-Key als Umgebungsvariable im Dienst: erster echter Lauf von
FilePermissions unter Linux-Rechten.
Am Ende eine Liste der zehn zurueckzumeldenden Ausgaben und die Befehle zum
Aufraeumen der VM.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A2 (CI-Runner) auf pausiert: auf der Gitea-Maschine ist derzeit keine Leistung
fuer einen weiteren Container frei (Entscheidung Richard). Der Workflow bleibt
liegen und ist sofort lauffaehig, sobald ein Runner da ist.
A4 aufgeteilt, weil die bisherige Blockade nicht stimmte:
- A4a "Linux-Betrieb auf einer Test-VM" ist NICHT durch A3 blockiert. Am Code
nachgeprueft: LicenseGate ruft bei fehlender Lizenz kein Environment.Exit auf,
sondern startet die Core-Shell im eingeschraenkten Modus ohne Trading-Module.
Watchdog, Error-Reporting und Update-Pruefung stehen in appsettings.json
ohnehin auf false. Der Linux-Betrieb ist damit ohne Deploymentcenter testbar -
und Richard hat dafuer Test-VMs.
- A4b "Feldtest im Zielland" bleibt blockiert (A3 + A4a).
- A5 und B3 haengen jetzt praeziser an A4b statt an "A4".
Das ist mehr als Umsortieren: Die Anwendung ist noch nie auf Linux GELAUFEN -
verifiziert war bisher nur, dass sie sich publishen laesst. Das ist die groesste
ungetestete Flaeche im Projekt, und sie ist ab sofort adressierbar.
A4a listet konkret, was zu pruefen ist: native Abhaengigkeiten von
SkiaSharp/HarfBuzz, DB-Verhalten mit und ohne erreichbare MySQL, die
WorkingDirectory-Falle aus D-11 (server_settings.xml relativ zum
Arbeitsverzeichnis, master.key relativ zur Programmdatei - bei Abweichung legt
ServerSettings.Load() kommentarlos eine neue Datei an), SIGTERM-Shutdown,
Logrotate und der Master-Key als Umgebungsvariable unter Linux-Rechten.
Nebenbei wird dort T2 nachweisbar: der TerminalLogger stempelt mit DateTime.Now
statt AppTimeZone - auf einer UTC-VM mit Anzeigezone Europe/Berlin muessen die
Logdatei-Grenzen sichtbar von der angezeigten Uhrzeit abweichen. Bisher ist das
ein theoretischer Befund.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Status des Projekts stand verstreut in elf Umsetzungsplaenen, drei
Konzepten, der Linux-Analyse und dem Projektstand - teils widersprechend, teils
wochenlang veraltet. Ab jetzt gibt es genau eine Statusquelle.
docs/ROADMAP.md (neu):
- Alle Vorhaben in vier Stufen A bis D, plus technische Schuld und Verlauf.
Die Stufen sind eine Reihenfolge, keine Termine: jede schafft die
Voraussetzung fuer die naechste.
- Statuszeichen: erledigt / offen / blockiert (mit Ursache) / bewusst
zurueckgestellt / Idee, nicht beschlossen. Damit ist das, was wir NICHT bauen
wollen, sichtbar vorgehalten statt unauffindbar in einem Plan zu schlummern.
- Inhaltlich getragen, nicht nur verlinkt: je Vorhaben Ziel, Phasen,
Akzeptanzkriterien, offene Entscheidungen und Leitplanken aus den Quelldokumenten.
- Sichtbar gemacht, was vorher zwischen den Dokumenten verborgen lag:
CopyTrading Phase 1 ist der Engpass der gesamten Roadmap (MarketMaking und
BundleArbitrage haben harte Voraussetzungen darauf), und die Sniper-Metriken
aus Phase 3.2 sind ein Spezialfall des StrategieDrift-Fingerprints - zusammen
bauen statt doppelt.
Archiv (docs/archiv/):
- 15 Dokumente verschoben (11 Umsetzungsplaene, 3 Konzepte, ANALYSE-Linux-Portierung).
Sie bleiben die Bauanleitungen mit Code-Bezuegen, Risikotabellen und
Begruendungen - eingefroren ist nur ihr Status.
- archiv/README.md ordnet jedes Dokument seinem Roadmap-Punkt zu.
Verweise nachgezogen - der eigentliche Aufwand:
- 25 Markdown-Links repariert. 15 davon verschiebungsbedingt (eine Ebene
tiefer), der Rest war schon vorher falsch: die Ideensammlung verlinkte
Quellcode relativ zum Repo-Wurzelverzeichnis statt zu docs/.
- 12 Dateien ausserhalb von docs/ verwiesen in Kommentaren auf die Plaene
(csproj, props, setup.json, sechs Quelldateien) - alle auf archiv/ umgebogen.
- Verweise auf Dateien, die der Fruehjahrsputz geloescht hat (Ui/,
Program.cs, WindowMenuBar), zu Klartext entschaerft statt tote Links zu lassen.
- Gegenprobe: 85 Links geprueft, 0 kaputt. Build gruen, 476 Tests gruen.
PROJEKTSTAND.md entdoppelt: Abschnitt "Offen" verweist jetzt auf die Roadmap.
Arbeitsteilung ist damit klar - Projektstand sagt was IST, Roadmap was KOMMT.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die Plattformneutralitaet war nach dem WinForms-Ausbau eine Momentaufnahme: eine
einzige net10.0-windows-Zeile oder ein "using System.Drawing" genuegt, und der
Linux-Build ist kaputt, ohne dass es auf einer Windows-Maschine auffaellt - dort
baut es weiter. Genau das faengt die CI ab, und zwar auf Linux.
.gitea/workflows/ci.yml, zwei Jobs auf ubuntu-latest:
- build-test: restore, build, die 476 Tests (brauchen keine DB, laufen gegen
EF-InMemory), Linux-Publish. Der Publish ist kein Selbstzweck - dort faellt
auf, wenn ein Paket doch windows-only ist. Anschliessend wird geprueft, dass
die Executable, appsettings.json, setup.json und libSkiaSharp.so wirklich im
Ergebnis liegen.
- guard: keine windows-TFMs, kein UseWindowsForms/UseWPF, keine windows-only
using-Direktiven, keine versionierten Secret-Dateien, keine anfaelligen Pakete.
Alle Waechter sind in beide Richtungen gegengeprueft: sie schlagen bei
simulierten Regressionen an (windows-TFM, UseWindowsForms, using System.Drawing,
getrackte packager.config.json samt dc_sub_-Token, Newtonsoft 11.0.2) und
schweigen beim Ist-Zustand. Die Namespace-Pruefung trifft bewusst nur echte
using-Direktiven: im Bestand steht an vielen Stellen erklaert, WARUM
System.Drawing nicht verwendet wird, und das darf keinen Fehlalarm ausloesen.
Der Schwachstellen-Check ist Punkt 1 der wiederkehrenden Audit-Checkliste aus
dem Sicherheitskonzept - laeuft ab jetzt bei jedem Push statt quartalsweise von
Hand. Er wuerde zum Beispiel anschlagen, wenn der Newtonsoft-Pin im Core faellt.
Bewusst kein -warnaserror: die 15 vorhandenen Warnungen muessten erst weg, sonst
ist die CI ab dem ersten Tag rot und wird ignoriert.
WICHTIG - die CI laeuft noch nicht: auf der Gitea-Instanz ist kein Actions-Runner
registriert (auf Repo-, Benutzer- und Instanzebene geprueft, ueberall 0).
has_actions ist true, es fehlt nur der Runner. Einrichtung Schritt fuer Schritt
in docs/LEITFADEN-CI.md Abschnitt 3.
.gitattributes neu: erzwingt LF fuer .yml/.sh/.service. Entwickelt wird mit
autocrlf=true auf Windows, ausgefuehrt auf Linux - ein Shell-Skript mit CRLF
scheitert dort mit irrefuehrenden Meldungen. Bisher gab es keine .gitattributes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
docs/PROJEKTSTAND.md neu: Einstiegsdokument mit Gesamtueberblick - Architektur,
Modul-Stand, was abgeschlossen ist und was offen. Alle Angaben am Code
nachgeprueft, nicht aus den Plandokumenten uebernommen. Die offenen Punkte sind
danach getrennt, ob sie am Schreibtisch erledigt werden koennen oder echtes
Geld/den Zielserver brauchen - das war vorher nirgends zusammengefasst.
Modularisierungsplan korrigiert: Die Phasen 3 bis 6 standen auf "IN ARBEIT"
beziehungsweise offen, obwohl die Arbeit seit Wochen getan war. Nachgeprueft und
abgehakt sind unter anderem:
- Phase 5: alle Modul-Services liegen im Modulprojekt, frm_main ist weg, alle
vier Module implementieren IPolyTraderModule
- Phase 6: komplett - kein MongoDB.Driver/LiteDB mehr in irgendeiner csproj
- Phase 7 teilweise: 476 Tests, keine leeren catch-Bloecke mehr,
Secrets-Verschluesselung umgesetzt (AES-GCM statt DPAPI, da DPAPI Windows-only
ist und die Linux-Portierung blockiert haette)
Offen bleiben aus Phase 7 nur God-Methoden und die TerminalLogger-Umstellung.
Beim Nachpruefen aufgefallen: Accounting A-3 (US-Steuerschicht, Form 8949) ist
entgegen der bisherigen Annahme nicht gebaut - es gibt keinen UsTaxEngine.
A-2 und A-4 dagegen sind da. Im Projektstand vermerkt.
docs/README.md verweist jetzt auf den Projektstand und fuehrt die bisher
fehlenden Ordner sicherheit/ und den Deploymentcenter-Plan auf.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Das Repo enthaelt ab jetzt ausschliesslich plattformneutralen Code. Build gruen
(0 Fehler), 476 Tests gruen, Linux-Publish der Avalonia-App verifiziert.
Rueckfallebene ist der Tag winforms-final, der jetzt auch auf dem Server liegt.
WinForms endgueltig ausgebaut (P11/L5):
- PolyTrader.App.csproj aus PolyTraderSharp.sln genommen und geloescht
- Ui/, Models/, Licensing/, services/, Properties/, Resources/icons/,
Program.cs, favicon.ico entfernt - rund 4.500 LOC generierter Designer-Code
- Root-appsettings.json entfernt: exaktes Duplikat der Avalonia-Kopie, die die
App tatsaechlich liest. Zwei Dateien mit gleichem Inhalt laufen frueher oder
spaeter auseinander.
- Kein net10.0-windows mehr im Repo; Build-Warnungen von 23 auf 15 gesunken
(die CS0169 aus den Designer-Resten sind weg)
PNG-Symbole gerettet statt geloescht:
Die Avalonia-App band sie per ..\..\Resources\*.png aus dem Repo-Root ein und
haette sie mitverloren. Sie liegen jetzt in src/PolyTrader.App.Avalonia/Assets/,
wo sie hingehoeren. Der avares-Pfad "Assets/<datei>.png" bleibt unveraendert -
in der gebauten Assembly nachgeprueft.
LicenseLabrador abgeloest (D-6):
- LicenseLabrador.Client aus lib/nuget entfernt, Quellen-Mapping in
NuGet.Config auf Deploymentcenter.* reduziert, lib/nuget/README.md neu
- Bewusste Abweichung vom Plan: die Watchdog*-Felder in ServerSettings bleiben.
D-1 hat sie auf die Deploymentcenter-API umgewidmet statt sie zu ersetzen;
sie werden aktiv benutzt. Die Planzeile stammte aus der Zeit davor.
Weitere Altlasten:
- agentspace/ (30 Dateien: WinForms-Designer-Patcher, fix_mongo.py nach der
MySQL-Migration, tmp/test/scratch-Skripte) entfernt
- Ideen-fuer-Mittwoch.txt entfernt - Inhalt ist laengst umgesetzt
- tote .gitignore-Regel fuer agentspace/antigravity/ entfernt
- lokal entfernt (nicht versioniert): MongoDB/-Exporte, data.db, .bak-Datei
Dokumentation nachgezogen:
- ANALYSE-Linux-Portierung.md auf Revision 6, P11/L5 als erledigt
- LEITFADEN: Abschnitt B vollstaendig aufgeloest, A5 prueft ab jetzt gegen
einen Worktree des Tags statt gegen den Arbeitsbaum
- UMSETZUNGSPLAN-Watchdog-LicenseLabrador-Integration.md als ABGELOEST
gekennzeichnet, D-6 im Deploymentcenter-Plan auf den Iststand gezogen
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sicherungscommit vor dem Aufraeumen des Repos, damit nachvollziehbar bleibt,
welcher Stand vor der Bereinigung galt. Build gruen, 476 Tests gruen.
Zwei Straenge, die sich ueber .csproj, Program.cs und appsettings.json
ueberschneiden und darum gemeinsam abgelegt werden:
Deploymentcenter-Integration (P3c, Plan D-0 bis D-5 code-seitig fertig):
- Deploymentcenter.Client 2.5.0 als lokales Paket, Source-Mapping erweitert
- DeploymentcenterOptions, DeploymentcenterErrorReporter, LicenseGate/LicenseCli
- WatchdogHeartbeatService auf die Deploymentcenter-API umgestellt
(version, os, checks, metrics, status stopped)
- Security: MasterKeyResolver, SecretRedactor, FilePermissions
- Directory.Build.props mit zentraler Version 0.1.0 (Packager-Versionsdisziplin)
- deploy/: Packager-Vorlage und systemd-Unit; echte Zugangsdaten bleiben
ueber .gitignore aussen vor
- setup.json fuer die Erstinstallation
- UMSETZUNGSPLAN-Deploymentcenter-Integration.md; ANALYSE-Linux-Portierung.md
verweist auf den neuen Plan
Einfenster-Shell (UI-Redesign):
- ShellWindow + ShellNavModel als Seitenleisten-Shell
- WindowMenuBar und WindowMenuModel entfallen
- Modul- und Kernfenster auf die Shell-Einbettung angepasst
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beide Portierungsdokumente hingen dem Code hinterher. Commit 7f0b05e setzte A1
bis A4 um, ohne eine einzige Markdown-Datei mitzuziehen - der Leitfaden wies die
vier Punkte weiter als offen aus. Ein Agent, der ihn als Arbeitsanweisung nimmt,
haette sie ein zweites Mal gebaut.
LEITFADEN-Avalonia-Portierung.md:
- A1 bis A4 als erledigt markiert, mit Ist-Tabelle: wo der Code liegt und dass
auch die Feinheiten sitzen (nullables GetService fuer Supervisor, LaunchUriAsync
statt Process.Start, DialogWindow.Confirm vor Delete, ContextMenu mit beiden
Eintraegen). Die Soll-Beschreibungen bleiben als Pruefvorlage fuer A5 stehen.
- A5 (Durchsehen mit echten Daten) als einziger offener Punkt ausgewiesen.
- Abschnitt B um das Lizenz-Gate und den Watchdog-Heartbeat ergaenzt. Wichtig fuer
den Naechsten: die Avalonia-App setzt derzeit GAR KEINE Lizenz durch, waehrend
die WinForms-Fassung das Gate weiter hat. Beides kommt mit dem Deploymentcenter
neu, also dort nichts mehr investieren.
- Neuer Abschnitt C fuer Folgepunkte ohne Blockerwirkung.
ANALYSE-Linux-Portierung.md (Revision 5):
- P5 bis P8 als erledigt, Stufen L3 und L4 entsprechend; Restaufwand von 33-51 PT
auf 7-13 PT korrigiert.
- Offen bleiben P3c (Deploymentcenter, steht als Naechstes), CI, systemd/Feldtest,
WinForms-Ausbau und die Abnahme A5.
- Historische Aufwandszahlen als Rueckblick gekennzeichnet statt geloescht.
Nachgeprueft statt uebernommen: A1-A4 gegen den Code verifiziert, ebenso dass es
keinerlei CI-Konfiguration gibt (weder .github noch .gitea) und dass --headless in
App.Avalonia/Program.cs bereits existiert.
Beim Pruefen aufgefallen, kein Fehler: TerminalLogger schreibt die Tagesdatei mit
DateTime.Now und der Launcher liest sie mit DateTime.Now - konsistent, aber beide
ignorieren die in P2 eingefuehrte AppTimeZone. Als Folgepunkt C notiert, relevant
erst beim Headless-Betrieb auf einem UTC-Server.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Paritaet mit dem WinForms-Referenzstand (Tag winforms-final) hergestellt:
- A1 & A2 (Launcher): Account-Uebersicht DataGrid (inkl. Polymarket-Profil-Button via Launcher.LaunchUriAsync), Modul-KPI-Kacheln (7T/30T PnL & Winrate) und 3-Spalten-Live-Ueberblick (Auffaellige Trades 24h, Warnungen & Fehler heute aus den JSONL-Logs, Supervisor-KI Bericht). Periodische Aktualisierung alle 30 s eingebaut.
- A3 (Copytrading): Master-Trader Werkzeugleiste um 'Neu' (AddNewTrader) und 'Loeschen' (DeleteSelectedTrader mit DialogWindow.Confirm) erweitert.
- A4 (Terminal): Log-Kontextmenue fuer 'Kopieren' und 'Alles auswaehlen' an die Live-Log-Ausgabe angefuegt.
Verifiziert: Solution baut fehlerfrei, 450 Tests gruen, --smoke-ui test erfolgreich.
Co-Authored-By: Antigravity AI <antigravity@google.com>
docs/LEITFADEN-Avalonia-Portierung.md: Anleitung fuer einen KI-Agenten, der die UI-
Portierung weiterfuehrt. Enthaelt bewusst eine EHRLICHE Luecken-Liste - alle acht Fenster
konstruieren zwar, mehrere sind aber inhaltlich unvollstaendig. Gegen den Tag
winforms-final verglichen und belegt:
- A1: Launcher-Live-Ueberblick fehlt KOMPLETT (auffaellige Trades 24h, Warnungen/Fehler
heute aus der JSONL, letzter Supervisor-Bericht, Modul-KPIs) - groesste Luecke
- A2: Launcher-Account-Uebersicht fehlt KOMPLETT (inkl. Polymarket-Button je Konto)
- A3: Copytrading, Master-Trader: 'Neu' und 'Loeschen' nicht verdrahtet
- A4: Terminal-Kontextmenue (Kopieren/Alles auswaehlen) fehlt
- A5: kein Fenster wurde mit echten Daten durchgeklickt - Spaltenbreiten, Umbrueche und
Splitter-Positionen sind ungeprueft
Dazu die Regeln (Layout deklarativ, keine festen Farben, keine Erfolgs-Dialoge, Module
bleiben frei von Avalonia), das Baukastenmuster, die Stolperfallen die mich Zeit gekostet
haben (x:DataType, CalendarDatePicker-Typ, BindingList vs ObservableCollection,
LoadingRow, Namenskollision ClosedTradeRow, SaveFilePicker-Pfad), die Pruefbefehle mit
erwarteter Ausgabe und was NICHT angefasst werden darf (Avalonia 12, Lizenzdialog,
WinForms-Projekt).
Alle Dateiverweise und der dokumentierte Smoke-Befehl sind verifiziert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Farbschema hell / dunkel / dem System folgen, umschaltbar per Klick, Stand wird in
server_settings.xml gemerkt (ServerSettings.Theme). Der Editor zeigt die Einstellung
automatisch als Auswahlfeld - kein Zusatzcode, weil sie ein Enum ist.
- App.axaml: 18 Farb-Token je Variante (Flaechen, Rahmen, Texte, Bedeutungsfarben,
Zeilenfaerbung, Trading-Umschalter, Chat-Rollen). Die Standard-Steuerelemente stellt
das FluentTheme selbst um.
- 22 fest verdrahtete Farben in 11 XAML-Dateien auf DynamicResource umgestellt - die
wechseln damit von selbst mit.
- Umschalter (Sonne/Mond) sitzt in der gemeinsamen Fensterleiste, also auf JEDEM Fenster.
Der eigentliche Knackpunkt waren die Farben, die im Code gesetzt werden - die folgen dem
Thema NICHT von selbst:
- TradeRowPalette liefert jetzt Eigenschaften statt static readonly, loest also bei jedem
Zugriff neu auf. Im Dunkeln gedaempfte Toene statt der hellen Pastelltoene, die dort
blenden und den Text unlesbar machen wuerden.
- ChatEntry speichert die ROLLE statt eines fertigen Brush - dadurch stimmt der Verlauf
nach dem Umschalten ohne Neuaufbau der Liste.
- Launcher-Umschalter, Dashboard-KPI und die Grid-Zeilenfarben zeichnen sich ueber
ThemeManager.ThemeChanged neu.
- Das Terminal bleibt in beiden Schemata dunkel (Konsolen sind konventionell dunkel).
Nebenbei die Anzeige-Kultur gepinnt (stand ohnehin auf der Linux-Liste): auf Linux richtet
sie sich sonst nach LANG/LC_ALL, das unter systemd oft nicht gesetzt ist - dann faellt .NET
auf Invariant zurueck und aus '1.234,56 USDC' wird '1,234.56 USDC'. Maschinen-I/O laeuft
davon unabhaengig weiter invariant.
Smoke-UI prueft jetzt zusaetzlich, dass ALLE 18 Farben in BEIDEN Varianten aufloesen -
ein vertippter Ressourcenschluessel wuerde sonst still grau werden.
Verifiziert: Solution baut, 450 Tests gruen, --smoke-ui gruen (10 Fenster + Editor +
beide Farbschemata), App startet im gespeicherten Schema, Linux-Publish laeuft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Alle acht Fenster laufen jetzt unter Avalonia: Launcher, Dashboard, Settings, Terminal,
Server Jobs, Copytrading, ResolutionFarming, Supervisor, Accounting (+ Shutdown- und
Allzweck-Dialog).
- Copytrading: vier Tabs (Master-Trader mit Account-Zuweisung, Offene Trades, Geschlossene
Trades mit Filterleiste, Account-Einstellungen). Zeilenfaerbung nach PnL laeuft ueber
DataGrid.LoadingRow - greift damit auch bei virtualisierten Zeilen, anders als das
fruehere Faerben in DataBindingComplete.
- ResolutionFarming: Kandidaten, Positionen, Historie, Settings - je Konto.
- Supervisor: Analyse-Chat gegen den Agenten (Tool-Fortschritt in der Statuszeile),
Dossiers mit Markdown-Ansicht, Berichte, Counterfactuals.
- Accounting: KPI-Kacheln, Monats-BWA, Ledger, Abruf/Status, PDF- und CSV-Export ueber
den plattformneutralen Datei-Dialog.
Der SettingsEditor traegt wie erwartet die drei restlichen PropertyGrid-Stellen
(Master-Trader, Account-Einstellungen, ResolutionFarming) mit je einem Aufruf.
ENTSCHEIDUNG - Modul-Fenster liegen in der App, nicht in den Modulen
(begruendet in Views/Modules/README.md): Die App ist der Kompositionswurzel und
referenziert ohnehin alle Module. So bleiben die Modulprojekte FREI VON AVALONIA, was fuer
den kopflosen Linux-Betrieb den Ausschlag gibt - der Daemon soll keine GUI-Bibliothek
mitschleppen. Verifiziert: kein Modul zieht Avalonia. Registrierung in Shell/ModuleViews.cs,
und zwar nur fuer tatsaechlich geladene Module - ein per DisabledModules abgeschaltetes
Modul bekommt gar kein Fenster.
Nebenbei: eigene View-Model-Typen CopyOpenTradeRow/CopyClosedTradeRow statt des
Modul-Modells ClosedTradeRow - sie tragen den aufgeloesten Master-Trader-Namen und die
Zeilenfarbe, die es dort nicht gibt (und vermeiden die Namensmehrdeutigkeit).
Verifiziert: Solution baut, 450 Tests gruen, --smoke-ui gruen (alle 8 Fenster + Launcher +
Dialog + Editor-Pruefung), App laeuft real mit allen Trading-Diensten, Linux-Publish laeuft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Alle vier Core-Fenster sind damit portiert.
TERMINAL:
- Live-Ausgabe als virtualisiertes ItemsControl ueber eine begrenzte Zeilenliste statt
RichTextBox. Damit entfaellt das Auto-Clear der WinForms-Fassung, das bei Erreichen der
Zeichengrenze den GESAMTEN Verlauf verwarf - jetzt werden nur die aeltesten Zeilen
verdraengt (Ringpuffer, 5000 Zeilen), der juengste Verlauf bleibt immer sichtbar.
Die Zeilenzahl steht in der Statuszeile.
- Log-Viewer unveraendert im Funktionsumfang: JSONL-Tagesdateien, Filter nach Datum, Level,
CID und Volltext, Doppelklick uebernimmt die CID (Signal-Kette verfolgen).
ZEITZONE (Befund aus der Linux-Analyse, hier faellig geworden):
Die Terminal-Ansicht rechnete hart gegen die WINDOWS-ID 'W. Europe Standard Time'. Auf Linux
traegt die nur ueber die ICU-Zuordnung und faellt ganz aus, wenn ICU fehlt oder
InvariantGlobalization gesetzt ist - das Fenster haette beim Oeffnen geworfen.
Neu: PolyTraderSharp.Services.AppTimeZone + ServerSettings.ApplicationTimeZoneId
(Default 'Europe/Berlin', IANA-Schreibweise). Aufloesung versucht die ID direkt, dann die
jeweils andere Schreibweise (IANA<->Windows), zuletzt die Systemzeitzone - ein unbekannter
Wert ist damit nie fatal, sondern erzeugt nur eine Warnung. Beide Programm-Einstiege setzen
sie einmalig beim Start; laut Vorgabe wird sie bei der Installation festgelegt und nicht im
laufenden Betrieb gewechselt (Aenderung verschiebt Logdatei-Tagesgrenzen).
8 neue Tests (AppTimeZoneTests) halten fest: IANA- UND Windows-ID liefern denselben
UTC-Versatz (Winter +1, Sommer +2), unbekannte IDs fallen mit Warnung auf die Systemzeitzone
zurueck, leere Angabe = Systemzeitzone, UTC wird korrekt umgerechnet.
Verifiziert: Solution baut, 450 Tests gruen, --smoke-ui gruen (6 Fenster + Editor-Pruefung,
Zeitzone loest als Europe/Berlin auf), App laeuft real, Linux-Publish laeuft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der PropertyGrid-Ersatz ist EIN wiederverwendbares Steuerelement statt Handarbeit je Feld:
Controls/SettingsEditor zeigt ein beliebiges Einstellungsobjekt nach Richards Vorlage -
Kategorie-Ueberschrift, Beschriftung links, Feld rechts, Erklaerung klein darunter.
- SettingsModelBuilder liest die Attribute, die fuers PropertyGrid ohnehin gepflegt waren:
[Category] gruppiert, [DisplayName] beschriftet, [Description] wird zum Hinweistext,
[Browsable(false)] blendet aus (Watchdog-Token, Lizenzschluessel bleiben unsichtbar).
Ergebnis fuer ServerSettings: 6 Abschnitte, 15 Felder - ohne eine Zeile Feld-Code.
- Layout-Regel gewahrt: WELCHE Felder es gibt, kommt als Daten; WIE ein Feld aussieht,
steht deklarativ als DataTemplate je Feldtyp (Text/Zahl/Ja-Nein/Auswahl/Nur-Lese).
- Damit sind auch die drei restlichen PropertyGrid-Stellen (Account-Einstellungen,
Master-Trader, ResolutionFarming) mit je einem Aufruf erledigt.
SettingsWindow: Server-Settings + Polymarket-Accounts, Master-Key erzeugen,
OpenRouter-Key/Watchdog-Token setzen, Test-Heartbeat. Rueckmeldungen laufen ueber die
Statuszeile statt ueber Dialoge - nur echte Entscheidungen bekommen einen Dialog
(neu: Views/DialogWindow fuer Hinweis/Rueckfrage/maskierte Eingabe, Avalonia hat keine MessageBox).
Nebenbei einen offenen Punkt der Linux-Analyse erledigt: Schluesseldateien (master.key,
openrouter.key) werden jetzt per File.SetUnixFileMode auf 600 gesetzt. Auf Linux legt
File.WriteAllText sonst mit ueblicher umask 644 an - weltweit lesbar.
Lizenzdialog bewusst NICHT portiert: haengt am alten LicenseLabrador-SDK, das mit der
Deploymentcenter-Anbindung (P3c) ohnehin ersetzt wird - waere Wegwerfarbeit.
Smoke-UI prueft jetzt zusaetzlich die Feldzahl des Editors: ein Fenster kann fehlerfrei
konstruieren und trotzdem leer sein, wenn die Attribute verlorengehen.
Verifiziert: Solution baut, 442 Tests gruen, --smoke-ui gruen (5 Fenster + Editor-Pruefung),
Linux-Publish laeuft.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Drittes Fenster: KPI-Kacheln, drei Diagramme, Tradehistorie mit Suche/Filter und
Modul-Aktivierung. Aufbau nach docs/UI-SPEZIFIKATION-WinForms.md.
- Diagramme sind jetzt echte Steuerelemente (LiveCharts2) statt nach Bitmap gerenderter
ScottPlot-Bilder: interaktiv (Tooltips/Zoom) und ohne System.Drawing. Die Auswertung
kommt unveraendert aus TradeAnalytics - der Chart-Wechsel beruehrte keine Fachlogik.
Das war der Zweck der bestehenden Trennung und hat sich hier ausgezahlt.
- ModuleActivationInfo vom UI-Typ in den Core verschoben (PolyTrader.Core.Modularity):
Aussage ueber die Modularitaet, keine Darstellungsfrage - beide Shells brauchen sie.
- Modul-Tab listet auch NICHT geladene Module, sonst liessen sie sich nie reaktivieren.
Blockierte Module haben eine deaktivierte Schaltflaeche statt eines Hinweisdialogs;
der Grund steht ohnehin in der Spalte 'Hinweis'.
WICHTIG - Avalonia 12 -> 11.3.19 zurueckgenommen:
Der erste Wurf zog per Version='*' Avalonia 12.1.1. LiveCharts2 2.0.5 (die aktuellste
Version) ist gegen Avalonia 11 gebaut und bricht dort zur Laufzeit:
MissingFieldException 'Avalonia.Input.Gestures.PinchEvent'. Avalonia 12 ist dem
Chart-Oekosystem voraus. Jetzt 11.3.19 (DataGrid folgt eigener Reihe: 11.3.13).
Erst wieder anheben, wenn LiveCharts2 Avalonia 12 unterstuetzt.
Verifiziert: Solution baut, 442 Tests gruen, --smoke-ui gruen (alle 4 Fenster),
App laeuft real mit allen Trading-Diensten, publisht fuer linux-x64.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neues Projekt src/PolyTrader.App.Avalonia (net10.0, Avalonia 12.1.1, LiveCharts2 2.0.5)
- laeuft unter Windows und Linux aus derselben Quelle.
Enthalten:
- Program.cs mit bewusst getrenntem Aufbau: BuildHost() stellt Persistenz, Dienste und
Module ohne jeden UI-Bezug zusammen, erst Main haengt Avalonia daran. Damit ist der
kopflose Linux-Betrieb (--headless, Stufe L2) ohne Umbau erreichbar - der Schalter ist
bereits drin.
- AvaloniaUiHost als IModuleUiHost: gleiche Semantik wie die WinForms-Shell (ein Fenster
je View, offene nach vorn holen, alles maximiert).
- Fenster-Menueleiste vollstaendig DEKLARATIV (Controls/WindowMenuBar.axaml + ItemsSource
auf WindowMenuModel.Entries). Loest die alte Fassung ab, die menu.Items zur Laufzeit
leerte und neu befuellte - genau der Punkt, den die neue Layout-Regel verbietet.
- ViewIcons fuer Avalonia: dieselben Schluessel und dieselben PNGs wie zuvor, Core und
Module bleiben unveraendert.
- LauncherWindow, JobsWindow, ShutdownConfirmWindow (inkl. der 10-Sekunden-Sperre).
- --smoke-ui als Nachfolger der WinForms-Konstruktionspruefung; startet den Host bewusst
NICHT, damit ein reiner UI-Test nicht die Trading-Engine gegen echte Endpunkte anwirft.
Dabei aufgeraeumt:
- JobManager.Jobs: BindingList -> ObservableCollection. BindingList implementiert kein
INotifyCollectionChanged; neu registrierte Jobs waeren in Avalonia unsichtbar geblieben.
- StartupHydrationService aufgeteilt in CoreStateHydrationService (Core: Accounts +
Demo-Positionen) und CopyTradingHydrationService (Modul: Settings + Trader). Behebt einen
latenten Fehler: bei deaktiviertem Copytrading-Modul waeren die Accounts gar nicht mehr
hydriert worden, obwohl sie zum Core gehoeren.
Verifiziert: Solution baut, 442 Tests gruen, --smoke-ui gruen, die App laeuft real mit
Fenster und allen Trading-Diensten (Market-Sync, Master-Trader-Analyse, RF-Scanner),
und publisht fuer linux-x64.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Alle sieben Projekte auf net10.0 (App: net10.0-windows). Runtime 10.0.10 ist
installiert, 442 Tests gruen, Linux-Publish aller Nicht-App-Projekte laeuft.
EF Core 8 / Pomelo 8 bleiben bewusst stehen: net10.0 konsumiert net8.0-Bibliotheken
problemlos, und ein Provider-Wechsel hat wegen der Migrations-Implikationen eine
eigene Risikoflaeche - das gehoert in einen separaten, verifizierten Durchgang.
Sicherheitsfund nebenbei: Ab .NET 9 prueft NuGet standardmaessig auch transitive
Pakete. Damit wurde sichtbar, dass Nethereum 6.1.0 Newtonsoft.Json [11.0.2, 14.0.0)
zulaesst und ohne Pinnung auf 11.0.2 aufloest - bekannte Luecke hoher Schwere
(GHSA-5crp-9r3c-p9vr). Die App pinnte laengst 13.0.4, Core und Module nicht.
Jetzt im Core gepinnt, damit jeder Consumer sie bekommt (auch der kuenftige
Linux-Daemon). Danach 0 NU1903-Warnungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Variante B (Entscheidung Richard): Modul-UI entfernt statt in Zwischenprojekte
ausgelagert. Avalonia ist plattformuebergreifend, die neuen Ansichten kommen spaeter
direkt in die Modul-Projekte zurueck - kein Zwischenschritt, keine Wegwerfarbeit.
- 23 WinForms-Dateien aus den 4 Modulen entfernt (Spezifikation steht in
docs/UI-SPEZIFIKATION-WinForms.md, Originalcode im Tag winforms-final).
- RegisterUi ist jetzt je Modul ein dokumentierter No-Op: View-ID, Titel, Gruppe,
Order und der Tab-Aufbau stehen als XML-Doku drin, damit der Avalonia-Nachbau
die stabilen IDs und die Struktur uebernimmt.
- Alle 4 Modulprojekte + Testprojekt: net8.0 statt net8.0-windows, UseWindowsForms raus.
- P4 vorgezogen (war durch den Testprojekt-Wechsel faellig): PDFsharp-MigraDoc-GDI
-> PDFsharp-MigraDoc (Core-Build). Der Core-Build findet keine Systemschriften,
daher neu Logic/PdfFontResolver.cs: durchsucht die Schriftverzeichnisse des OS nach
Segoe UI/DejaVu/Liberation/Noto/Arial/FreeSans. Keine Schriftdateien im Repo noetig;
fehlt auf Linux alles, kommt eine klare Meldung mit apt-Hinweis statt eines
kryptischen Renderer-Fehlers.
Verifiziert: Core, alle 4 Module und das Testprojekt publishen fuer linux-x64, und
zwar ohne ein einziges Windows-spezifisches Paket in den deps.json. 442 Tests gruen
(inkl. PDF-Rendering) auf net8.0. Windows-App laeuft weiter mit den Core-Fenstern.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vor dem Entfernen der WinForms-UI: maschinell aus allen .Designer.cs extrahierte
Spezifikation aller 16 Fenster - Groessen, Tabs, Beschriftungen, Schaltflaechen und
saemtliche Grid-Spalten mit Reihenfolge, Format und Breite. Dazu uebergreifende
Gestaltungsregeln, Farbwerte der PnL-Zeilenfaerbung, Symbol-Schluessel je Fenster
und Verhaltensnotizen aus dem Code-Behind.
Damit laesst sich die Avalonia-UI moeglichst 1:1 nachbauen. Der Originalcode bleibt
zusaetzlich im Tag winforms-final; das Dokument empfiehlt, dort einmalig Screenshots
mit echten Daten zu ziehen (optischer Gesamteindruck, den kein Text ersetzt).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- TradeRowColoring liefert jetzt eine TradeRowTint-Kategorie (Loss/SmallWin/BigWin)
statt einer System.Drawing.Color. Die Schwellenlogik bleibt getestet, die konkrete
Farbe legt die UI fest (neu: Ui/TradeRowPalette.cs im CopyTrading-Modul).
Bessere Schichtung und Voraussetzung dafuer, dass das Modul spaeter net8.0 wird.
- TradeRowColoringTests prueft die Kategorie statt der Farbe (gleiche Abdeckung).
- Models/DashboardRow.cs: verwaistes using System.Drawing entfernt.
System.Drawing liegt damit ausschliesslich noch in UI-Ordnern - die Fachlogik in
Core und Modulen ist frei davon.
442 Tests gruen, --smoke-ui gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Der Core traegt keine WinForms-/System.Drawing-Abhaengigkeit mehr und baut als
plattformneutrales net8.0 (verifiziert: publish -r linux-x64 erfolgreich).
- ModuleView.CreateForm (Func<Form>) -> CreateView (Func<object>): die Shell kennt
ihr Toolkit und castet, der Core nicht. Avalonia kann denselben Contract nutzen.
- ModuleView.Icon (System.Drawing.Image, seit .NET 7 Windows-only) -> IconKey (string).
Aufloesung Schluessel->Bildressource neu in Ui/ViewIcons.cs, ersetzt Program.AssignMenuIcons.
- WindowMenu.cs (reine WinForms-Logik) aus dem Core nach Ui/ verschoben.
- WindowMenuTests entfernt: testet die eingefrorene WinForms-Menuelogik, die das
Testprojekt nach dem Core-Schnitt nicht mehr erreicht. Im Tag winforms-final erhalten;
das Avalonia-Gegenstueck bekommt eigene Tests (P6/P9).
Module und App bleiben vorerst net8.0-windows - ihre UI zieht erst mit der
Avalonia-Portierung um. Windows-App unveraendert lauffaehig (--smoke-ui gruen).
442 Tests gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- TraderMonitorService las API-Preise kulturabhaengig: unter de-DE wurde aus
"0.53" der Wert 53 (Faktor-100-Fehler im Einstandspreis). Nutzt jetzt den
bereits vorhandenen invarianten Helper ParseDecimal.
- Gleiche Fehlerklasse in PolymarketClobClient (6x) und MasterTraderAnalyticsJob
vorsorglich auf InvariantCulture gestellt.
- Neuer Regressionstest ApiNumberParsingTests (10 Faelle unter erzwungener de-DE-Kultur).
- Threema komplett entfernt (Entscheidung Richard): ThreemaService, vendorte
Bibliothek libs/Threema-MsgApi-Net-Core, ServerSettings-Block, DI-Verdrahtung.
- Ersetzt durch neutrale INotificationSink (No-Throw-Vertrag) + LogNotificationSink
als Uebergang; RocketChat/Telegram folgen spaeter.
- Entfernt nebenbei libsodium 1.0.16, die einzige Registry-Nutzung im Build,
den HttpListener-Webhook und System.Web.HttpUtility (alles Linux-Hindernisse).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PolyTrader.App.csproj verwies per ProjectReference nach
..\..\LicenseLabrador\client-dotnet\... und baute damit nur auf einer
Maschine, auf der das Schwester-Repo danebenliegt. Auf dem Zielland-System
waere der Build fehlgeschlagen.
Stattdessen liegt das SDK als versioniertes Paket in lib/nuget und wird
ueber die NuGet.Config-Quelle "local" aufgeloest. Ein DLL-Verweis haette
nicht gereicht: das Paket traegt die transitiven Abhaengigkeiten
(BouncyCastle, ProtectedData, System.Text.Json) in seinen Metadaten.
packageSourceMapping bindet LicenseLabrador.* fest an den lokalen Feed,
damit ein gleichnamiges Paket auf nuget.org unseres nicht verdraengt
(Dependency Confusion).
Enthaelt ausserdem die bereits vorgemerkte Umbenennung
LicenseDialog.Validate -> ValidateKey: der alte Name verdeckte
ContainerControl.Validate() (CS0108), ein Aufruf ueber eine Form-Referenz
haette einen Netzwerk-Call ausgeloest statt zu validieren.
Build und Tests gruen (438 Tests).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Die urspruengliche Ideenliste (Menueleiste, sicheres Beenden, Modul-Aktivierung,
Watchdog, ClawdDotNet) ist vollstaendig abgearbeitet - UI-Slice 5 (039bc24),
Watchdog/Lizenz (ca750a0) und die ClawdDotNet-Uebernahme (bb103a5). Die Datei
wird als Nachweis mitgefuehrt, worauf diese Slices zurueckgehen; abgeloest wird
sie von docs/IDEENSAMMLUNG-Feldtest-2026-08.md, die auf diesen Dateinamen verweist.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Laufende Sammlung von Richards Beobachtungen beim Einsatz von PolyTrader, je Punkt
Beobachtung -> Befund (im Code geprueft) -> Ansatz, mit stabilen IDs (L-1, ACC-1 ...)
als Referenz fuer spaetere Umsetzungs-Chats. Hier wird bewusst NICHT umgesetzt.
Querschnitts-Erkenntnis: ACC-1, RF-1 und teilweise CT-3 haben dieselbe Ursache -
Module wurden mit Null-Stubs statt echter Datenquellen fertiggestellt und mit
"Zielland" zurueckgestellt. Zielland-gebunden ist aber nur das Schreiben (Orders,
Signing, On-Chain-Tx); Lesen (Data-/Gamma-API, Alchemy-Logs, Balance) ist es nicht.
Loest die abgearbeitete Liste Ideen-fuer-Mittwoch.txt ab.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Slices W-A/W-B/W-C und L-A aus UMSETZUNGSPLAN-Watchdog-LicenseLabrador-Integration.
Watchdog (Dead-Man's-Switch, externer Server):
- WatchdogHeartbeatService als BackgroundService + DI-Singleton; jeder Sendeversuch
gekapselt, ein Ausfall des Watchdogs beeintraechtigt PolyTrader nie.
- Eigene Implementierung statt Test-Client des Fremdprojekts: TLS-Pruefung bleibt
aktiv, http:// nur fuer localhost (Agent-Token nicht im Klartext ins Netz).
- Status aus dem App-Log abgeleitet (Error mit 5-Minuten-Sticky-Fenster, entprellt),
Lifecycle-Events started/stopping.
- Konfiguration in ServerSettings; Agent-Token [Browsable(false)] mit maskierter
Eingabe + Statusanzeige, bei gesetztem Master-Key verschluesselt (enc:v1:).
Lizenz (LicenseLabrador, Ed25519):
- LicenseGate.RunStartupGate prueft beim Start; bei ungueltiger Lizenz wird die
Modulliste leer gebaut, sodass nur die Core-Shell (Terminal/Einstellungen)
startet. Bewusst kein Environment.Exit - ein Trading-Bot darf nicht mitten im
Lauf hart sterben. TamperSuspected gilt als nicht nutzbar.
- LicenseDialog (partial + .Designer.cs) fuer Start- und Verwalten-Modus, mit
Hardware-ID zum Kopieren; Smoke-UI konstruiert beide Modi headless.
- Master-Key wird jetzt VOR dem Host-Build geladen, da auch der Lizenzschluessel
entschluesselt werden muss; derselbe TerminalLogger wird als Singleton
weitergereicht, damit die Startmeldungen im Terminal-Fenster erscheinen.
Der Lizenz-SDK-Client wird per Cross-Repo-Projektreferenz auf
..\..\LicenseLabrador eingebunden, damit SDK-Fixes ohne Kopie einfliessen.
484 Zeilen Tests fuer den Heartbeat; Suite gruen (438 Tests).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Fenster-Menue: WindowMenu fuellt die oberste MenuStrip mit Top-Level-Eintraegen
nebeneinander (mit Icon) statt Untermenue "Fenster"; ModuleView.Icon zentral in der
App zugewiesen (AssignMenuIcons). Kein miFenster mehr im Launcher-Designer.
- Sicheres Beenden: ShutdownConfirmDialog (10s-Timer sperrt "Jetzt beenden", Abbrechen
jederzeit) via IModuleUiHost.RequestShutdown(). Nur der Launcher (Hauptprozess) bietet
"Beenden"; andere Fenster nur "Fenster schliessen" (kein App-Shutdown, Module laufen
weiter). Launcher-Schliessen-X routet ueber dieselbe Abfrage.
- Modul-Aktivierung (restart-basiert): ServerSettings.DisabledModules, in Program.Main
vor der DI-Registrierung gefiltert -> deaktivierte Module werden nicht geladen.
Dashboard-Tab "Module" zeigt Status + schaltet um (Hinweis: greift nach Neustart).
Optionaler IPolyTraderModule.GetActivationBlocker fuer "nicht aktivierbar"-Info.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Geschlossene Trades: Zeilenfaerbung nach PnL-% (TradeRowColoring, pur+getestet: <0 rot,
0-10% hellgruen, >10% gruen) via DataBindingComplete. Filter-Panel (Designer): Markt (Text),
Master-Trader (Combo, dynamisch), Ergebnis (Alle/Gewinner/Verlierer), Von/Bis (optionale
DateTimePicker mit Checkbox), Zuruecksetzen. Summary zeigt gefiltert/gesamt.
- Neuer Tab 'Offene Trades' (OpenTradesView, designerfaehig): alle offenen Positionen aus dem
Laufzeit-State mit Entry/Aktuell/Wert/Buchgewinn/-% und Status (offen/Exit laeuft), Zeilenfaerbung
nach Buchgewinn-%, Summenzeile. In CopyTradingMainForm zwischen Master-Trader und Geschlossene eingehaengt.
- Master-Trader-Grid: AutoSizeColumnsMode=Fill + FillWeights -> Spaltenbreiten teilen sich immer die
Breite (Fix der 'verbuggten' Breiten); RowHeader war bereits aus.
Tests: +8 (TradeRowColoring-Schwellen). Build 0 Fehler, 396 Tests gruen, --smoke-ui gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ShellUiHost injiziert das gemeinsame 'Fenster'-Menue beim Oeffnen zentral in jedes Fenster
(nur wenn keins eigenes vorhanden ist, z.B. Launcher). Damit erscheint das Menue auf allen
Core- und Modul-Fenstern ohne Achtfach-Designer-Duplikat, und jedes kuenftige Fenster bekommt
es automatisch. Inhaltliche Controls bleiben designerbasiert; das Nav-Menue ist Shell-Chrome.
Tests: +3 (WindowMenu.Populate: Inhalt Launcher/Views/Beenden, aktuelles Fenster fett+angehakt,
offenes angehakt, Klick navigiert). 389 Tests gruen, --smoke-ui gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- IModuleUiHost (Core) um Navigation erweitert: Views/IsOpen/OpenView/ActivateMain/OpenStateChanged
+ optionales Icon je ModuleView. So kann JEDES Fenster (auch Modul-Fenster, die nur Core kennen)
das gemeinsame Fenster-Menue bauen.
- WindowMenu (Core): baut das 'Fenster'-Dropdown (Launcher + alle Views + Beenden), haakt offene
Fenster an, markiert das aktuelle fett; Neuaufbau beim Aufklappen.
- ShellUiHost: SetMainWindow/ActivateMain; oeffnet ALLE Fenster jetzt MAXIMIERT (Vorgabe).
- Launcher: alle Modul-/Core-Buttons STATISCH im Designer (btn_copytrading/-resolutionfarming/
-supervisor ergaenzt), an View-IDs gebunden; fehlt eine View -> Button deaktiviert. Dynamischer
Laufzeit-Anhang ENTFERNT -> kein doppelter Accounting-Button mehr; leerer btn_accounting_Click raus.
Datei/Beenden -> Fenster-Menue (WindowMenu). Launcher startet maximiert (Sizable, MinSize 1280x720).
Build 0 Fehler, --smoke-ui alle 6 Views + Launcher gruen. Fenster-Menue auf den uebrigen Fenstern folgt (1b).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RF-UI designerfaehig (Richards Vorgabe, letzter code-only-Altbestand):
- ResolutionFarmingMainForm auf partial + .Designer.cs umgestellt (4 Tabs Kandidaten/
Positionen/Historie/Settings, alle Controls im Designer; Verhalten unveraendert).
S-3 Counterfactual ('Was waere aus abgelehnten BUYs geworden?'):
- CounterfactualJob (alle 6h, API-gedrosselt): nimmt Rejected-BUY-Entscheidungen mit
abgelaufenem MarketEndDate aus dem Journal, prueft die Marktaufloesung
(ICounterfactualResolutionSource; live = Adapter um CheckMarketResolutionAsync) und
speichert IsWinner + hypothetischen PnL/Share (CounterfactualMath, pur) nach
sup_counterfactuals (unique je DecisionId -> idempotent). Migration generiert+angewendet.
- Agent-Tool query_counterfactuals + UI-Tab 'Counterfactual' (via Designer).
S-3 Threema-Tagesbericht:
- DailyReportService: taeglich zur konfigurierten Stunde (OPT-IN via
POLYTRADER_SUPERVISOR_DAILY=0-23) laesst der Agent einen 24h-Kurzbericht erstellen
(KPIs je Modul, Fehler, Reject-Haeufungen), sendet via Threema und legt ihn als
sup_report ab. Ohne OpenRouter-Key: stiller Skip mit Log.
Tests: +7 (CounterfactualMath, Job aufgeloest/unaufgeloest/idempotent, Tagesbericht
mit/ohne Key). Build 0 Fehler, 367 Tests gruen, --smoke-ui alle 5 Views gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Das Dashboard ist keine stumpfe Trade-Liste mehr, sondern ein Auswertungs-Fenster:
- ToolStrip (via Designer): Scope-Filter Konto/Modul/Live-Demo/Zeitraum + Aktualisieren.
- TabControl mit 2 Tabs:
- Dashboard: KPI-Kacheln (Netto-PnL/Winrate/Trades/O-PnL/Profit-Faktor) + 3 Charts
(Equity-Kurve, PnL je Modul, PnL je Tag) fuer den gewaehlten Scope.
- Tradehistorie: gefilterte Trade-Liste (Spalten via Designer) + Suche + Gewinner/Verlierer.
- Charts via ScottPlot CORE-Paket (nur SkiaSharp, .NET-nativ) -> als Bitmap in PictureBoxen
gerendert; KEINE OpenTK/.NET-Framework-Transitiven (bewusst nicht ScottPlot.WinForms).
- Auswertungslogik pur in TradeAnalytics (getestet). In-Memory-Filter auf gecachtem Recent-Set.
- Smoke-UI konstruiert die DashboardView jetzt direkt -> verifiziert das Chart-Rendering headless.
Build 0 Fehler, 331 Tests gruen, --smoke-ui: [OK] core.dashboard konstruiert (inkl. Charts).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- TerminalView: ContextMenuStrip (Kopieren/Alles auswaehlen/Alles kopieren/Terminal leeren)
am rtbTerminal - macht das Kopieren entdeckbar (Ctrl+C funktioniert zusaetzlich nativ).
- JobsView: ToolStrip 'toolStripJobs' (docked Top) mit Starter-Button 'Aktualisieren'
(dgvJobs.Refresh) - weitere Job-Steuerelemente folgen nach und nach.
Beide via Designer (.Designer.cs), Logik im Code-Behind. Build 0 Fehler, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Settings: neuer Toolbar-Button 'Master-Key erzeugen' (Tab General Settings, via Designer).
Erzeugt zufaelligen 32-Byte-AES-Key -> master.key (gitignored), nur aktiv wenn KEIN Key
existiert (Env-Var oder Datei), Lockout-Schutz + Backup-Warnung, danach deaktiviert.
- Einbezogen: laufende Designer-Umstrukturierung (SettingsView/LauncherForm: Button-Bilder
aus Properties.Resources statt eingebettet; dgv_accountlist im Launcher; DashboardView.resx).
- docs/steuer: US-CPA-Fragebogen als PDF.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- F5: Startwarnung, wenn der DB-Connection-String kein SslMode erzwingt (String selbst wird
nie geloggt). Eure Connection enthaelt bereits SslMode -> Warnung bleibt aus.
- F6: geprueft - keine Secret-Werte in Logs (nur Vorhandensein-Flags/Fehlermeldungen).
- Sicherheitskonzept: Status F1-F7 dokumentiert.
Build 0 Fehler, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Behebt den kritischsten Befund (Klartext-Private-Keys in remote-gehosteter MySQL):
- SecretProtection (Core/Security): AES-256-GCM, authenticated. Master-Key AUSSERHALB der DB
(env POLYTRADER_MASTER_KEY, sonst gitignorierte master.key). Format enc:v1:base64(nonce|tag|ct).
Alt-Klartext (ohne Praefix) wird gelesen und beim Speichern verschluesselt (selbstheilend).
Ohne Master-Key: Passthrough + deutliche Startwarnung (kein stiller Sicherheitsverlust).
- EncryptedStringConverter (EF ValueConverter) auf core_accounts.PrivateKey/ApiSecret/ApiPassphrase;
Spalten 256->512 verbreitert (Migration EncryptAccountSecretsWidenColumns, offline generiert).
- Program.cs: Master-Key vor der Hydration laden; nach Start einmalige/idempotente Re-Encryption
vorhandener Klartext-Credentials. Auch in --smoke-ui verdrahtet.
- CoreDbContextFactory nutzt jetzt fixe Server-Version (offline-Migrationsgenerierung, kein DB-Zugriff).
13 neue Krypto-Tests (Round-Trip, Nonce-Frische, Manipulations-/Falscher-Key-Erkennung, Passthrough,
Key-Formate). Build 0 Fehler, 324 Tests gruen, --smoke-ui ok (Warnung ohne Key wie erwartet).
AKTIVIERUNG (im Zielland): POLYTRADER_MASTER_KEY setzen (zufaelliger 32-Byte-Base64-Key, SEPARAT sichern!)
+ Migration anwenden (dotnet ef database update --context CoreDbContext). Danach Alchemy-/Mullvad-Secrets
aus F3 rotieren. WICHTIG: Master-Key-Verlust = Kein Zugriff auf die Keys mehr.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der auskommentierte redeem_markets.py-Aufruf uebergab Private-Key + Secrets als
Prozess-Argumente (in der Prozessliste sichtbar). War deaktiviert, aber latentes Risiko
(reaktivierbar/falsches Muster) -> entfernt. Sicherheitshinweis fuer kuenftiges
Auto-Redeem hinterlegt (Secrets nie via argv; Redeem in .NET/Nethereum).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
F4: Newtonsoft.Json in der Threema-Lib von 11.0.2 (Advisory NU1903, high) auf 13.0.4
gehoben (= App-Version). Build ohne NU1903, 311 Tests gruen.
F3: hardcodierte Secrets aus ServerSettings-Defaults entfernt (Alchemy-API-Key in
PolygonRpcUrl, Mullvad-Account-ID) -> leere Defaults; echte Werte kommen aus
server_settings.xml (gitignored). WICHTIG (nicht im Code moeglich): beide Secrets
ROTIEREN, da sie in der Git-History liegen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root aufgeraeumt: alle Konzept-/Plan-/Fach-Dokumente nach docs/ verschoben,
organisiert nach Typ (wie fuer ein separates Docs-Repo vorgeschlagen, aber bewusst
in diesem Repo, damit Plan->umsetzende-Commits nachvollziehbar bleiben):
- docs/konzepte/ (KONZEPT-*)
- docs/umsetzungsplaene/ (UMSETZUNGSPLAN-*)
- docs/ideen/ (fruehe Ideen, Platzhalter)
- docs/pruefplaene/ (PRUEFPLAN-*)
- docs/steuer/ (Steuer-/Buchhaltungs-Doks, z.B. US-CPA-Fragebogen)
- docs/README.md (Index/Konventionen)
Getrackte Plaene als Rename verschoben (History erhalten); zuvor untracked Konzept-/
Plan-Dateien jetzt versioniert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase RF-1 (read-only): Scanner holt bald aufloesende Favoriten von einer
IFarmingMarketSource, bewertet sie und schreibt JEDEN Kandidaten (akzeptiert wie
abgelehnt inkl. Grund) nach rf_candidates. Platziert keine Orders.
- MarketScannerService.Evaluate (pur/statisch, voll getestet): Filterkette mit
Reject-Grund = erster Fehlschlag (Preisband -> Kategorie -> Blacklist ->
Aufloesungsfenster -> Netto-Edge nach Fees). Cluster-Key + Score immer berechnet.
- ScanAccountAsync: Beschaffung -> Bewertung -> Persistenz. BackgroundService-Loop
(12min) ueber Accounts mit Settings; fehlertolerant.
- IFarmingMarketSource + ScannedMarket-DTO trennen die (live-/API-gebundene)
Beschaffung von der Bewertung -> Pipeline ohne echte Gamma/CLOB-API testbar.
- NullFarmingMarketSource als Default: Modul laeuft ohne Live-Anbindung (die im
Zielland registriert wird) und produziert dann korrekt keine Kandidaten.
Hinweis: Zur Laufzeit fragt der Scanner rf_settings ab; bis die Migration angewendet
ist, faengt der try/catch den fehlenden-Tabelle-Fehler ab (nur Log). Migration bewusst
separat anzuwenden.
7 neue Tests (Evaluate-Faelle + Orchestrierung). Build 0 Fehler, 296 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Entities RfCandidate/RfPosition/RfClosedTrade (+ RfSettings aus Slice 1).
- ResolutionFarmingDbContext: Tabellen rf_settings/rf_candidates/rf_positions/
rf_closed_trades. Autoincrement-PKs (Identity) fuer Candidate/ClosedTrade von
Anfang an (Lehre aus dem CopyTrading-TradeId-Problem), zusammengesetzter PK
(AccountId,TokenId) fuer Positions, Indizes + Decimal-Precision.
- 4 Repos (Settings/Candidate/Position/ClosedTrade) mit serverseitigen Aggregaten
(RealizedPnlSince fuer Kill-Switch, CountOpenedSince fuer Tages-Drossel).
- Modul registriert DbContextFactory + Repos.
- Design-Time-Factory nutzt die fest gepinnte Server-Version -> Migration wurde
OHNE DB-Verbindung generiert (kein Zugriff auf die produktive DB). Anwenden per
'dotnet ef database update' bewusst im Zielland/lokal durch den Nutzer.
6 neue EF-InMemory-Repo-Tests. Build 0 Fehler, 289 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vorbereitung fuer das ResolutionFarming-Modul: FeeModel von
PolyTrader.Modules.CopyTrading.Logic nach PolyTrader.Core.Trading verschoben, damit
mehrere Strategiemodule dieselbe Fee-Logik nutzen koennen (Module duerfen nicht
voneinander abhaengen -> geteiltes gehoert in den Core). CopyTrading-Referenzen +
FeeModelTests auf den Core-Namespace umgestellt. Rein mechanisch, verhaltensneutral.
Build 0 Fehler, 244 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verifiziert den kritischen K1a-Fix mit Integrationstests statt nur per Review
(nach dem K3-Fehlplatzierungs-Fund):
- TraderMonitorService._clob -> IClobClient (verhaltensneutral); CleanupStaleOpenOrdersAsync
internal. FakeCopyTradeLogRepository ergaenzt.
- 2 Tests: Stale Order mit aktiver Leiter wird NICHT gecancelt; ohne Leiter WIRD sie
storniert (Kontrast, beweist Nicht-Vacuositaet).
Build 0 Fehler, 244 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Testabdeckung fuer den geldkritischen Engine-Pfad (bisher 0 Tests), da die
Fable-Guards zwischen Services entstehen und Unit-Tests sie nicht fangen:
- Engine._clob -> IClobClient (verhaltensneutral, DI registriert IClobClient bereits);
ProcessAccountOrderAsync internal. FakeMarketRepository/FakeAccountRepository ergaenzt.
- 7 Integrationstests (CopyTradingEngineTests) ueber gemockten CLOB: H3 BUY-Skip bei
ExitPending, Doppel-SELL-Guard, K3 System-Close (TraderId==0) schliesst Fremd-Position,
Fremd-Trader-SELL bleibt abgewiesen, H2 Cleanup schont Leiter (+ Kontrast ohne Leiter).
DABEI ECHTEN BUG GEFANGEN: Der K3-Fix aus Slice 3 sass an der falschen Stelle
(IsAuthorizedSell nach dem Position-Remove, Zeile ~643) – der eigentliche Ownership-Check
ist der fruehe inPortfolio-Lookup (Zeile 437, p.SourceTraderId == signal.TraderId), der
System-Signale schon vorher mit early return abwies. Fix jetzt am richtigen Ort; der
downstream-Check bleibt als Defense-in-depth. Ohne den Engine-Test waere das unentdeckt geblieben.
Build 0 Fehler, 242 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entscheidung Richard (Variante A): Re-buyt der Master, waehrend unsere SELL-Leiter
die Position abverkauft, wird der BUY uebersprungen statt zugekauft. Sonst stockte
der BUY die Position auf, die die Leiter danach inkl. neuer Shares zum alten Floor
verkauft (oekonomisch widerspruechlich). Die Leiter fuehrt den Exit sauber zu Ende.
Guard am Anfang des Engine-BUY-Pfads (spiegelt den bestehenden SELL-ExitPending-Guard).
Build 0 Fehler, 233 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
H4 – Rundungs-Dust-Reject-Schleife:
- SellLogic.RoundToTick (0.001, AwayFromZero, wie CalculateExactOrderAmounts). Die
Leiter platziert Preise gerundet -> usdc = size × Preis geht exakt auf (kein Dust).
- ProcessLadderAsync bricht ab, wenn pos.Size < MinShares (Dust-Rest gehalten,
ExitPending=false), statt endlos Sub-Minimum-Orders zu schicken.
M1 – GlobalPnl-Doppelzaehlung: in beiden Live-Close-Bloecken jetzt NUR innerhalb des
_processedClosures-Dedup-Guards gebucht (API-Lag zaehlte sonst doppelt).
M2 – TokenId in beiden Live-Close-Records gesetzt (sonst greift die Dedup nach Neustart nicht).
M3 (Minimum) – TradeId-Init: serverseitiges GetMaxTradeId() statt Full-Table-Find(_=>true).Max();
Fehlschlag wird laut geloggt statt still geschluckt. (Autoincrement-Migration bewusst als
Follow-up aufgeschoben – Schema-Aenderung an der Trade-Persistenz erst im Zielland live verifizieren.)
M4 – MongoExportParser ProfitTarget-Default 50 -> 9999 (Take-Profit bleibt dormant).
M6 – Fee-Satz (real oder Kategorie-Fallback, FeeModel.ResolveBps) in alle signierten Orders:
Engine-BUY, SELL-Leiter (Start/Step/Floor), PreRedeem (WSS + REST). API-gated, im Zielland verifizieren.
Doku – stale [Description]: ProfitTarget/SellFloorPct als IMPLEMENTIERT markiert.
Tests: +10 (RoundToTick, Dust-Abbruch, ResolveBps). Build 0 Fehler, 233 gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
K3 – Demo-Auto-Close bei Marktauflösung funktioniert wieder:
- System-SELLs (TraderId==0) sind vom Ownership-Check ausgenommen. Regel in reine
CopyTradingRisk.IsAuthorizedSell(signalTraderId, positionSourceTraderId) extrahiert
(System ODER Besitzer) und in der Engine genutzt. Vorher lehnte der Check jedes
System-Close ab (Copy-Positionen haben SourceTraderId>0) -> Demo-Positionen
schlossen bei Resolution nie, 30s-Loop feuerte endlos.
- Resolved-Cache (_resolvedDemoMarkets) in PollDemoExpirationsAsync: aufgeloeste
Maerkte werden nicht erneut angefragt (kein Log-Spam / keine unnoetige API-Last).
M5 – Auto-Pause in der Demo-Phase nicht mehr wirkungslos:
- Anzeige-Spalten (CopyPnl30d etc.) zeigen Live-Kennzahlen, sobald vorhanden, sonst
Demo-Kennzahlen -> Demo-Validierung ist sichtbar statt leer.
- Harte Auto-Pause wirkt bewusst NUR auf Live-Ergebnissen.
- Kadenz: stuendlicher Light-Check (Auto-Pause) statt nur alle 12h; schwere
History-Analyse bleibt 12h (schliessen sich pro Tick aus, kein Doppellauf).
Tests: 5 neue (IsAuthorizedSell). Build 0 Fehler, 223 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ruhende GTC-Leiter-/MakerEntry-Orders ueberleben Neustarts auf dem CLOB, der
Verwaltungszustand (ExitLadders/ExitPending/PendingOrderTimestamps) ist transient.
Ohne Bereinigung liefe die Engine gegen Waisen-Orders (Doppel-Leiter, Kaskaden).
- StartupOrderReconciliationService (IHostedService): storniert beim Start je
Live-Account alle offenen CLOB-Orders; danach entscheidet die Engine sauber neu.
Registriert als ERSTER Modul-HostedService (nach Hydration, vor Monitor/Engine),
pro Account fehlertolerant.
- GetOpenOrdersAsync: assetId jetzt optional (default "") -> ohne Filter ALLE
offenen Orders des Accounts. Signaturneutral (HMAC geht ueber Pfad ohne Query),
rueckwaertskompatibel fuer die bestehenden per-Asset-Aufrufer. IClobClient +
FakeClobClient nachgezogen.
Hinweis: "/data/orders ohne asset_id = alle Orders" ist API-gated und im Zielland
live zu verifizieren (wie M6).
Tests: 3 neue (cancelt alle Orders je Live-Account, ueberspringt Demo/credential-los,
no-op ohne offene Orders). Build 0 Fehler, 218 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wer darf die ruhende Leiter-Order anfassen? Nur die Leiter selbst.
- H1 (Race): StartLadderAsync macht ZUERST einen atomaren Claim
(ExitLadders.TryAdd). Master-SELL (Engine) und Profit-Target (Sync) sind
damit idempotent – kein Doppel-GTC / keine Fehlerkaskade. Verliert ein
Aufrufer den Claim, wird die (evtl. von der Engine entfernte) Position als
ExitPending zurueckgestellt – kein Waise. Order-Fehler gibt den Claim zurueck.
- K1a (Floor-Deadlock): CleanupStaleOpenOrdersAsync ueberspringt Keys mit
aktiver Leiter (ExitLadders.ContainsKey) – cancelt die Floor-Order nicht mehr.
- K1b (Floor-Robustheit): ProcessLadderAsync prueft am Floor via GetOpenOrders,
ob die SELL-Order noch ruht; falls nicht (Cleanup/extern/Teil-Fill), neu
platzieren statt bis zum Neustart unverkaeuflich zu haengen.
- H2 (Engine-Cancel): Pre-Signal-CancelConflictingOrders wird uebersprungen,
wenn fuer den Markt eine Leiter aktiv ist – zerschiesst die Leiter-Order nicht.
Tests: 8 neue Integrationstests (SellLadderService ueber gemockten IClobClient):
atomarer/paralleler Claim, Waisen-Schutz, Claim-Rueckgabe, Floor-Neuplatzierung,
Floor-Halten bei ruhender Order, Leiter-Ende bei gefuellter Position.
Verifikation: Build 0 Fehler, 215 Tests gruen, --smoke-ui ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Ist TrackedTrader.MakerEntry gesetzt, wird der BUY OHNE Preisaufschlag als
ruhendes GTC-Limit am Master-Preis platziert (statt teurem Taker-Fill via GTD),
spart Fees/Spread bei langsamen Mastern. Nutzt die getestete
CopyTradingRisk.CalculateBuyOrderPrice (0 % Aufschlag). Default aus -> dormant.
(Ohne Orderbuch ist der Master-Preis die Naeherung fuer den Bid; echte
Bid-Platzierung + Nichtfill-Eskalation folgen mit dem Market-Channel/Zielland.)
207 Tests gruen. Build/Smoke gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- SellLogic.IsProfitTargetReached (pure, getestet): currentPrice >= entry*(1+pct/100);
pct<=0 oder Default 9999 = inaktiv.
- Ladder-Start-Logik konsolidiert: SellLadderService.StartLadderAsync ist jetzt die
gemeinsame Quelle fuer Master-SELLs (Engine) UND eigene Exits (Profit-Target).
SellLadderService als Singleton+Hosted registriert; Engine + TraderMonitor
injizieren es. Engine-SELL-Block ruft nur noch StartLadderAsync (verhaltensgleich).
- TraderMonitorService.CheckProfitTargetsAsync im 30s-Live-Sync: erreicht eine
Live-Position ihre Schwelle, Exit ueber die Leiter (Startlimit = aktueller Preis,
ExitReason "Profit Target"). PreRedeemLimit hat Vorrang. Dormant, da ProfitTarget
projektweit 9999.
169 Tests gruen. Build/Smoke gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- SELL-Spam-Blockade greift nur noch bei kürzlichem SELL: PendingOrderTimestamps
bekommt eine Side ("BUY"/"SELL"); ein vorheriger BUY blockiert einen legitimen
schnellen SELL des Masters nicht mehr (alle Schreibstellen aktualisiert).
- GlobalPnl: PollClosedAccountsAsync addiert den realisierten PnL jetzt auch
(wie PollLiveAccountsAsync) -> Anzeige driftet nicht mehr.
- Demo-ClosedTrade erhält TokenId (der _processedClosures-Preload filtert darauf;
fehlte -> Duplikat-/Dedup-Risiko nach Neustart).
163 Tests gruen. Build/Smoke gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Behebt die April-Verlustquelle: SELLs wurden als Market-Order mit 0.01-Limit ins
oft leergeraeumte Orderbuch geworfen -> wir wurden zur Exit-Liquidity. Jetzt:
GTC-Limit nahe am Master-Exit, stufenweises Nachpreisen bis zum Floor.
- Position.ExitPending (runtime-only, EF-ignoriert): Position wird bei SELL NICHT
mehr optimistisch entfernt, sondern als ExitPending zurueckgestellt (kein
Doppel-SELL, Limits rechnen korrekt; Sync schliesst nach bestaetigtem Fill).
- CopyTradingState.ExitLadders + ExitLadderState (transienter Leiter-Zustand).
- SellLogic (pure, getestet): FirstLimit (HF-fest/prozentual), Floor (SellFloorPct),
NextPrice (relative Stufe, auf Floor geclamped), IsAtFloor, LadderStepPct (3%),
LadderIntervalSeconds (HF 20s / sonst 120s).
- SellLadderService (BackgroundService): senkt offene Exit-Limits stufenweise
(cancel via CancelConflictingOrdersAsync -> tiefer neu platzieren), am Floor ohne
Fill Position halten + Threema-Benachrichtigung. Fills erkennt der bestehende Sync.
- CopyTradingEngine SELL-Live-Pfad ruft die Leiter; Demo-Pfad unveraendert.
Doppel-SELL-Guard ueber ExitPending. Umfangreiches Logging (kein Live-Test moeglich).
163 Tests gruen. Build/Smoke gruen. Backup-Rollback: Commit 1dffc9e.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Neue pure Klasse TradeMath (Logic/): ExitValue, RealizedPnl, PnlPercent
(Null-Guard), WeightedAverageEntryPrice (Div-durch-0-Schutz).
- CopyTradingEngine ruft sie jetzt im Demo-Close-PnL und bei der Positions-
Aufstockung (Demo + Live, gewichteter Einstiegspreis) – verhaltensneutral.
- TradeMathTests (6 Faelle: Gewinn/Verlust, %-Basis, 0-Kapital/0-Size-Guards).
Gesamt 160 Tests gruen. Build/Smoke gruen. (Phase-0.1-SELL-Wiring weiterhin
bewusst zurueckgestellt bis zum Server-Test; pure Leiter liegt getestet bereit.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Fix (Richard): MaxBuyPrice-Skalen-Korrektur analog PreRedeemLimit
(Migration FixMaxBuyPriceScale: Werte > 1 wie 98.0/99.0 -> /100 = 0.98/0.99;
auf MySQL angewendet). Cap greift bei den betroffenen Accounts jetzt wieder.
Beschreibung des Feldes um den Skalen-Hinweis ergaenzt.
- Testnetz erweitert: reine Klasse BlockchainSubscription (Logic/) fuer das
Alchemy-Abo (PadAddress + Filter-Batching in 3er-Chunks, Buy=Topic3/Sell=Topic2
je Chunk). AlchemyWebsocketService ruft sie jetzt (verhaltensneutral;
Konstanten + lokale Methoden entfernt). BlockchainSubscriptionTests: 13 Faelle
(Padding, Chunk-Anzahl 0/1/3/4/6/7, Topic-Zuordnung, CTF-Adresse/Topics).
Gesamt 137 Tests gruen. Build/Smoke gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ziel (Richard): vor den CLOB-Eingriffen ein umfangreiches Testnetz, damit künftige
Änderungen keine neuen Fehler einschleusen. Reiner, verhaltensneutraler Umbau –
alte Version liegt als Rollback in Git (Commit 38f609e), siehe .agents/rules/clob.md.
- Neue pure Klasse CopyTradingRisk (Logic/): CalculateBuyOrderPrice (HF-fest /
prozentual, gedeckelt durch MaxBuyPrice + harte 0.99), ResolveTimeBucket/
TimeLimitPct/TimeBucketLabel/IsPositionInBucket (Zeitfenster-Exposure),
MaxPerMarket (Markt-Budget inkl. Low-Balance-Bypass-Stufen).
- CopyTradingEngine BUY-Pfad ruft diese Funktionen jetzt statt Inline-Mathematik
(1:1-Semantik, dedupliziert die doppelte Order-Preis-Berechnung).
- CopyTradingRiskTests: 38 Fälle über alle Zweige/Grenzwerte (HF vs. normal,
MaxBuy-/0.99-Deckel, Bucket-Grenzen 6/24/72h, null/expired Expiry,
Balance-Stufen 150/500). Gesamt 124 Tests grün.
Fix: PreRedeemLimit-Skalen-Korrektur (Migration FixPreRedeemLimitScale): Alt-Werte
> 1 (z. B. 99.5) werden /100 (0.995); 0 bleibt deaktiviert. Auf MySQL angewendet.
Build/Smoke grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Umsetzung des Fable-Plans, Start mit dem risikoarmen Settings-Fundament
(kein Hot-Path/CLOB-Verhalten geändert):
- Alle Copytrading-Settings (alt + neu) haben jetzt [Description]/[DisplayName] ->
im PropertyGrid als Erklärung sichtbar (Richards Vorgabe). Test erzwingt, dass
jede einstellbare Option eine Beschreibung trägt.
- ProfitTarget-Default -> 9999 (praktisch deaktiviert); Migration setzt zusätzlich
bestehende Zeilen per SQL auf 9999 (Entscheidung 2). Take-Profit-LOGIK folgt.
- Neue Account-Settings (noch nicht verdrahtet, für Phase 0.1/1.3/2):
SellFloorPct (15), MaxSpreadPct (5), MinSellRatioPct (10).
- Neue Master-Trader-Settings: AutoPauseEnabled (Default AN, per Master abschaltbar,
Entscheidung 3) + MakerEntry (Default aus, Entscheidung 4).
- EF-Migration AddCopytradingBehaviorSettings (neue Spalten + sinnvolle Defaults
fuer Bestandszeilen) erstellt und auf MySQL angewendet.
- Erklärung dokumentiert einen gefundenen Skalen-Verdacht: PreRedeemLimit wird
gegen den 0-1-Preis verglichen; Alt-Werte 99.5 triggern nie (-> ggf. 0.995).
Tests: 86 gruen. Build/Smoke gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- MasterTraderAnalyticsJob + PersistenceService von services/ nach
src/PolyTrader.Modules.CopyTrading/Services/ verschoben und in
CopyTradingModule.RegisterServices registriert (reiner Move). Beide sind
copytrading-spezifisch (Master-Trader-Historie bzw. Persistenz der
geschlossenen Copytrades ueber den Modul-Channel; Dual-Write in Core-Log bleibt).
- Program.cs: die zwei Hosted-Service-Registrierungen entfernt.
- appsettings.json: Logging-Sektion ergaenzt -> EF-Core-Command-Logging auf
Warning (kein SQL-Spam mehr; --smoke-ui zeigt 0 "Executed DbCommand"-Zeilen).
Damit liegt die gesamte Copytrading-Logik im Modul; App/Core enthalten nur noch
generische Infrastruktur + Startup-Hydration + CLI-Tools.
Build gruen, 48 Tests gruen, --smoke-ui gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Beide Listener sind copytrading-spezifisch (überwachen die getrackten Master-
Trader bzw. Auto-Redeem nach Copytrading-Settings) und werden jetzt vom Modul
besessen statt von der App. Reiner Move, keine Logikänderung.
- services/AlchemyWebsocketService.cs + services/PolymarketWssClient.cs
-> src/PolyTrader.Modules.CopyTrading/Services/ (Namespace bleibt transitional).
- CopyTradingModule.RegisterServices registriert nun beide Hosted Services sowie
IBlockchainWssClientFactory->AlchemyWssClientFactory (Core-WSS-Infra, nur vom
Copytrading-Blockchain-Listener genutzt).
- Program.cs: die drei Registrierungen entfernt (WSS-Factory + 2 Hosted Services)
+ ungenutztes using PolyTrader.Core.Streaming.
- WSS-Verbindungsinfrastruktur (AlchemyWssClient/BlockchainWss) bleibt in Core.
DI-Auflösung unverändert (gleicher Container). Build grün, --smoke-ui grün.
Laufzeit-Verifikation der WSS-Verbindungen: Server-Test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Konsistent zum Master-Trader-Tab bekommen die beiden anderen Tabs eine ToolStrip
mit ihren Aktions-Buttons:
- ClosedTradesView: ToolStrip mit "Aktualisieren"; Kurzauswertung wandert in eine
untere Statusleiste (lblSummary).
- AccountSettingsView: ToolStrip mit Account-Auswahl (ToolStripComboBox) +
"Speichern"; Hinweistext in untere Statusleiste (lblHint).
- Beide bleiben Designer-basiert (Size statt ClientSize, da UserControl).
Hinweis: Separate Einzelview-Registrierungen existieren nicht mehr (bereits in
c3d7e41 auf die eine View copytrading.main konsolidiert); die drei UserControls
sind ausschliesslich Tab-Inhalte.
Verifiziert: Build gruen, --smoke-ui gruen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Statt je Ansicht ein eigenes Fenster (3 Launcher-Buttons) gibt es jetzt EIN
Modul-Fenster mit Tabs – wie im alten PolyTrader. Skaliert sauber, wenn weitere
Module dazukommen (ein Button je Modul).
- MasterTradersView/ClosedTradesView/AccountSettingsView: von Form -> UserControl
(Tab-Inhalte); Designer-Root auf Size statt ClientSize/Text/MinimumSize.
- Neu: CopyTradingMainForm (Designer) mit TabControl + 3 TabPages, hostet die
drei UserControls; Initialize(IServiceProvider) versorgt jeden Tab per DI.
- CopyTradingModule.RegisterUi registriert nur noch EINE View "Copytrading".
Verifiziert: Build grün, --smoke-ui grün (eine View copytrading.main +
Launcher konstruieren fehlerfrei, 3 Accounts / 32 Trader hydriert).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Der VS-WinForms-Designer braucht einen parameterlosen Konstruktor, um eine Form
zu instanziieren. Die drei Views hatten nur einen DI-Ctor -> Designer hätte sie
nicht öffnen können. Umgestellt auf das Core-View-Muster (DashboardView):
- Parameterloser Ctor: InitializeComponent() + Event-Wiring.
- Initialize(deps): Abhängigkeiten setzen + Daten laden.
- Felder nullable + Null-Guards in den Handlern.
- CopyTradingModule.RegisterUi: new View() + view.Initialize(...) statt DI-Ctor.
Verifiziert: Build grün, --smoke-ui grün (3 Accounts / 32 Trader, alle Views OK).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die drei Modul-Views wurden von komplett code-first (alle Controls im Konstruktor)
auf das Standard-WinForms-Designer-Muster umgestellt (je X.cs + X.Designer.cs mit
InitializeComponent), damit sie im Designer geöffnet und bearbeitet werden können:
- ClosedTradesView, AccountSettingsView, MasterTradersView: alle wichtigen
Steuerelemente (Panels, DataGridView mit expliziten Spalten via
AutoGenerateColumns=false, PropertyGrid, ToolStrip, GroupBox, CheckedListBox,
ComboBox, Buttons, Labels, Splitter) sind jetzt Designer-Felder.
- Konsistent mit den Core-Views (DashboardView-Muster): Layout im Designer,
Zellformate/Event-Wiring/Datenbindung im Code.
Verifiziert: --smoke-ui grün (3 Accounts / 32 Trader; alle Views + Launcher OK).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ursachen (App startete aus bin/ bzw. per Doppelklick ohne UI):
1. appsettings.Local.json (MySQL-Connection) wurde NICHT ins Output kopiert und
nur relativ zum Arbeitsverzeichnis geladen -> leere Connection -> Pomelo fiel
auf localhost:3306 zurueck -> "Connect Timeout expired".
2. ServerVersion.AutoDetect(conn) oeffnet beim Options-Bau eine blockierende
DB-Verbindung -> haengt/crasht den Start, wenn die DB nicht erreichbar ist.
3. CopyTradingEngine.StartAsync lud den MarketCache ungeschuetzt -> DB-Fehler
riss AppHost.Start() ab, bevor die UI erschien.
Fixes:
- csproj: appsettings.Local.json mit ins Output kopieren (CopyToOutputDirectory).
- Program: UseContentRoot(AppContext.BaseDirectory) -> Config wird immer neben
der EXE gesucht (Main + Smoke-Test).
- ServerVersion fest gepinnt: DatabaseServerVersion.Value = MariaDB 11.8.6 (wie
am Server erkannt); AddCorePersistence + CopyTradingModule nutzen sie statt
AutoDetect. Kein blockierender Connect mehr beim Start.
- CopyTradingEngine-Preload in try/catch: DB-Fehler bricht den Start nicht mehr ab.
- Neuer Diagnose-CLI --db-version (gibt @@version aus).
Verifiziert: --smoke-ui aus fremdem Arbeitsverzeichnis laeuft gruen
(3 Accounts / 32 Trader hydriert, alle Views + Launcher OK).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- KRITISCH: Host.CreateDefaultBuilder lädt appsettings.Local.json nicht (nur
appsettings.json + appsettings.{Environment}.json). Dadurch war
Database:MySqlConnectionString zur Laufzeit leer -> Pomelo fiel auf
localhost:3306 zurück ("Connect Timeout expired"), die GUI-App hätte am
Server nie mit MySQL verbunden. Fix: appsettings.Local.json explizit per
ConfigureAppConfiguration ergänzen (in Main und im Smoke-Test).
- Neuer CLI-Modus --smoke-ui: baut einen minimalen Host, hydriert den State
aus MySQL und konstruiert jede registrierte View + den Launcher (ohne
Message-Loop / Trading-Services). Deckte den obigen Bug auf.
- Verifiziert: 3 Accounts / 32 Trader hydriert; alle 3 Modul-Views + Launcher
konstruieren fehlerfrei mit echten Daten.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>