Files
claude-regelwerk/.vault-tools/trading-plattform-pruefung/LIESMICH.md
T
Pascal MichelandClaude Opus 5 ea278dc24f Automatischer Push: 46 Datei(en) geändert
- .claude/agents/planer.md
- .claude/skills/plan-executer-pruefung/SKILL.md
- .claude/workflows/plankritik.js
- .claude/workflows/planung.js
- .claude/workflows/pruefung.js
- .claude/workflows/verbrauch.js
- .claude/workflows/welle-mit-pruefung.js
- .vault-tools/plan-kopie/LIESMICH.md
- .vault-tools/plan-kopie/plan_zeichen.py
- .vault-tools/plan-kopie/rot_nachweis.py
- .vault-tools/trading-plattform-pruefung/LIESMICH.md
- .vault-tools/trading-plattform-pruefung/abendkontrolle.py
- … und 34 weitere

Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-25 04:00:02 +02:00

36 KiB

type, status, title, summary, tags, created, updated
type status title summary tags created updated
resource active Trading Plattform: Prüfwerkzeuge des Koordinators fürs Dashboard Eigener Lauf mit echten Daten zum Dashboard der Trading Plattform — Vergleich der Endpunkte gegen Vollparse und pandas, zwei WebSocket-Verbindungen, Browser-Lauf und Wiederaufbau mit Playwright, gefahrlose Proben der zwei Skripte, Mutantenläufe. Entstanden 2026-09-17 (Teil 3b), erweitert 2026-09-18 (Teil 10: Anmeldung, Angriffsfälle, Beobachtung, Kerzenlatenz), bewusst nicht im Projekt-Repo.
vault-tools
trading-plattform
2026-09-17 2026-09-24

Prüfwerkzeuge fürs Dashboard der Trading Plattform

Koordinator-Werkzeuge, nicht fürs Repo. Sie starten nie den echten Broker: Das Probe-Backend läuft mit BrokerAttrappe und einem Wegwerf-Register unter /tmp, liest aber die echten Protokolle und den echten Katalog. Python-Teile laufen in WSL aus dem Projektordner, die Browser-Teile mit dem Windows-Python und Playwright (Chromium).

Datei Was sie tut Aufruf
pruef_teil3b.py Liste und Einzelansicht der Läufe gegen einen eigenen Vollparse, Kerzen gegen eine eigene pandas-Rechnung; --sabotage verfälscht je einen Wert und muss mit Exit 2 enden (sieben Fälle) wsl -d Debian -- bash -s -- pruef_teil3b.py alles [--sabotage zahl] < lauf_pruef.sh
pruef_ws.py, lauf_ws_probe.sh, start_probe_backend.py, start_probe.sh zwei WebSocket-Verbindungen am Probe-Backend müssen dieselben zeit-Werte sehen wsl -d Debian -- bash -s < lauf_ws_probe.sh
browserlauf.py bei 375, 768, 1024 und 1440 px: Zeilen in „Läufe", zwei Einzelansichten, Minuten- und Tageschart gezeichnet, kein waagerechter Scroll, keine Konsolenmeldung; schreibt Screenshots — ansehen Probe-Backend starten (wsl -d Debian -- bash -s 8145 2.0 < start_probe.sh, im Hintergrund), dann python -X utf8 browserlauf.py http://localhost:8145 <ausgabeordner>
wiederaufbau.py Backend beenden und neu starten, die Kopfzeile muss „Backend getrennt" und wieder „Backend verbunden" zeigen, ohne Neuladen; --ohne-neustart muss rot enden python -X utf8 wiederaufbau.py
skripte_probe.sh, abkuerzung_probe.sh --help, Lauf ohne Schalter, unbekanntes Argument und Abkürzungen von --ausfuehren — ausschließlich aus einem leeren Temp-Verzeichnis; die Übung selbst wird nie gefahren wsl -d Debian -- bash -s < skripte_probe.sh
mutanten_py.py, mutanten_ts.py Mutanten zu Teil 3b auf einer Kopie mit angewendetem Plan, je mit Fehlerzeile Pfad der Kopie als erstes Argument
real_pytest.sh volle Suite im echten Baum, mit Zählung der „Task was destroyed"-Meldungen wsl -d Debian -- bash -s -- -q < real_pytest.sh

Teil 10 (2026-09-18): Paper-Runner, Anmeldung, Härtung

Datei Was sie tut Aufruf
start_probe_zugang.py die echte App mit Attrappe, Wegwerf-Register und Wegwerf-Zugang (Benutzer probe, bekanntes Passwort, TOTP-Beispielgeheimnis der RFC-Literatur; beides in zugang.json der Ablage), auf Wunsch mit einer Paper-Statusdatei. Seit 2026-09-21 bricht es ab, wenn im Arbeitsordner eine config/secrets.toml liegt — erzeuge_app startete bis Paket S5 immer den echten Stille-Wächter, und eine Probe-Instanz im echten Projektordner hätte nach 180 s aufs Telefon geklingelt aus einer Kopie des Projektordners (ohne Geheimnisdatei) in WSL: PYTHONPATH=. python start_probe_zugang.py <port> <ablage> [mit-paperstatus]
angriffe.py 56 Fälle gegen Host-Positivliste, Origin, Sitzungszwang, Cookie-Attribute, Bremse, CSP und die anderen Header, WebSocket ohne Sitzung; Regressionsnachweis gegen das Backend vor Teil B: 45 rot python angriffe.py <basis-url> <ablage-mit-zugang.json>
browserlauf_zugang.py Anmeldeformular ohne Sitzung, falsche und richtige Anmeldung (frischer TOTP-Code), Name und „Abmelden" in der Kopfzeile, Strom, Karte „Paper-Betrieb", alle Ansichten unter der CSP, Abmelden und Neuladen, 375 px; protokolliert jede Antwort ab 400 mit Phase und Pfad (antworten-ab-400.json); --sabotage muss rot enden; Screenshots — ansehen (der Lauf fand so das GET /api/paper vor dem Tor und die unbeschrifteten Felder) python -X utf8 browserlauf_zugang.py http://localhost:<port> <ablage>/zugang.json <ausgabeordner> [--sabotage]
pruef_beobachtung_echt.py baue_beobachtung gegen NautilusEnv._beobachtung auf den echten IEX-Kerzen eines Tages, beide Seiten unabhängig gerechnet; Sabotage rot. Seit 2026-09-18 mit zweitem Teil: eine feste Aktionsfolge über alle fünf Stufen, Vergleich nach jedem Schritt bei gleichem Zustand (gemessen am 2026-09-17: 120 Beobachtungen bitgleich, davon 50 long, 50 short, Kontowert in allen ungleich dem Startkapital, Zähler in 60 größer null); --mutant-vorzeichen (Betrag statt Vorzeichen der Position) lässt genau die 50 Short-Beobachtungen rot fallen, während der erste Teil grün bleibt PYTHONPATH=. python pruef_beobachtung_echt.py JJJJ-MM-TT aus dem Projektordner
lies_paper_protokoll.py fasst ein Paper- oder Probe-Protokoll zusammen (Takte je Phase, Killswitch je Takt, frische Kerzen, erste Entscheidung, Orders, Schlussphase, Ende) python lies_paper_protokoll.py <jsonl>
handelstag_auswertung.py wertet einen Paper-Handelstag aus: Takte je Phase, frische Kerzen, Spanne Taktzeile gegen Minutenende (Obergrenze für „Kerze abrufbar"), Orders, Ende; mit --broker lesend die Orders des Paper-Kontos (Annahme bis Füllung aus created_at/filled_at gegen order_timeout_s, dazu die Teilspannen bis submitted_at und von dort bis zur Füllung — seit dem ersten Handelstag, an dem der Broker eine Order 8,7 s zwischen Annahme und Weitergabe liegen ließ und submitted_at allein das verschwiegen hätte; ein Hinweis ab der halben Grenze; Vorzeichen offener Positionen), mit --kerzen die Kosten je Order gegen den Schluss der letzten abgeschlossenen IEX-Kerze in Basispunkten. Am 2026-09-18 an den zwei Protokollen der Nacht erprobt (Probe: Spanne ausgelassen, weil die Kerzen gespielt sind) aus dem Projektordner: python handelstag_auswertung.py <protokoll.jsonl> [--broker] [--kerzen]
vorstart_pruefung.py liest vor dem Runner-Start: läuft schon ein Runner, Killswitch-Zustand im Register (nur Auskunft — der Start stellt nach der Neustartregel immer auf angehalten; ein Befund ist allein gesperrt), Paper-Konto glatt, Marktuhr des Brokers, eigene Uhr gegen den Date-Kopf des Brokers. Am 2026-09-18 fand der erste trockene Lauf einen Killswitch auf aktiv (Klick um 08:55 Uhr), den der Start überschreibt aus dem Projektordner: python vorstart_pruefung.py
runner_stand.py zeigt den Stand eines laufenden Paper-Runners aus seinem Protokoll: Zeilen je Art, Takte je Phase und Killswitch-Zustand, letzter Takt, Order- und Ende-Zeilen. Urteilt nicht und gibt keine Kontowerte aus. Am 2026-09-18 am Protokoll der Nacht erprobt (drei Zeilen: kopf, ereignis, ende); an einem Protokoll mit Takten noch nicht in WSL: python runner_stand.py [<protokoll.jsonl>], ohne Angabe das neueste *-paper.jsonl im Projektordner
protokoll_vergleich.py vergleicht zwei JSONL-Protokolle der Messwerkzeuge Wert für Wert (Bitgleichheit nach einem Umbau); trennt ABWEICHUNG, NUR NEU (neuer Schlüssel, kein Befund ohne --streng) und NUR ALT. Erprobt am 2026-09-18: Selbstvergleich 5.190 Werte ohne Befund, --sabotage (ein ULP) rot, der Ein-Jahres-Lauf mit OMP_NUM_THREADS=8 gegen den ohne 621 Abweichungen ab der dreizehnten Stelle python protokoll_vergleich.py <alt.jsonl> <neu.jsonl> [--ohne …] [--streng] [--sabotage]
probe_neu_einfrieren.py friert tests/fixtures/tage_t0_t1_referenz.json nur neu ein, wenn der Diff genau der vorhergesagte ist (neuer Schlüssel fenster_ausgelassen_pool in den Poolzeilen, geänderte Werte allein in der T1-Poolzeile und dort nur in den gelisteten Feldern); erprobt am 2026-09-18 an der Kopie mit angewendetem Plan B: 24 erlaubte Änderungen, 0 Befunde; --sabotage (ein ULP in einer T0-Zeile) rot, und --schreiben schrieb dann nichts in WSL aus der Projektwurzel: python probe_neu_einfrieren.py [--schreiben] [--sabotage]
ntfy_probe_server.py nimmt ntfy-Meldungen auf 127.0.0.1 entgegen und schreibt sie als JSONL mit (Titel, Priorität, Tags, Text; vom Authorization-Kopf nur Schema und Länge) — für den Lauf mit echten Daten zu Paket D ohne echtes Thema; --status 403 lässt jede Zustellung scheitern python ntfy_probe_server.py <port> <mitschrift.jsonl> [--status 200] [--verzoegerung 0.0]
handabruf_kerzen.py Alter der jüngsten AAPL-Minutenkerze per REST (feed iex oder sip) mit Urteil FRISCH/ALT — die Messung vor dem ersten Paper-Tag; nachts nur ein Funktionsnachweis. Gemessen 2026-09-18 nachts: iex antwortet in 0,5 s, sip mit 403 „subscription does not permit querying recent SIP data" aus dem Projektordner: `TZ=Europe/Berlin python handabruf_kerzen.py [iex

Seit 2026-09-18 kennen angriffe.py und browserlauf_zugang.py https. angriffe.py erwartet je nach Schema der Basis-URL Secure am Cookie und Strict-Transport-Security (https) oder beides nicht (http), dazu unter https keine Antwort 200 auf Klartext; --ca <pem> nennt das Zertifikat, dem vertraut wird (geprüft, nicht abgeschaltet). browserlauf_zugang.py --selbstsigniert schaltet die Zertifikatsprüfung des Browsers ab. Regressionsnachweis vom selben Tag: gegen ein TLS-Backend mit einem Mutanten von sicherheit.py (ohne Secure, ohne HSTS) fielen genau die vier https-Fälle rot, Exit 2; Grundlinie über http 59 Fälle, über https 60. Läuft das Backend auf einem anderen Rechner, fährt man angriffe.py dort in einem Wegwerf-Container mit --network host und legt die drei Dateien der Ablage (zugang.json, status.json, anmeldungen.jsonl) per Verknüpfung in einen Ordner — das Werkzeug braucht Dateizugriff auf die Ablage des Backends.

Paket F (2026-09-20): Produktivbetrieb als Dienst

Datei Was sie tut Aufruf
pause_echtlauf.py Tagesverlust-Schutz in der Pause auf den echten IEX-Kerzen eines Tages: rechnet aus den Rohkerzen vor, in welchem Takt die Grenze reißen muss (long und short, Grenze bei der Hälfte des größten Tagesverlusts), und hält das gegen das Protokoll der echten PaperSitzung im Zustand angehalten; dazu die Gegenprobe ohne Position. Einziger Netzzugriff: die Kerzen, lesend; Meldungen gehen an einen mitschreibenden Transport. Gemessen am 2026-09-17: long Takt 6, short Takt 173, je erwartet gleich gemessen aus dem Projektordner in WSL: python pause_echtlauf.py JJJJ-MM-TT
dienste_stand.sh nur lesend: Unit-Dateien, is-enabled, Zustand, Startzeiten und letzter Exit-Code von Dashboard-Dienst und Runner, Zeitgeber, /api/gesund, Start von systemd, die letzten Journalzeilen beider Dienste, status.json und tagesstart.json ohne Kontowerte. Das Journal geht ohne sudo, wenn der Benutzer in adm oder systemd-journal ist (hier: ja); sonst nimmt das Skript sudo -S mit WSL_PW aus der Umgebung aus PowerShell: wsl -d Debian --exec bash /mnt/d/Claude/.vault-tools/trading-plattform-pruefung/dienste_stand.sh
hole_kerzen.py holt die echten IEX-Minutenkerzen eines Handelstags lesend und legt sie als JSON ab — die Eingabe für neustart_echtlauf.py. Gemessen am 2026-09-20 für den 2026-09-17: 390 Kerzen, byte-gleich mit dem Abruf des Abschlussprüfers aus dem Projektordner in WSL: python hole_kerzen.py JJJJ-MM-TT <ziel.json>
neustart_echtlauf.py der Tagesverlust nach einem Neustart mitten am Tag: rechnet aus den Rohkerzen vor, bei welcher Kerze die echte Grenze (0,2 Prozent) gegen den Tagesstart reißt und bei welcher gegen den Neustartkurs, und fährt dann zwei echte PaperSitzungen nacheinander mit gemeinsamer tagesstart.json, dazu die Gegenprobe ohne Datei. Kein Netz. Gemessen am 2026-09-20 auf den Kerzen des 2026-09-17 und 2026-09-18: mit Datei Riss bei der vorgerechneten Kerze (5, 150, 19), ohne erst bei 18, 173, 42 aus dem Projektordner in WSL: python neustart_echtlauf.py <kerzen.json>
ntfy_lesen.py liest über die Abfrage-Schnittstelle von ntfy zurück, was in der letzten Stunde unter dem Thema der Maschine ankam — Titel, Priorität, Zeit, erste Zeile. Schickt nichts und gibt das Thema nie aus, auch nicht in einer Fehlermeldung aus dem Projektordner in WSL: python ntfy_lesen.py
wiederanlauf_probe.ps1 beendet die Distribution hart (wsl --terminate) und misst, wann geplante Aufgabe, Distribution und Dashboard von selbst zurück sind. Ein laufender Runner stirbt mit — nur außerhalb der Handelszeit, nur mit -Ausfuehren (ohne den Schalter Exit 2, nichts getan). Während der Messung kein anderer wsl.exe-Aufruf, jeder Klient weckt die Distribution selbst. Gemessen am 2026-09-20: Rückkehr am nächsten Fünf-Minuten-Rasterpunkt, Dashboard 13 s danach powershell -File wiederanlauf_probe.ps1 -Ausfuehren

Paket H (2026-09-21): Kennzahlen nach Home Assistant

Datei Was sie tut Aufruf
ha_einrichten.py richtet in Home Assistant die Gegenstelle für den Hausmelder ein: acht Helfer mit dem Präfix trading_ und eine Automation mit Webhook-Auslöser (local_only, nur POST). Die Webhook-ID entsteht im Skript (64 Hex-Zeichen), wird nie ausgegeben und landet nur in [homeassistant] der config/secrets.toml des Trading-Projekts, mit aktiv = false. pruefen und lesen lesen nur (lesen zeigt zusätzlich die Zustände der Helfer), probe schickt eine Beispiel-Nutzlast und liest zurück, entfernen baut Helfer und Automation wieder ab. Läuft unter Windows mit dem Python des Home-Assistant-Projekts — dort liegen der Klient src/ha_verbindung.py, die Adresse der Instanz und der Name der Token-Variable; das Token bleibt auf der Windows-Seite und kommt nie auf den Trading-Rechner. Gemessen am 2026-09-20/21: eingerichtet, probe rückgelesen wie gesendet, und ein POST des echten Hausmelder aus WSL kam in den Helfern an `.venv\Scripts\python.exe -X utf8 ha_einrichten.py <pruefen

Nacht vom 2026-09-20 auf den 2026-09-21: Generalprobe, Hausmelder, YubiKey, Härtung

Datei Was sie tut Aufruf
generalprobe_echtlauf.py ruft die echte Funktion _generalprobe aus scripts/paper.py — dieselbe Verdrahtung wie im Betrieb — mit den echten IEX-Kerzen eines Tages (JSON aus hole_kerzen.py), einer Sicherungskopie des Registers (das echte wird nur lesend geöffnet), dem echten Registermodell, einem mitschreibenden „echten" Konto, das bei jedem schreibenden Aufruf wirft, einer Netzsperre auf requests.Session.request und einem Faden, der wie das Dashboard klickt (fortsetzen, anhalten, fortsetzen, glattstellen, freigeben). Urteilt über Exit-Code, Modus, Meldungsvorsatz, Netzversuche, Aufrufe am Konto, Position nach dem Glattstellen, Alter des Herzschlags, tagesstart.json. Gemessen am 2026-09-20/21 mit den Kerzen des 2026-09-18: bei 1 s je Marktminute 435 s, 389 Takte, drei Orders, 0 Befunde in WSL: python generalprobe_echtlauf.py <code-baum> <echter-projektordner> <kerzen.json> <wegwerf-ordner> [tempo]
hausmelder_echtlauf.py der echte Hausmelder-Faden gegen einen mitschreibenden HTTP-Server auf 127.0.0.1: erste Nutzlast ohne Statusdatei, Änderung, Stille ohne Änderung, Lebenszeichen, Killswitch-Wechsel, HTTP 500 (Merker kippt nicht), 302 (nicht gefolgt), veraltet, Adresse in keinem Fehlschlag und keinem repr, starte_hausmelder über eine Geheimnisdatei. Mit --echt <secrets.toml> zusätzlich ein POST an die dort eingetragene Adresse; die Adresse wird nie ausgegeben. Zurücklesen mit ha_einrichten.py lesen in WSL: python hausmelder_echtlauf.py <code-baum> <wegwerf-ordner> [--echt <secrets.toml>]
ha_aktiv_setzen.py setzt [homeassistant] aktiv in einer Geheimnisdatei auf true oder false — genau eine Zeile, mit Probe vor dem Schreiben, dass sich nur dieser Wert ändert; gibt nur Abschnittsnamen und die Länge der Adresse aus `python ha_aktiv_setzen.py <secrets.toml> <true
start_probe_w.py Probe-Backend wie start_probe_zugang.py, dazu die Konfiguration für Sicherheitsschlüssel (RP-ID localhost, Origin http://localhost:<port>) und wahlweise ein nur gelesener Marktkatalog. Bricht ab, wenn im Arbeitsordner eine config/secrets.toml liegt — Probe-Instanzen starten nur aus einer Kopie oder einem Arbeitsbaum ohne Geheimnisse, sonst sprächen sie mit dem echten ntfy und dem echten Home Assistant in WSL aus der Kopie: python start_probe_w.py <port> <ablage> [<katalog>]
browser_w.py Browserlauf zum YubiKey-Weg: Playwright/Chromium mit einem virtuellen Authenticator über das DevTools-Protokoll (WebAuthn.addVirtualAuthenticator) gegen die Probe-Instanz unter http://localhost:<port> — Anmelden mit Code, Registrieren in „Zugang", Anmelden mit Passwort und Schlüssel (der Zähler des Authenticators muss steigen, sonst wurde er nie gefragt), falsches Passwort, Code-Weg danach, Entfernen, Gegenprobe unter 127.0.0.1 (409), Schlüsseldatei und Anmeldeprotokoll ohne Passwort, keine CSP- oder Permissions-Policy-Meldung. Gemessen am 2026-09-21: 17 von 17, auch gegen eine gehärtete Systemeinheit unter Windows: python -X utf8 browser_w.py <port> <ablage>
latenz_auswertung.py rechnet Reaktionszeiten aus dem, was ein Lauf ohnehin hinterlässt — nur lesend, Register mit mode=ro: Klick → Runner reagiert (Ereignis in killswitch_ereignisse mit Auslöser pascal gegen die erste Taktzeile mit dem neuen Zustand; obere Schranke, weil die Taktzeile am Ende des Takts entsteht), Kerze → Taktende (nur im Modus paper) und den Taktabstand als Rahmen. Für Tage, an denen der Runner seine Latenzen noch nicht selbst misst. Gibt nie einen Kontowert aus in WSL aus dem Projektordner: python latenz_auswertung.py <protokoll.jsonl> [<register.db>]
bremse_echtlauf.py Misst das Wachstum des Anmeldeprotokolls im gesperrten Zustand gegen eine laufende Probe-Instanz: fünf Fehlversuche, dann je 5 s Dauerfeuer auf beginn, abschluss und den Weg mit Code, gezählt in Zeilen und Bytes; zweiter Durchgang mit dem Abschluss als erster gesperrter Anfrage; dazu der 409 des Abschlusses unter 127.0.0.1. Anlass: Der Prüfer maß am 2026-09-21 im Schlüsselweg 22 474 B/s, weil die Protokollbremse nur im Weg mit Code stand. Nach Task 229 gemessen: 2721 Anfragen in 5 s → eine Zeile in WSL: python bremse_echtlauf.py <port> <ablage> <beginn|abschluss>
s5_echtlauf.py Gegenmessung der Dashboard-Härtung gegen eine laufende Probe-Instanz: 422 ohne die Eingabe, 512 MiB Rumpf mit und ohne content-length samt Spitzenspeicher des Servers aus /proc, Latenz von POST /api/killswitch/anhalten unter 40 parallelen teuren Kerzenabrufen, überlanger Grund, Sitzungswiderruf nach Passwortwechsel. Gemessen am 2026-09-21: 413 in 0,19 s ohne Speicherzuwachs (vorher 1,5 GiB), Killswitch höchstens 0,51 s (vorher 118 s) in WSL: python s5_echtlauf.py <port> <ablage> <code-baum>
s1_alpaca_lesen.py liest mit dem Alpaca-Klienten eines Code-Baums die echten Antworten des Paper-Kontos — nur lesend, ohne einen Betrag auszugeben (Feldnamen, Typen, Statusverteilung der Orderhistorie, Felder mit None). Für den Vergleich alter gegen neuer Parser in WSL: python s1_alpaca_lesen.py <code-baum> <echter-projektordner>

Killswitch-Simulation (2026-09-21)

Datei Was sie tut Aufruf
killswitch_simulation.py der Killswitch im Zeitraffer, ohne Netz, ohne das echte Konto und ohne das echte Register — die echte Funktion _generalprobe mit den Kerzen eines Tages (JSON aus hole_kerzen.py), verdrahtet wie generalprobe_echtlauf.py. Drei Szenarien: hand (fortsetzen, anhalten, fortsetzen, glattstellen, freigeben — gehandelt wird nur im Zustand aktiv, beim Anhalten bleibt die Position stehen, nach dem Glattstellen ist sie null und der Runner gesperrt), sturz (alle Kerzen ab 11:00 Uhr New Yorker Zeit zehn Prozent tiefer — der Runner reißt die Tagesverlustgrenze selbst, stellt glatt, sperrt, meldet „Grenze verletzt", und sperrt nach einem „Freigeben" im selben Takt wieder, ohne neue Order) und neustart (das Dashboard startet mitten am Tag neu — Pause mit stehender Position, Pausenmeldung mit dem Auslöser neustart, und die Latenzanzeige zählt den Neustart nicht als Klick). Der Kopfkommentar nennt je Prüfung die Herkunft der Erwartung und die Grenzen: Gefüllt wird gespielt, der Klick geht nicht über HTTP, der Watchdog wird nicht gezielt ausgelöst. Anlass: Die Killswitch-Übung des Projekts stellt echte Orders und schreibt ins gemeinsame Register — sie darf nicht laufen, solange der Paper-Runner läuft. Gemessen am 2026-09-21 gegen den Betriebscode (0.20.0) mit den Kerzen des 2026-09-18 bei 1 s je Marktminute: je Szenario 431 s, Exit 0, 389 Takte, kein Befund und kein Hinweis; Reaktion des Runners auf einen Klick 0,85 bis 0,99 s (neun Messungen) in WSL: python killswitch_simulation.py <hand|sturz|neustart> <code-baum> <echter-projektordner> <kerzen.json> <wegwerf-ordner> [tempo]
killswitch_simulation_mutanten.py der Regressionsnachweis dazu: kopiert den Code-Baum, fährt zuerst die Grundlinie, macht die Kopie dann an sechs Stellen einzeln kaputt (Runner übergeht den Killswitch; Glattstellen schließt nicht; Tagesverlustgrenze greift nicht; jeder Auslöser zählt als Klick; keine Pausenmeldung beim Neustart; Tagesverlust hält nur an) und erwartet je Mutant Exit 2. Ein Muster, das nicht genau einmal trifft, ist ein Befund des Treibers. In zwei Teilen, je unter zehn Minuten. Gemessen am 2026-09-21 gegen den Betriebscode: Grundlinie und Gegenprobe in allen drei Szenarien ohne Befund, alle sechs Mutanten gesehen — drei davon an genau einer Prüfung (die Position nach dem Glattstellen, die Zahl der Klick-Messungen, die fehlende Pausenmeldung). Der erste Lauf der Grundlinie fand dabei einen Fehler der Prüfung, nicht des Runners: Im Schnelltempo fiel ein Klick mitten in einen Takt; dessen Taktzeile trug schon gesperrt, aber noch die Phase handelt, ohne Entscheidung und ohne Order. Seitdem ist alles ab dem zweiten Takt eines nicht aktiven Abschnitts verbindlich, der erste wird als Hinweis gedruckt in WSL: python killswitch_simulation_mutanten.py <code-baum> <echter-projektordner> <kerzen.json> <arbeitsordner> <1|2>

Red Button (2026-09-22, Paket R)

Datei Was sie tut Aufruf
browser_r.py Browserlauf zum Red Button mit virtuellem Sicherheitsschlüssel gegen eine Probe-Instanz (start_probe_w.py aus einer Kopie ohne Geheimnisdatei, mit gebautem dashboard/dist): anmelden mit Code, Schlüssel registrieren, unter 127.0.0.1 den Dialog öffnen (Hinweis „nur unter http://localhost:…", kein Wortfeld, gesperrter Knopf, kein POST), unter localhost den Red Button drücken, Grund eintragen, Stick (virtuell) berühren — beginn und Abschluss 200, Zähler des Authenticators steigt, genau ein Registerereignis glattstellen mit Auslöser pascal, Kopfzeile gesperrt; Screenshots. Importiert totp, schritt und melde_mit_code_an aus browser_w.py. Reihenfolge ist Absicht: erst 127.0.0.1, solange der Killswitch noch bedienbar ist — nach dem Notaus ist er gesperrt. Gemessen am 2026-09-22: 15 von 16, der eine Befund war ein zu strenger Check des Skripts (berichtigt). Nicht gemessen: eine abgelehnte Signatur (der virtuelle Authenticator signiert immer gültig), das Wort ohne Schlüssel, die Protokollbremse — das deckt tests/test_dashboard_red_button.py unter Windows: python -X utf8 browser_r.py <port> <ablage-der-probe> <ordner-fuer-screenshots>

Das Einrichten selbst (deploy/dienste-einrichten.sh unter sudo -S, deploy/windows/wsl-wachhalten.ps1 -Aktion einrichten) und das Eintragen des ntfy-Themas liefen aus dem Scratchpad der Sitzung; die Befehle stehen in der Administrator-Anleitung des Projekts, Abschnitt „Produktivbetrieb als Dienst".

Die Compose-Probe (Bauen aus dem echten Baum mit verankerten Ausschlüssen, Start, Healthcheck, Angriffsfälle, Runner-Probe im Container, Aufräumen) lag als compose_probe_echt.sh im Scratchpad der Sitzung und braucht sudo -S mit dem WSL-Passwort aus $WSL_PW; sie ist deshalb nicht hier abgelegt. Muster: tar --exclude=./data — ohne Anker fällt auch trading/data weg.

Vor dem Browser-Lauf npm run build im Projekt, sonst dient das Backend eine alte Oberfläche aus. Die Datensatz- und Dateinamen in browserlauf.py und pruef_teil3b.py sind die des Bestands vom 2026-09-17; nach einem neuen Katalog oder neuen Protokollen nachziehen. Die Statustexte in wiederaufbau.py sind aus Kopfzeile.tsx abgeschrieben.

Die generischen Planwerkzeuge liegen unter .vault-tools/plan-kopie/.

Geheimnisdatei seit Paket E2 (2026-09-23)

Die Werkzeuge nennen config/secrets.toml nicht mehr fest. Wer eine Projektklasse ruft, gibt None weiter (from_secrets(None, …), secrets_pfad=None, lies_ntfy_geheimnisse()); wer die Datei selbst liest (handabruf_kerzen.py, handelstag_auswertung.py, vorstart_pruefung.py, pruef_beobachtung_echt.py), holt den Pfad mit trading.geheimnisse.pfad() und nennt im Fehlerfall geheimnisse.beschreibung(); ha_einrichten.py löst gegen den übergebenen Projektordner auf. Der Auflöser nimmt das Argument, dann TRADING_GEHEIMNISSE, dann $CREDENTIALS_DIRECTORY/secrets.toml, sonst config/secrets.toml relativ zum Arbeitsverzeichnis — nach dem Umzug der Datei ins Linux-Dateisystem steht die Variable nur in einer Login-Shell (~/.profile). Ein Werkzeug aus einer Skriptdatei über wsl --exec bash sieht sie nicht und meldet „fehlt": dann export TRADING_GEHEIMNISSE=/home/claude/.config/trading-plattform/secrets.toml im Skript setzen. start_probe_w.py und start_probe_zugang.py nehmen beide Variablen absichtlich aus ihrer Umgebung, damit eine Probe nie die echte Datei liest; ha_aktiv_setzen.py bekommt den Pfad als Argument.

Paket M (2026-09-24): zehn Aktien in einem Runner

Datei Was sie tut Aufruf
handelstag_auswertung.py seit Paket M mit mehreren Instrumenten: Instrumente aus dem Protokollkopf; je Instrument Entscheidungen, Orders und die aus der Folge erwartete Zahl (Stufen, Versatz, Entscheidungen, Schlussbein, ohne geteilte Beine), erreichte Positionen und Takte mit frischer Kerze; groesste Zahl von Orders in einem Takt, Ereignisse je Art, Positionen je Instrument am Ende, BEFUND fuer jede nicht gefuellte Orderzeile; das Taktfeld orders gilt als Orders dieses Takts; --broker und --kerzen fragen alle Symbole des Kopfs, jede Order gegen die Kerze ihres Symbols wie bisher: python handelstag_auswertung.py <protokoll> [--broker] [--kerzen] aus dem Projektordner
m_probeaufruf.py lesender Probeaufruf vor dem Einspielen: GET /v2/assets roh (Schluessel und Typen) und ueber AlpacaBroker.anlage, trades/latest mit allen Symbolen roh und ueber letzte_kurse, Kerzen gebuendelt gegen einzeln, Seitenverhalten mit kleiner Seite; Exit 0 nur, wenn alles wie angenommen ist und keine Aktie die Startpruefung einer Folge mit Short verfehlt aus einem Arbeitsbaum mit Paket M in WSL: python m_probeaufruf.py <handelstag> <kennung> ...

Betrieb ohne täglichen Klick (2026-09-24): Abendkontrolle und Rückweg

Pascal am 2026-09-24: eine dauerhafte Abendkontrolle, die Neustarts übersteht und keine Updates von Claude Code oder Desktop blockiert, und zehn Aktien bis Mittwoch 2026-09-30. Beides läuft als Windows-Aufgabe mit pythonw.exe, ohne Claude-Prozess.

Datei Was sie tut Aufruf
abendkontrolle_wsl.py liest einen Handelstag und urteilt im Code: Handelstag laut GET /v2/calendar, Protokoll des scharfen Runners, letzte Zeile „Ende: …, Exit n" im Journal (jeder Exit ungleich 0 ist ein Befund), BEFUND-Zeilen von handelstag_auswertung.py --broker --kerzen, offene Positionen beim Broker, mindestens ein Takt aktiv, Tagesbericht, Dashboard und Zeitgeber, Killswitch nicht gesperrt; bei Befund eine Meldung mit hoher Priorität über den Melder des Projekts. Gibt eine JSON-Zeile aus, nie Beträge in WSL: python abendkontrolle_wsl.py --tag JJJJ-MM-TT [--ohne-meldung]; nur eine Meldung: --meldung TITEL TEXT
abendkontrolle.py Windows-Seite: prüft jeden Werktag seit 2026-09-24 ohne Ergebnisdatei (höchstens sieben Tage zurück, heute erst ab 22:30), legt das Ergebnis unter data/paper/abendkontrollen/<tag>.json im Projekt ab und schreibt eine Zeile in Inbox/<tag>.md unter „Agentenprotokoll", bei Befund mit #needs-review python abendkontrolle.py [--tag JJJJ-MM-TT]
abendkontrolle_einrichten.ps1 Aufgabe „Trading Plattform - Abendkontrolle": werktags 22:45 und fünf Minuten nach jeder Anmeldung, nur angemeldet, verpasste Läufe beim nächsten Start powershell -NoProfile -File abendkontrolle_einrichten.ps1 [-Aktion entfernen]
abendkontrolle_angriffe.py, abendkontrolle_ersatz_auswertung.py 44 Fälle in WSL (Kalender, Protokoll, Ende je Lauf samt mittags abgebrochenem und abendlichem Lauf, Journal, Auswertung, Broker, Maske, Bericht, Dienste, Killswitch, getrennte Fragen, Meldeweg gegen ntfy_probe_server.py und gegen einen toten Port, Bedienfehler; Reihenfolge an zwei Positionen) und 20 unter Windows (Notiz, Überschrift mit Zusatz, CRLF, kein UTF-8, Ergebnisform, Abbruch wird wiederholt, keine Nachbardatei, fällige Tage), ohne Netz. Am 2026-09-24 nach der unabhängigen Prüfung: 0 Abweichungen python abendkontrolle_angriffe.py einmal in WSL (Venv), einmal unter Windows
rueckweg_aapl.py, rueckweg_aapl_einrichten.ps1 einmal: config/paper-aapl-register.toml wird config/paper.toml, lokal committet (nicht gepusht) — nur nach 2026-09-30 22:05, bei stehendem Runner, sauberem Projektordner mit master, wenn dort noch die Konfiguration mit quelle = "folge" liegt und beide Dateien ausser [agent], den Instrumenten und dem Tagesverlust dieselben Schluessel und Werte tragen, in beide Richtungen verglichen (sonst schaltete der Tausch etwa ein abgeschaltetes [auto_fortsetzen] still wieder ein); ein halb erledigter Tausch wird zu Ende committet. Sonst Befund in der Notiz und eine Meldung. Aufgabe „Trading Plattform - Rueckweg AAPL" am 2026-09-30 22:50, zweiter Versuch 2026-10-01 22:10 python rueckweg_aapl.py; Einrichten wie oben
rueckweg_aapl_angriffe.py 22 Fälle auf einem Wegwerf-Git-Repo (dazu halb getauscht, Abschnitt nur in paper.toml, Automatik nur dort abgeschaltet, Abschnitt nur dort gelöscht, anderer Wert, anderer Zweig); am 2026-09-24 0 Abweichungen python rueckweg_aapl_angriffe.py unter Windows
abendkontrolle_mutanten.py baut je einen Fehler in eine Wegwerfkopie und verlangt, dass der Angriffstreiber rot wird: 16 Mutanten von abendkontrolle_wsl.py (in WSL), 9 von abendkontrolle.py und 12 von rueckweg_aapl.py (unter Windows). Am 2026-09-24: 37 von 37 gefangen python abendkontrolle_mutanten.py einmal in WSL, einmal unter Windows

Einspielen (2026-09-24): Werkzeuge aus dem Scratchpad hierher

Datei Was sie tut Aufruf
dashboard_neustart.sh sudo systemctl restart trading-dashboard.service nur bei stehendem Runner, danach Tor 6b (Journal der letzten Minute ohne PermissionError/Traceback, sonst Exit 27), /api/gesund und die Oberfläche. Pascals dauerhafte Freigabe gilt für genau diesen Neustart außerhalb der Handelszeit mit WSL_PW per WSLENV: wsl -d Debian -u claude -- bash …/dashboard_neustart.sh
geheimnis_scan.py vor jedem Push: Werte ab 12 Zeichen aus Geheimnis- und Zugangsdatei gegen git log -p <von>..<bis>, nur Schlüsselnamen und Trefferzahlen; dazu, ob eine der drei Geheimnisdateien verfolgt wird. Regressionsnachweis mit SCAN_PROBE=<bekannter Text> (am 2026-09-24: 66 Treffer für einen bekannten Text, 0 für die echten Werte) in WSL: python geheimnis_scan.py <repo> <von> <bis> [<bis> …]

IBKR-Zugang (2026-09-24): Paper-Konto über das Gateway im Container

Pascal am 2026-09-24: Zugang zum IBKR-Paper-Konto vorbereiten, Gateway als Container in WSL, erster Test nach 22:00. Nichts davon handelt.

Datei Was sie tut Aufruf
ibkr_zugang_eintragen.sh Pascal trägt Paper-Benutzername, Passwort (ohne Anzeige, zweimal) und Kontonummer ein; Ablage /home/claude/.config/trading-plattform/ibkr/ (0700/0600); ausgegeben werden nur Längen. Mit erfundenen Werten in einem Wegwerf-Ordner geprüft (IBKR_ZIEL) wsl -d Debian -u claude -- bash …/ibkr_zugang_eintragen.sh
ibkr_gateway_test.sh Gateway-Container ghcr.io/gnzsnz/ib-gateway (auf eine Prüfsumme festgelegt), Paper, READ_ONLY_API=yes, Port nur auf 127.0.0.1:4004; Schritte laden, pruefen, starten, log (Benutzername maskiert), probe, stoppen; verweigert zwischen 15 und 22 Uhr Berlin mit WSL_PW per WSLENV: wsl -d Debian -u claude -- bash …/ibkr_gateway_test.sh <schritt>
ibkr_probe.py lesende Probe über nautilus-ibapi im eigenen Venv ~/venvs/ibkr-probe: Verbindung, Konto (nur Anfang und Länge), Kontoart, Währung, Positionen (Zahl), verzögerter AAPL-Kurs (nur die Kursart), Fehlercodes; nie ein Betrag. Ohne Gateway geprüft: „keine Verbindung", Code 502, Exit 3 ~/venvs/ibkr-probe/bin/python …/ibkr_probe.py [--port 4004]

Paket AF (2026-09-24): Fortsetzen zum Tagesstart ohne Klick

Datei Was sie tut Aufruf
af_gegenfall.py faehrt die echte PaperSitzung eines Arbeitsbaums mit AF und der ausgelieferten config/paper.toml gegen einen ProbeBroker, Kerzen aus einer Datei von hole_kerzen.py fuer jede Aktie, Wegwerf-Register mit der Neustartregel, ohne Netz; der Fall restposition (10 Stueck in der letzten Aktie) und der Fall mitten (Start 60 Marktminuten nach der Oeffnung) muessen nicht_fortgesetzt mit dem Grund in Protokoll und Meldung zeigen, der Fall flach ist die Gegenprobe mit fortgesetzt, Ausloeser automatik und Orders; Exit 0 nur ohne BEFUND aus dem Arbeitsbaum in WSL: python af_gegenfall.py <kerzen.json> <fall>, Fall restposition, mitten oder flach; die Kerzen vorher einmal lesend mit hole_kerzen.py <tag> <kerzen.json>
af_registerprobe.py fragt die echte Funktion pruefe_register (Paket AF) gegen data/registry.db, nur lesend (mode=ro; die Klasse Registry fuehrte beim Oeffnen das Schema aus und schriebe); druckt Zustand, die vier juengsten Killswitch-Ereignisse (Stufe, Ausloeser, Zeit) und den Befund; Exit 0 erfuellt, 1 nicht erfuellt, 3 Register fehlt. Belegt am 2026-09-24 an drei gespielten Registern (bereit / Pascals Anhalten ohne Fortsetzen / aktiv) und an einer Kopie des echten; die mtime des echten blieb gleich. Braucht den Code mit AF im genannten Ordner in WSL im Projektordner nach dem Dashboard-Neustart: ~/venvs/trading/bin/python af_registerprobe.py .

Was die uebrigen Werkzeuge mit AF sehen: handelstag_auswertung.py braucht keine Aenderung, es zaehlt das Ereignis auto_fortsetzen unter ereignisse je art und druckt seinen Text. abendkontrolle_wsl.py liest Zustand, Seit und Ausloeser des Killswitch und berichtet jede Zeile auto_fortsetzen als Hinweis (die ersten 200 Zeichen des Feldes text, das mit dem Ergebnis beginnt). neustart_echtlauf.py setzt angehalten/neustart ohne Ereignis, pause_echtlauf.py einen Ausloeser echtlauf: Die Sitzung setzt dort nicht fort, schreibt aber je Lauf eine Zeile auto_fortsetzen und in "Paper-Runner wartet" eine Zeile mehr. generalprobe_echtlauf.py und killswitch_simulation.py laden config/paper.toml und klicken nach Plan; gegen einen Baum mit AF setzt die Sitzung dort mit dem Schalter selbst fort, bevor der geplante Klick kommt. Wer diese vier fuer einen Vergleich mit Paket M faehrt, setzt vorher auto_fortsetzen=False in ihr replace(lade_paper_config(...), ...); neustart_echtlauf.py und pause_echtlauf.py rufen lade_paper_config ohne replace auf — dort in der Konfiguration ihrer Kopie [auto_fortsetzen] aktiv = false setzen.