a07ad942c15d1f40988e18aaa83b425ccbfb70e7
286
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
cef6646a17 |
Verlustbegrenzung: Notfall-Stop und HTF-Flip-Close gemessen - beide durchgefallen
User-Frage nach automatischem Notfall-Close (30 %?) und alternativ einem Flip-Close bei entgegengerichtetem Trend. 1) NOTFALL-STOP. 30 % waere ohnehin wirkungslos: Einsatz 670 EUR/Lot, Median-Verlust 20 EUR/Lot = 3 % der Margin. 30 % erreichen 1 % aller Verluste. Kontrafaktisch ueber 1022 echte Trades (MAE aus M5-Bars, 87 EUR/$/Lot aus den Trades selbst geschaetzt): ohne Stop +358 EUR 3 % -293 | 5 % -639 | 8 % -14 | 15 % -416 | 30 % -331 Keine Schwelle schlaegt "gar kein Stop". Nach Einstiegsart: bei "ohne Signal" sieht 8-10 % mit +298/+290 gut aus, aber beide Nachbarn kippen (-292 / -106) -> Rauschen. 2) FLIP-CLOSE AUF DEN HTF-TREND (backtest_flipclose_htf.py) - war nie gemessen. Alle sechs Varianten in BEIDEN Haelften schlechter: BASIS H1 -548 H2 -154 M30 ab +0,0R -629 -247 M30 ab +0,5R -574 -234 M30 ab +1,0R -549 -183 M30 auch im Minus -616 -327 M30+H1 ab +0,5R -570 -222 M30+H1 auch im Minus -616 -290 Die mildeste Variante ist die, die kaum feuert - exakt das Muster der 15-Minuten-Regel. Kontrolle: die Basis (-548/-154) reproduziert backtest_flipclose2.py (-537/-140), die Pipeline ist in Ordnung. Methodik: feste, geteilte Entry-Liste ueber alle Varianten. backtest_flipclose2.py laeuft nach jedem Exit bei xb+1 weiter, wodurch jede Variante eine andere Trade-Folge bekommt (der am 31.07. bei backtest_exit_combo.py korrigierte Fehler). Hier von vornherein vermieden. Mechanismus in allen Faellen derselbe: Trefferquote steigt (38->44 %, 42->51 %), Ertrag faellt = Gewinner-Kappen. Fuenfte unabhaengige Messung dieser Klasse, alle negativ. Nichts gebaut. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
59e9498237 |
G/V-Lag: 1-s-Fallback + ehrlicher Verbindungspunkt (v=151)
Zuerst gemessen, dann gedreht - und das Backend war NICHT das Problem: /api/snapshot 75 Abrufe in 20 s -> 21 verschiedene ts = ~1/s WebSocket-Push direkt am Socket gemessen: Median 1,04 s (min 1,00 max 1,06) G/V-Aenderungen Ø 1,44 s - das ist der Markt, keine Verzoegerung Die ganze Server-Kette liefert bereits 1 s. Der Lag entsteht erst am Handy: bricht der WebSocket STILL weg (WireGuard-Aussetzer, App-Wechsel), traegt nur noch der REST-Poll - und der stand auf 4 s. POLL_MS 4000 -> 1000, aber mit Sperre: solange der WS liefert (lastWsMs, Fenster WS_FRISCH_MS=2200 ms), ueberspringt der Poll den Abruf. Kein zusaetzlicher Verkehr im Normalfall. Denkfehler, den erst die Simulation zeigte: der erste Entwurf las die WS-Frische aus lastRecvMs (jede Quelle) - damit drosselte sich der Poll SELBST und kam bei totem WS nur auf 2,9 s statt 1 s. Jetzt zwei getrennte Uhren. Simuliert: WS gesund -> 0 Zusatz-Abrufe, max. Alter 0,9 s. WS tot -> 1/s, max. Alter 0,9 s. WS traege (5 s) -> max. 2,9 s. Vorher bei totem WS: 4,0 s. Der Verbindungspunkt log: er wurde nur bei sock.onclose auf "off" gesetzt, aber genau der Fall, der den Lag erzeugt, feuert KEIN onclose - der Socket haengt still, der Punkt blieb gruen. Neu .dot.stale (bernstein, pulsierend) ab 3,5 s ohne frischen Snapshot: gemessen wird, was ANKOMMT, nicht was der Socket ueber sich behauptet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c445c687f5 |
Streu-Datei 'start_server.bat)' entfernt
Entstand versehentlich beim Testen (unmaskierte Klammer in einer Shell-Zeile) und wurde im vorigen Commit mit eingecheckt. Kein Inhalt von Belang. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
b14d81f412 |
restart_server.bat prueft jetzt auch - und zwei cmd-Fallen dabei behoben
Korrektur meiner eigenen Einordnung von vorhin: ich hatte restart_server.bat als "Wiederanlauf-Pfad" ausgenommen. Falsch. Die Aufgabenplanung startet start_server_hidden.vbs -> start_server.bat; restart_server.bat wird von NICHTS automatisch aufgerufen (geprueft) und ist damit ein absichtliches Deployment. Es prueft jetzt vor dem Kill, Notausgang --ohne-pruefung. Nur start_server.bat bleibt ungeprueft - das ist der echte Wiederanlauf-Pfad. Zwei cmd-Fallen, beide NUR durch den Positiv-Test gefunden: 1) `if errorlevel 1` innerhalb eines geklammerten if/else-Blocks wird zur PARSE-Zeit ausgewertet, nicht zur Laufzeit. Der erste Entwurf brach deshalb auch bei SAUBEREM Code ab - der Neustart haette nie mehr funktioniert. Behoben mit Sprungmarken statt Klammer-Bloecken. 2) `echo ... ^(x^)` maskiert im Block anders -> "Der Befehl [0] ist falsch geschrieben". Text jetzt ohne runde Klammern. Der Negativ-Test allein sah in beiden Faellen voellig in Ordnung aus: kaputter Code -> Abbruch, Server unangetastet, Exit 1. Erst der Positiv-Test hat es entlarvt. Eine Sperre muss man in beide Richtungen pruefen. Alle drei Zweige verifiziert (sauber -> weiter/rc 0, kaputt -> Abbruch/rc 1, --ohne-pruefung -> weiter/rc 0), gegen eine Attrappe, deren Kill/Start durch ein echo ersetzt ist - so liess sich der Durchlauf-Zweig pruefen, ohne den laufenden Server anzufassen. Auch der Testaufbau hatte einen Fehler: die Attrappe lag zuerst in %TEMP%, dort macht `cd /d "%~dp0"` das Temp-Verzeichnis zum Arbeitsordner und %~dp0tools\pre_commit.py existiert nicht -> scheinbarer Fehlschlag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
0ab79f1876 |
Code-Pruefung ans Deployment haengen, nicht nur an den Commit
User-Frage "wird die Pipeline bei jedem Deployment ausgefuehrt?". Antwort war NEIN: git commit check_nfalle + pytest (Hook installiert) tools/deploy.py prueft nur den LAUFENDEN Server, nicht den Code restart_server.bat gar nichts Aufgabe OilTradingServer -> start_server_hidden.vbs gar nichts Commit und Deployment sind zwei Ereignisse und fallen beliebig auseinander: eine geaenderte, nie committete Datei ging ueber restart_server.bat ungeprueft live; nach einem Reboot startet die Aufgabe, was auf der Platte liegt. "Der Server kommt hoch" ist kein Ersatz: die beiden log.-NameError in core/trader.py sassen MONATE in except-Zweigen (einer seit dem Initial-Commit), und der Server startete jedes Mal sauber. deploy.py bekommt Schritt 0: check_nfalle + pytest VOR dem Kill, bei Rot Abbruch mit Rueckgabecode 1. Die Reihenfolge ist der Punkt - ein laufender, funktionierender Server darf fuer kaputten Code nicht abgeschossen werden. Notausgang --ohne-pruefung. Beide Richtungen verifiziert: mit eingebautem F821-Fehler -> ABBRUCH, Exit 1, Server-PID vorher/nachher identisch (20892), der Prozess wurde nachweislich nicht angefasst. Ohne Fehler laeuft es durch. BEWUSST NICHT in restart_server.bat und die Aufgabenplanung - das sind WIEDERANLAUF-Pfade. Wuerde ein fehlschlagender Test dort den Start verhindern, staende eine offene Position ohne Trailing, Time-Stop und Notfall-Stop da, nur mit dem Broker-SL. Eine Pruefung, die den Bot offline laesst, ist schlimmer als der Fehler, den sie sucht. Der Batch gibt stattdessen einen Hinweis aus und verweist auf deploy.py. Regel: absichtliches Deployment blockieren, Wiederanlauf niemals. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
3f1f19087d |
Live-Backtest-Vergleich in die Pipeline: core/stichprobe.py + Abschnitt E
Konsequenz aus dem Messfehler vom 07.08.: der Vergleich lief nur, wenn jemand
daran dachte - und als er lief, war er falsch gebaut.
1) core/stichprobe.py - die Praevention ist KONSTRUKTIV, nicht ermahnend:
entkoppeln() / anteil_ci() / unterscheidbar() / schluessel_level_stunde().
Regel: vor jeder berichteten Rate entkoppeln, jede Aussage ueber einen
Unterschied mit Konfidenzintervall belegen. Die Zeilen in
pbreak_predictions und recommendations sind nicht unabhaengig.
8 Tests, darunter einer, der die reale Konstellation nachspielt
(roh 77 %, entkoppelt 33 %).
Fallstrick beim Bau, gefunden weil ich es laufen liess: ein sqlite3-Cursor
liefert Tupel, keine dicts - die Feldangabe akzeptiert jetzt Namen UND
Spaltennummern.
2) analyze_divergence.sec_d0 war selbst der Fehler. Es mittelte AVG(p_break)
ueber ALLE Rohzeilen und flaggte bei Delta > 8 Pp:
vorher 1058 rohe Zeilen, Delta +8,7 Pp -> ALARM
jetzt 110 entkoppelte, 37,6 % liegt in [37,3 ... 55,5] % -> OK
Der Waechter haette heute also einen Fehlalarm produziert - genau den, dem
ich elf Hypothesen lang nachgegangen bin.
3) NEU: Abschnitt E "GLEICHES FENSTER" (--backtest). Rechnet den Backtest ueber
genau den Live-Zeitraum und haelt ihn gegen das Intervall der entkoppelten
Live-Rate. Erster Lauf: live 46,4 % [37,3 ... 55,5] gegen Backtest 43,9 %
-> im Intervall, kein Befund.
4) Eingebaut in den Wochenreport (weekly_review._divergenz_section, montags
07:30 per Mail + Telegram), mit demselben Fail-safe wie der
Squeeze-Abschnitt. Bewusst NICHT in den pre-commit-Hook: der braucht MT5 und
Minuten, Stufe 1 muss bei ~5 s bleiben.
Ausserdem ein Rechenfehler in meinem ersten Entwurf behoben (p_break steht in
der DB bereits in Prozent, ich hatte zusaetzlich skaliert -> "3763,9 %") und
ein \n-Heredoc-Fall, der genau gegen die dokumentierte Regel verstiess.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
1f58049049 |
Die "Basisraten-Luecke" war ein Messfehler - meiner. Aufgeloest.
Nach elf einzeln gemessenen Hypothesen: es gab keinen Fehler im System. Die
14,1 Pp (Backtest 38,6 % gegen live 52,7 %) entstanden, weil ich eine
GECLUSTERTE 6-Tage-Stichprobe gegen ein 208-Tage-Mittel gehalten habe.
Zeitraum Backtest auf 03.-07.08. eingeschraenkt: 38,6 -> 43,4 % +4,8 Pp
Clusterung live entkoppelt (max 1 je Level/Stunde): 52,7 -> 45,2 % -7,5 Pp
Rest +1,8 Pp
Entkoppelt: live 45,2 % [KI 35,5 ... 54,8] gegen Backtest 43,4 % - der
Backtest-Wert liegt IM Intervall. Kein belegbarer Unterschied.
Das ist exakt der Fehler, den ich am selben Tag in der Faelligkeitsbedingung
korrigiert hatte (800 rohe statt entkoppelte Vorhersagen) - und ich habe ihn in
der Auswertung selbst noch einmal gemacht. Regel: bei pbreak_predictions immer
entkoppeln, bevor eine Rate berichtet wird.
Was bleibt:
Basisrate "gewandert 37,8 -> 53,2 %" ZURUECKGEZOGEN
Kalibrierungsfehler BLEIBT: 14,3 Pp entkoppelt,
KI [6,8 ... 25,5], Modell sagt 38,1 %,
real 45,2 % -> ~7 Pp Unterschaetzung
"oberste Klasse invertiert" NICHT belegt (beruhte auf n=29 rohen
Zeilen = wenige unabhaengige Faelle)
AUC unveraendert unentschieden
Konsequenz: nichts umbauen. Die Stichprobe ist fuer eine Reparatur zu klein -
genau deshalb steht die Faelligkeit jetzt auf 350 entkoppelten (Stand 93).
Die elf Hypothesen, alle gemessen: Niveau-Drift, Regime-Merkmal, Vola-Regime,
aktuelles Regime, Sammelart, ATR-Floor, Level-Auswahl, Beruehrungs-Erkennung,
Timeout, Auswertungs-Aufloesung M1/M5, Richtungsquelle.
Zwei Kontrollen bestaetigen die Werkzeuge: mein M1-Nachspiel reproduziert die
Live-Auswertung zu 100 %, und pb_levels30 ist live befuellt - der M5-Fallback
ist nicht aktiv.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
aefac274d3 |
Level-Auswahl: Nachbau behoben (core/sr_levels.py) - Luecke bleibt offen
Auftrag zum benannten naechsten Schritt: die Backtests bauten die
Live-Level-Auswahl nach, statt sie zu benutzen. Drei echte Abweichungen:
1. Der Nachbau clusterte den GEMISCHTEN Rohpool (sorted(ch+cl)); live werden
ph und pl GETRENNT geclustert. Das ist exakt der Fehler, den der Live-Code
als behoben dokumentiert ("nicht vorher zusammenlegen!" - Ketten-Mega-
Cluster in dichten Zonen). Gemessen: 4,5 % aller Zeitpunkte hatten einen
anderen Widerstand.
2. Live rundet jede Linie auf 3 Stellen, der Nachbau nicht.
3. Live fuehrt Widerstand und Unterstuetzung mit getrennter Hysterese.
Geloest ueber core/sr_levels.py (cluster/linien/naechste/halten).
engine._draw_levels ruft es auf, Verhalten bitgenau unveraendert
(tests/test_sr_levels.py, 6 Tests, je 300-400 Zufallsfaelle). Der Test enthaelt
die Gegenprobe, dass der Nachbau wirklich abwich - sonst waere nicht belegt,
dass es etwas zu beheben gab.
backtest_pbreak_retrain.build_levels bleibt unveraendert (Migrations-Regel: die
daraus gefitteten Live-Gewichte duerfen sich nicht rueckwirkend verschieben).
Daneben neu: build_levels_live fuer kuenftige Fits.
ABER die Korrektur schliesst die Basisraten-Luecke nicht: 38,0 -> 38,3 %,
live 52,7 %.
Damit fuenf Hypothesen geprueft und alle widerlegt:
Niveau/Achsenabschnitt Roll-Achse faellt live durch
Vola-Regime ueber 5 Quintile flach (37,0-39,2 %)
Sammelart -1,7 Pp, falsche Richtung
ATR-Floor-Artefakt +2,8 Pp; bei live-gleichem ATR erst 40,1 %
Level-Auswahl +0,4 Pp
Nebenbefund: 53,9 % aller Backtest-Bars sitzen auf dem ATR-Floor 0,12, live nur
5,4 % - der Backtest-Zeitraum ist deutlich ruhiger. Der ATR selbst stimmt aber
ueberein (Median live 0,2167 gegen letzte 7 Tage 0,2174).
Kein Notfall: auto_sr_close ist false, das Modell schliesst keine Trades.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
2e89724368 |
P(break) Niveau-Reparatur gemessen: beide Varianten fallen durch
Folgeauftrag zur B4-Pruefung. Hypothese war: das Modell rankt brauchbar, nur
sein Niveau haengt an einer wandernden Basisrate. Geprueft wurden ein
Regime-Merkmal (ATR/gleitender Median) und ein laufend nachgefuehrter
Achsenabschnitt, Regel vorab fixiert.
collect() in backtest_pbreak_retrain.py hat dafuer einen ADDITIVEN
REG-Parameter bekommen (Default None), Ausgabe ohne ihn bitgenau geprueft
(4371 Zeilen, 0 Abweichungen).
Auf Backtest-Daten besteht die Roll-Achse (Kalib 2,61->1,95 und 10,51->3,25 Pp,
AUC leicht besser), das Regime-Merkmal faellt durch (H2->H1 schlechter).
Auf LIVE-Daten (n=921 ab 01.08.) faellt auch die Roll-Achse durch: Kalib
14,16 -> 10,64 Pp (also nicht repariert), AUC 0,531 -> 0,516 (ueber der
Toleranz), und der Nachbar n=800 kippt auf 15,14 Pp = schlechter als der
Ausgangswert.
Grund: die oberste Klasse bleibt INVERTIERT (69 % vorhergesagt, 17,2 % real).
Eine Niveau-Verschiebung kann eine invertierte Klasse nicht reparieren. Die
Ausgangshypothese ist damit widerlegt.
Drei Erklaerungen fuer die Basisraten-Luecke geprueft, alle widerlegt:
Sammelart (live 1x je Beruehrung vs Backtest jeder Bar): -1,7 Pp, falsche
Richtung
Vola-Regime: Bruchrate ueber 5 Quintile flach (37,0 bis 39,2 %)
aktuelles Regime ungewoehnlich: letzte 7 Tage Median 0,96 = normal
Der flache Vola-Befund erklaert zugleich, warum das Regime-Merkmal nichts
bringt.
Kontrolle: das Modell VOR dem 31.07. hat auf diesen Daten AUC 0,364/0,406 -
unter 0,5, also invertiert. Reproduziert exakt den Grund fuer das
Nachtrainieren.
Nichts gebaut. Naechster Schritt ist kein drittes Fitten, sondern die einzige
ungeprueft gebliebene Divergenz: die Level-Auswahl selbst (Backtest baut sie
mit pick_level/_cluster nach, live entscheidet _draw_levels).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
908e20a9d0 |
P(break) v2 live geprueft: Kalibrierung daneben, Trennschaerfe unentschieden
Faellige B4-Messung nach dem Nachtrainieren vom 31.07. (878 Vorhersagen ab 01.08.). Drei Befunde. 1) Das Skript mischte zwei Modelle. Es trennte bei der M30-Umstellung (30.07.), nicht beim Nachtrainieren (31.07.) - "GESAMT" las altes und neues Modell zusammen. Derselbe Fehler wie am 02.08. in analyze_divergence.py. Neu: MODELL_V2 mit demselben Stichtag wie die Faelligkeitsbedingung. 2) Kalibrierung messbar daneben. Die Basisrate ist gewandert: Training 37,8 %, live 53,2 %, stabil ueber vier volle Tage (51,4 / 54,1 / 56,4 / 53,8 % bei n=122-276). Ein Modell, dessen Niveau an 37,8 % verankert ist, muss in einem 53-%-Regime systematisch zu niedrig sagen - genau das passiert. Oberste Klasse invertiert (69 % vorhergesagt, 17 % real). 3) Trennschaerfe NICHT entscheidbar - und das ist der wichtigere Befund. Entkoppelt n=87, AUC 0,556, 95-%-Bootstrap-KI [0,434 ... 0,674]. Das Intervall enthaelt den Zufall (0,50) UND die Messlatte (0,654). Die Faelligkeitsbedingung zaehlte die falsche Groesse: 800 ROHE Vorhersagen, die aber nicht unabhaengig sind (dieselbe Position pendelt um dasselbe Level). Aus 878 rohen werden 87 entkoppelte - die Bedingung ueberschaetzte die Beweismenge um rund das Zehnfache und meldete "faellig", obwohl die Messung nichts entscheiden konnte. Jetzt 350 ENTKOPPELTE (halbiert die KI-Breite). Stand 87/350. Operativ kein Notfall: auto_sr_close ist seit 06.08. false, das Modell schliesst keine Trades. Es speist nur Anzeige, Chart-Linien und Copilot-Kontext. Nichts umgestellt - ein drittes Fitten derselben Bauart wuerde denselben Weg gehen; der Befund zeigt aufs Niveau, nicht zwingend auf die Rangfolge. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
3e8fa9fea8 |
Auffang-Element in app.js: ein fehlendes Element bricht nicht mehr den Render
Gemessen: 95 direkte $("id")-Zugriffe, 0 davon abgesichert - obwohl die Regel
"neue Elemente per const el = $(..); if (el) {..}" seit 01.08. in CLAUDE.md
steht. Eine Regel mit 0 Prozent Befolgung ist keine Regel, also loest es jetzt
der Code an EINER Stelle statt an 95.
$() gibt bei fehlendem Element ein detachiertes <span> zurueck statt null,
plus einmalige console.warn je ID (kein stiller Fallback - das war der
catch{}-Fehler in pollSnapshot).
?. war NICHT die Loesung: 80 der 95 Zugriffe sind Zuweisungen, und
$("x")?.y = v ist ein Syntaxfehler.
$streng() ist der wichtige Teil. Alle Eingabefelder sind type="number", und
leer heisst dort ausdruecklich "Stop entfernen" (sl: null). Mit dem
Auffang-Element waere .value undefined -> parseFloat NaN -> JSON.stringify
macht daraus wieder null: eine fehlende Eingabemaske haette den Broker-SL
einer laufenden Position stillschweigend geloescht. Betroffen war genau eine
Funktion (sendSltp); setSrMin/setEmg/setManualMargin/setMarginPct fangen NaN
bereits ab (geprueft, nicht angenommen).
Beide Richtungen an einem Minimal-DOM verifiziert, das eine alte index.html
simuliert: mit der alten $-Definition bricht der Render beim ZWEITEN Feld ab,
mit der neuen laeuft er durch. Der Order-Pfad bricht in beiden Faellen sauber
ab.
Asset-Version v=149 -> v=150.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
e7112e1ab6 |
JS-Syntaxpruefung: node --check als Stufe B in check_nfalle
CLAUDE.md behauptete "kein node im Env" - das stimmte nicht mehr, Node
v24.18.0 ist installiert. Die Zeile hat die Frage jahrelang falsch
beantwortet.
Gemessen an 5 realistischen Fehlern findet die alte Klammern-Balance 1,
node --check findet 5 (86 ms):
Klammer zu viel Balance ok node ok
const x = ; Balance blind
let doppelt Balance blind
const doppelt Balance blind
return ausserhalb Fkt. Balance blind
Ein Syntaxfehler in app.js bricht den GESAMTEN Render - das Dashboard
friert auf Altwerten ein. Bei 95 direkt dereferenzierten $("id")-Zugriffen
(0 davon mit ?.) ist das kein theoretisches Risiko.
Geprueft wird als MODUL (.mjs), nicht als CommonJS: als CJS haelt Node ein
top-level return fuer legal, der Browser laedt app.js aber als klassisches
Script, wo es ein Syntaxfehler ist. Verifiziert, dass das echte app.js den
strengeren Modus ohne Anpassung besteht.
Kein npm, keine package.json, kein node_modules - node --check ist die
Laufzeit selbst. Damit entsteht NICHT die Divergenz "Pruefumgebung ist nicht
die Laufumgebung" (der .ps1-BOM-Fehler, das pre-commit-Framework): Node und
Chrome benutzen denselben Parser (V8).
Drei Richtungen verifiziert:
sauber -> gruen
mit eingebautem Fehler-> Exit 1, Commit gestoppt
ohne node im PATH -> Rueckfall auf alte Pruefung, Exit 0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
fd3c7f57a5 |
Live-Code von Backtest-Skript entkoppelt: core/squeeze_scan.py
core/engine.py (squeeze_monitor) und weekly_review.py importierten
backtest_breakout_squeeze - die Abhaengigkeitsrichtung war verkehrt:
ein Fehler im Backtest konnte den laufenden Bot treffen.
Schwerer wog, WIE die Parameter hineinkamen:
BQ._N = _SQ_N; BQ._K = _SQ_K
Das mutiert Modul-Globale eines Backtests, wirkt prozessweit und damit auf
jeden anderen Nutzer desselben Moduls im selben Prozess. Die Werte weichen
real ab (Backtest _N=12, live _SQ_N=10).
Geloest ueber core/squeeze_scan.py - Parameter stehen in der Signatur.
backtest_breakout_squeeze.py leitet nur noch weiter, damit es EINE
Implementierung gibt statt zweier (der sim_run/_ema_series-Fehler).
Der Exit ist bewusst NICHT mitrepariert: exit_legacy ist eine bitgenaue
Kopie inkl. seiner Abweichungen vom kanonischen Exit (Trail 1,5 statt 1,0,
kein Lock/Time-Stop/TP, max_hold 288 statt 200). Damit misst der B4-Monitor
gegen einen veralteten Exit - separater, offener Befund. Ihn hier still
mitzuaendern haette die Vergleichsgrundlage verschoben.
Bitgenauigkeit bewiesen (tests/test_squeeze_scan.py): die alte Fassung liegt
eingefroren im Test und laeuft gegen die neue ueber 500 synthetische Reihen
x 3 Multiplikatoren. Ein Vorher/Nachher-Lauf waere ungueltig gewesen - der
Backtest zieht Bars live aus MT5, das Fenster verschiebt sich staendig.
Test selbst per Mutationsprobe geprueft: 5 von 6 eingebauten Fehlern schlagen
an, der sechste (d>0 -> d>=0) ist beweisbar aequivalent, da d nur +-1 ist.
Live-Gegenprobe auf 9000 M5-Bars: n=112, Treffer 44%, OeR +0,178, PF 1,26.
Aktivierung beim naechsten Neustart - bei offener Position kein Neustart fuer
eine verhaltensneutrale Aenderung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
a35a0e7006 |
Pipeline-Stufe 1 automatisiert: requirements, pre-commit-Hook, ruff
Nach Web-Recherche zum 2026er-Python-Standard umgesetzt, aber gefiltert: von
uv/Ruff/pyproject/CI passt hier nur, was zu einer Einzelmaschine mit
GUI-gebundenem MT5 und Live-Geld passt.
(1) requirements.txt (Laufzeit) + requirements-dev.txt (Werkzeuge/Messung),
Versionen gepinnt. Bis dahin gab es GAR KEINE Liste — nach einem
Maschinenausfall waere die Rekonstruktion Raten gewesen. Per AST ueber
core/, server.py, tools/ ermittelt statt geraten.
(2) tools/pre_commit.py faehrt vor jedem Commit check_nfalle + pytest (~5 s).
Einrichten: python tools/pre_commit.py --install. Notausgang
'git commit --no-verify' ist Absicht.
Bewusst OHNE das pre-commit-Framework: dessen Nutzen ist
Werkzeug-Versionierung ueber mehrere Maschinen. Hier gibt es eine, und es
wuerde eine ZWEITE ruff-Version in einer isolierten Umgebung installieren —
genau die Divergenz 'Pruefumgebung != Laufumgebung', die heute schon einmal
zugeschlagen hat.
(3) Ruff statt pyflakes (--select F821), ganzer Scan in 2,1 s. KEIN
ruff format — das wuerde 161 Dateien umformatieren, darunter alle
Backtests, und die Migrations-Regel verletzen.
⚠ VIERTER Fall der Klasse 'Erfolg melden, wo nichts geprueft wurde', und nur
durch den Test aufgefallen: --select F821,E999 laesst ruff 0.16 komplett
abbrechen (E999 wurde entfernt, Exit 2); die Meldung geht nach stderr, und weil
ich den Rueckgabecode nicht pruefte, meldete die Stufe 'keine undefinierten
Namen' — ohne irgendetwas geprueft zu haben. Ein absichtlich eingebauter
F821-Fehler kam glatt durch den Hook. Behoben: nur F821, und Exit 2 loest jetzt
den pyflakes-Rueckfall aus.
Beide Richtungen verifiziert: mit Fehler stoppt der Hook den Commit, ohne ist
er gruen. Der Test-Commit wurde zurueckgenommen (war nur lokal, ahead 1).
Nicht umgesetzt: Gitea Actions (Runner auf derselben Maschine wie der Live-Bot,
kein Mehrwert bei 5 s Pruefzeit), Container/Blue-Green (MT5 braucht eine
Desktop-Sitzung, EINE Broker-Verbindung), mypy/ty (kaum Annotationen).
Struktureller Fund: core/engine.py importiert backtest_breakout_squeeze — ein
Backtest ist Teil des LIVE-Abhaengigkeitsgraphen.
|
||
|
|
41e527c492 |
Auto-Logon aktiv — Registry-Weg, sicherer Weg blieb wirkungslos
Endstand verifiziert: AutoAdminLogon=1, DefaultUserName=ah, DefaultDomainName=HOMEBASE, Aufgabe OilAutoLogonLock Bereit und auf autologon_lock.ps1 zeigend. Die Boot-Luecke ist damit konfiguratorisch geschlossen. ⚠ Der SICHERE Weg hat nicht funktioniert: Sysinternals Autologon beendete sich mit ExitCode 0, schrieb aber nichts — weder ueber den Dialog noch ueber die Argument-Form. Ausgeschlossen: DevicePasswordLessBuildVersion (nicht gesetzt), fehlende Elevation, haengender Prozess. Ursache ungeklaert. Aktiv ist deshalb der Registry-Weg, und damit steht das Passwort im KLARTEXT unter HKLM\...\Winlogon\DefaultPassword — lesbar fuer jeden lokalen Admin und jedes Backup-Image. Entfernen-Kommando in CLAUDE.md. ⚠ Dritter Fall derselben Fehlerklasse in diesem Skript, jetzt behoben: die Speicherart wurde aus einer stale Variable gelesen, die VOR dem Registry-Schreiben gefuellt war. Die Ausgabe widersprach sich direkt — erst korrekt 'steht jetzt im KLARTEXT', zwei Zeilen spaeter 'nicht im Klartext ✅'. Der Zustand wird jetzt nach jedem Schreibvorgang frisch gelesen. Lehre aus allen drei Faellen: eine Erfolgsmeldung muss den Zustand NACH der Aktion pruefen, nicht den davor. Offen: die Wirkung ist erst beim naechsten Reboot belegt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
bdff39a278 |
Autologon: Rueckmeldung nicht mehr verschlucken, Registry-Weg als Ausweg
Zwei Fehler in meinem Direkt-Zweig, beide behoben:
(a) '& $exe ...' WARTET bei GUI-Anwendungen NICHT — das Skript las die
Registry, bevor Autologon fertig war. Jetzt Start-Process -Wait -PassThru.
(b) '$null = ... 2>&1' hat die Rueckmeldung verschluckt — genau die
Information, die zur Diagnose noetig war, wurde weggeworfen. Jetzt werden
ExitCode und Ausgabe gezeigt.
Zusaetzlich diagnostiziert: Autologon64.exe startet nur elevated (direkter
Aufruf aus einer normalen Sitzung scheitert mit 'erfordert erhoehte Rechte').
Der Windows-11-Blocker DevicePasswordLessBuildVersion ist NICHT gesetzt, war
also nicht die Ursache.
Neu als letzter Ausweg: der Registry-Weg, aber nur nach ausdruecklicher
Zustimmung und mit klarer Warnung — dort landet das Passwort im KLARTEXT unter
HKLM\...\Winlogon\DefaultPassword. Er funktioniert dafuer immer. Die
Entscheidung gehoert dem Nutzer, nicht dem Skript; das Entfernen-Kommando wird
gleich mit ausgegeben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
b35f27541f |
Autologon: Rueckfall auf den Direkt-Weg statt Sackgasse
Der Dialog-Weg ist zweimal ohne Ergebnis geblieben, weil er mit ENABLE bestaetigt werden muss. Statt den Nutzer ein drittes Mal tippen zu lassen, bietet das Skript nach einem abgebrochenen Dialog jetzt direkt an, es ohne Dialog zu erledigen (j/n) — die Aktivierung steckt dafuer in einer Funktion, die von beiden Wegen aufgerufen wird. Ausserdem ehrlicher in der Fehlerursache: ein falsches Passwort meldet Autologon nicht zurueck, das Ergebnis sieht dann genauso aus wie ein abgebrochener Dialog. Beides wird jetzt genannt statt nur eines. Mit dem echten 5.1-Parser geprueft, BOM gesetzt, Scan sauber. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
4c8ce18a9f |
Autologon: -Direkt-Weg ohne GUI-Dialog
Der GUI-Weg fuehrte zweimal zu nichts. Diagnostiziert: der Dialog OEFFNET sich (Fenstertitel 'Autologon - Sysinternals', Prozess verifiziert), muss aber mit ENABLE bestaetigt werden — nur schliessen tut nichts. Neu: -Direkt. Autologon 3.10 nimmt Benutzer/Domaene/Passwort als Argumente; das Skript fragt es per Read-Host -AsSecureString ab (unsichtbar, nicht in der History) und ruft ohne Dialog auf. Schlaegt es fehl, nennt das Skript jetzt den wahrscheinlichen Grund je nach Weg (Dialog nicht bestaetigt vs. falsches Passwort). Abwaegung dokumentiert: bei -Direkt steht das Passwort fuer den Moment des Aufrufs in der Kommandozeile des Kindprozesses (fuer Admins kurz sichtbar). Es landet nicht in einer Datei, nicht in der Shell-History — und anschliessend als verschluesseltes LSA-Secret statt im Klartext in der Registry. Mit dem echten 5.1-Parser geprueft (0 Fehler), -Direkt als Parameter erkannt, BOM gesetzt, n-Falle-Scan sauber. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
eccc13f2cf |
Autologon-Skript: zwei Fehler behoben, die Erfolg meldeten wo keiner war
Der erste Lauf hat NICHTS eingerichtet — weder Auto-Logon noch die
Sperr-Aufgabe. Nachgeprueft: AutoAdminLogon, DefaultUserName und
OilAutoLogonLock allesamt nicht vorhanden.
(1) $ErrorActionPreference = 'Stop' PLUS schtasks /Delete auf eine noch nicht
existierende Aufgabe: native Programme schreiben nach stderr, PowerShell
macht daraus unter 'Stop' einen Abbruch. Das Skript endete, BEVOR /Create
lief. Jetzt wird vorher per /Query geprueft.
(2) Die Erfolgsmeldung log: ein fehlendes DefaultPassword wurde als
"LSA-Secret ✅" ausgegeben — dabei war gar nichts gesetzt, weil der
Autologon-Dialog ohne Enable geschlossen wurde. Abwesenheit eines
Klartext-Passworts beweist nicht, dass der sichere Weg genommen wurde; sie
ist auch mit "nichts passiert" vereinbar. Jetzt ist AutoAdminLogon = 1 die
Bedingung, und erst danach wird ueber die Speicherart geurteilt. Ohne
aktives Auto-Logon bricht das Skript mit Code 1 ab und ueberspringt
Schritt 2.
Dazu ein Design-Fehler, der erst beim Nachdenken auffiel: die Sperre haette bei
JEDER Anmeldung gefeuert — ein ONLOGON-Trigger unterscheidet nicht zwischen
Auto-Logon und manuellem Login. 30 s nach jedem normalen Anmelden waere der
Bildschirm zugefallen. Neu: tools/autologon_lock.ps1 prueft die Systemlaufzeit
und sperrt nur, wenn der Rechner < 3 min laeuft (= Auto-Logon nach Boot).
Trocken getestet: bei 1088 min Laufzeit -> sperrt nicht.
Beide .ps1 mit BOM geschrieben und mit dem echten 5.1-Parser gegengeprueft
(0 Fehler). check_nfalle.py Stufe C2 deckt alle drei Skripte ab.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
da863371d3 |
.ps1 braucht ein BOM: Autologon-Skript brach unter powershell.exe 5.1
Das Skript liess sich nicht ausfuehren — "Schliessende ) fehlt", "Zeichenfolge hat kein Abschlusszeichen". Es war KEIN Syntaxfehler: Windows PowerShell 5.1 liest .ps1 als CP1252, wenn kein BOM da ist. Aus dem Gedankenstrich werden drei Zeichen, das darin enthaltene Anfuehrungszeichen schliesst den String vorzeitig, und der Fehler kaskadiert bis zum Dateiende. Der eigentliche Punkt ist, warum es beim Schreiben nicht auffiel: das hiesige PowerShell-Werkzeug ist pwsh 7, und das liest UTF-8 ohne BOM klaglos. Die Datei war in meiner Umgebung fehlerfrei und beim Nutzer kaputt — dieselbe Divergenz-Klasse wie der Deployment-Drift, nur eine Ebene tiefer: die Pruefumgebung war nicht die Laufumgebung. Behoben (UTF-8 MIT BOM) und mit dem ECHTEN 5.1-Parser gegengeprueft (Parser::ParseFile, 0 Fehler) — nicht mit pwsh 7, das den Fehler ja gerade nicht zeigt. Dabei ein zweiter Fall gefunden und mitbehoben: scripts/send_daily_report.ps1 (Umlaute, kein BOM). Der ist zwar dormant (Microsoft.Graph-Modul fehlt), haette aber genauso gebrochen. Dauerhaft abgesichert: tools/check_nfalle.py prueft es als Stufe C2 — .ps1 mit Nicht-ASCII und ohne BOM ist ab jetzt ein Befund. .bat ist nicht betroffen: cmd.exe verzeiht das in echo/Kommentaren (restart_server.bat enthaelt Sonderzeichen, bricht aber nicht). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
47d6d1ddae |
Auto-Logon vorbereitet — verschluesselt statt Klartext, mit Bildschirmsperre
Schliesst die letzte Luecke der Boot-Pipeline: OilTradingServer und HyperliquidDashboard haengen an einem Logon-Trigger, nach einem Update-Reboot laeuft nichts bis zur Anmeldung (real 20.07.: Reboot 01:30, Server bis 07:42 tot, -95,48 EUR). Ein Task "ohne angemeldete Sitzung" hilft NICHT: der Bot braucht das laufende MT5-Terminal, und das ist eine GUI-Anwendung — es braucht eine echte Desktop-Sitzung. Auto-Logon ist hier also das richtige Mittel, nicht nur das bequeme. BEWUSST NICHT der Registry-Weg: der legt das Passwort als DefaultPassword im KLARTEXT unter HKLM\...\Winlogon ab, lesbar fuer jeden lokalen Admin und in jedem Backup-Image. Stattdessen Sysinternals Autologon — verschluesseltes LSA-Secret. Die EXE ist Microsoft-signiert (Signatur geprueft: Status Valid). Das Skript verifiziert danach, dass DefaultPassword NICHT im Klartext steht. Das eigentliche Restrisiko ist nicht das Passwort, sondern die offene Sitzung: nach dem Reboot steht ein angemeldeter Desktop mit MT5 und Live-Broker- Verbindung da. Deshalb legt das Skript zusaetzlich die Aufgabe OilAutoLogonLock an — 30 s nach Anmeldung LockWorkStation. Die Sitzung laeuft weiter (MT5 und beide Server arbeiten), der Bildschirm ist gesperrt. NICHT ABGESCHLOSSEN: HKLM ist aus einer normalen Sitzung nicht schreibbar (getestet: "Requested registry access is not allowed"). Der letzte Schritt braucht ein Administrator-Fenster. Das Passwort steht NICHT im Skript, nicht in der Doku und nicht im Repo — es wird im Autologon-Dialog eingegeben. tools/autologon/ ist gitignored (Binaries, gleiche Regel wie tools/piper/). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
4cbb1f1db5 |
tools/deploy.py: Stufe 5 der Pipeline ist jetzt ein pruefbares Skript
Ersetzt das von Hand zusammengesetzte "killen, starten, warten, nachsehen" —
und macht die dokumentierte Schwachstelle der Pipeline pruefbar.
Fuenf Schritte, Rueckgabecode 0 nur wenn alle durchlaufen (verkettbar):
1. Prozess GEZIELT AM PORT beenden — nicht per *server.py*-Muster wie
restart_server.bat, das trifft auch das HL-Dashboard auf 8001 (real: es
wurde bei jedem MT5-Neustart still mit-erschlagen und riss die Luecken in
die Lead-Lag- und Order-Flow-Datensammlung).
2. starten und warten, bis /api/snapshot WIRKLICH antwortet.
3. genau EINE Instanz je Port.
4. --feld <name> pruefen.
5. Log AB DER STARTPOSITION auf ERROR/Traceback.
Schritt 4 ist der Kern: restart_server.bat hat zweimal still nicht neu
gestartet, und weil statische Dateien je Request frisch von der Platte gelesen
werden, belegt eine korrekt ausgelieferte app.js?v=N gar nichts ueber den
geladenen Python-Code. Ein neues Snapshot-Feld ist der einzige belastbare
Beweis — genau daran fiel der Fehler am 02.08. auf (hl_live.basis_stale). Ohne
--feld sagt das Skript ausdruecklich, dass der Beweis fehlt.
Beide Richtungen geprueft:
--feld rec_track -> "Python-Code ist neu", Exit 0
--feld dieses_feld_gibt_es_nicht -> "FEHLT - der alte Code laeuft weiter!",
Exit 1
Eine Pruefung, die nicht scheitern kann, waere wertlos.
Aufrufe:
python tools/deploy.py --feld <snapshot_feld>
python tools/deploy.py --nur-pruefen
python tools/deploy.py --hl
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
cddcefa463 |
Der Engpass war nie die Mathematik: quadratische Schleife, ~9 min -> 8,9 s
Anlass war die Frage nach numpy. Statt zu vermuten wurde profiliert — und das
Ergebnis war ein anderes als erwartet: von 10,07 s Gesamtlaufzeit steckten
8,17 s in der EIGENZEIT der Backtest-Schleife, nur 0,44 s in _build.
Ursache:
[C[j] for j in PH if i - _PIV_LOOK <= j <= i - _PIV_K] # je BAR, ganze Liste
Das ist O(Bars x Pivots) — bei 80k Bars hunderte Millionen Vergleiche, und
genau daher kamen die 9-20-Minuten-Laeufe. PH/PL sind sortiert, also genuegen
zwei Binaersuchen fuer dieselbe Menge in O(log n).
Gemessen: backtest_signal_touchfill.py ueber 80k Bars von ~9 min auf 8,9 s
(~60x), bei 8k Bars 10,07 s -> 1,43 s. Das Ergebnis bleibt inhaltlich
identisch (alle sechs Felder negativ); die Handvoll Trades Unterschied ist die
bekannte Live-Bar-Drift, nicht der Umbau.
MIGRATIONS-REGEL ERNST GENOMMEN: ein Vorher/Nachher-Vergleich zweier LAEUFE
taugt hier nicht, weil copy_rates_from_pos am neuesten Bar ankert und
eintreffende Live-Bars das Fenster verschieben. Die Gleichheit wird deshalb
DIREKT auf der Datenstruktur bewiesen — tests/test_pivotfenster.py mit vier
Faellen: 4.000 Bars x 400 Pivots, Randfaelle, leere Liste, beidseitig
inklusive Grenzen.
Angewandt auf 7 Skripte (auto_signal_v3, breakout_gated, dist_gated, htf_vola,
metalabel, sl_width, trail_be) — mechanisch identische Transformation, alle
kompilieren, Stichprobe gegengelaufen (dist_gated 20k in 1,1 s).
Lehre: die naheliegende Antwort (numpy) war die falsche. Ein Profil kostet zwei
Minuten und haette diese Bremse jederzeit gezeigt — sie lag seit Monaten in
jedem gegateten Backtest.
17 Tests gruen, n-Falle-Scan sauber.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
9887e3d5da |
pytest-Suite: 13 Tests in ~1 s, mutations-geprueft
Im Projekt sind ueber Monate dutzende Szenario-Tests entstanden ("mit 10
Szenarien getestet", "mit 18 synthetischen Szenarien") — alle als
Wegwerf-Skripte, keiner lief je ein zweites Mal. Bei einem System, das man vor
jeder Aenderung neu starten und live verifizieren muss, ist das der teuerste
Teil der Schleife.
Erfasst sind die beiden juengsten Pfade:
· _check_pending_fill (6 Faelle) — u.a. "fremde Position NICHT taggen" und
"derselbe Fill zaehlt nur einmal"
· Selbst-Kalibrierung (7 Faelle) — Episoden-Dedup, WARTEN re-armt, Auswertung
in beide Richtungen inkl. Broker-Offset, fehlende Bar bleibt offen,
Aggregation
Drei harte Regeln in tests/conftest.py: keine Live-DB (frische Temp-Datei je
Test), kein MT5 / kein laufender Server (gestubbt), kein Netz. Das Schema legen
die ECHTEN Konstruktoren an — HistoryLogger UND CandleLogger, denn candles_m1
gehoert nicht zum History-Schema. Ein handgebautes Test-Schema wuerde
irgendwann vom Produktivstand abweichen.
Warum Temp-DB statt Kopie der Live-DB: am 06.08. haben echte candles_m1-Zeilen
in einem vermeintlich leeren Fenster einen Test verfaelscht — zweimal sah es
nach einem Code-Fehler aus, es waren Testfehler.
MUTATIONS-GEPRUEFT, weil eine Suite die immer gruen ist wertlos waere: eine
absichtlich eingebaute "fremde Position wird doch getaggt"-Regression wird
gefangen. Nebenbefund: der Fill-Dedup ist DOPPELT gesichert (_pending_tagged
und der pop aus _pending_tickets) — nur eines zu entfernen faellt nicht auf,
beides zusammen bricht sofort zwei Tests. Gewollte Redundanz, kein
ungetesteter Zweig.
tests_rec_outcomes.py (Wegwerf-Fassung von gestern) und die verwaiste
test_pbreak.db entfernt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
79f3e8efe1 |
Konfidenzintervalle (scipy-Bootstrap) — und sie korrigieren den Befund vom 06.08.
backtest_cost_gate.ci95(): 95-%-Bootstrap-KI des Mittelwerts (Perzentil, 2000 Resamples, random_state fest -> reproduzierbar, ab n>=20). kennzahlen() liefert es als neuen Schluessel `ci` — rein additiv, alle 11 Aufrufer lesen weiter nur n/wr/oer/sr/pf, keine dokumentierte Zahl verschiebt sich (geprueft). Sofortiger Ertrag: der erste Lauf relativiert das `3 von 7 tragen` vom 06.08. Auf der entscheidenden Spalte C (Beruehrungs-Fill): KONTROLLE Squeeze H1 [+0,037…+0,229] H2 [+0,225…+0,366] PDH / PDL H1 [-0,032…+0,544]⚠ H2 [+0,155…+0,764] Equal H/L H1 [+0,001…+0,425] H2 [-0,035…+0,356]⚠ Asian Range H1 [-0,067…+0,357]⚠ H2 [-0,060…+0,332]⚠ Nur der Squeeze hat in BEIDEN Haelften ein Intervall klar ueber null. Bei Asian Range enthalten beide die Null — als Ueberlebender war das zu stark formuliert. Formulierung auf `1 gesichert, 2 unklar` korrigiert. Zwei verschiedene Fragen, beide noetig: die 2-Stichproben-Regel prueft die Stabilitaet des VORZEICHENS ueber Regime, das KI die Unterscheidbarkeit vom RAUSCHEN innerhalb einer Stichprobe. Hier war Ersteres erfuellt, Letzteres nicht. Ein KI, das die Null enthaelt, heisst nicht widerlegt, sondern nicht belegt — und zwei gleichgerichtete Haelften sind zusammen mehr Evidenz als jede fuer sich. Grenze dokumentiert: der Bootstrap unterstellt unabhaengige Ziehungen. Fuer die sequentielle Sim mit EINEM Slot passt das; fuer ueberlappende Fenster (analyze_hl_funding.py) ist er zu optimistisch — dort braeuchte es einen Block-Bootstrap. ci95 ist dafuer ausdruecklich NICHT gedacht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
e69907edbe |
pyflakes eingebunden — zwei echte Fehler in core/trader.py gefunden
Auf die Frage nach einem Lint-Modul: pyflakes installiert und als Stufe A2 in tools/check_nfalle.py eingebunden. py_compile prueft nur die SYNTAX; ein Tippfehler in einem NAMEN ist syntaktisch einwandfrei — und dieses Projekt hat sehr viele breite except-Exception-Bloecke, in denen ein NameError unsichtbar bleibt. Beim ERSTEN Lauf zwei echte Fehler, beide in core/trader.py, beide nutzten log. (den Namen gibt es dort nicht, nur log_trade/log_hist): · _broker_offset_s(): der NameError lief in das except-pass UND nahm die darunter stehende Zuweisung self._boff = int(off) mit -> ein echter Broker-Zeitzonen-Wechsel waere nie uebernommen worden, dauerhaft und lautlos. Ausgerechnet der Zweig, der als Deployment-Drift Fall 4 gebaut wurde (falscher Offset -> Time-Stop-Alter negativ). · modify_sltp(): steht NICHT in einem try -> der Fehler lief bis in /api/sltp. Der Broker hatte SL/TP bereits geaendert, der User bekam trotzdem eine Fehlermeldung, und set_sltp kam nie bis trail.deactivate() — das Trailing blieb an und haette die Handeingabe zurueckgezogen. Seit dem Initial-Commit drin. Beide behoben (log_trade). Zusaetzlich die Annotation 'HistoryLogger | None' ueber if TYPE_CHECKING sauber importiert (String-Annotation, kein Laufzeit-Import, kein Zirkel). Projektweit jetzt 0 undefinierte Namen. Schweregrad-Trennung ist Absicht: nur undefined name / syntax error werden gemeldet, die ~105 kosmetischen Hinweise unterdrueckt. Auch 'redefinition of unused' bleibt draussen — es trifft das legitime Muster hook = None + bedingtes def hook (in zwei Backtests geprueft, beide korrekt). Eine Pruefung mit Dauer-Treffern wird ignoriert, und mit ihr die eine echte. Backtest-Dateien nicht angefasst (Zahlen). Neustart verifiziert, Log sauber. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
394786b312 |
CLAUDE.md: die \n-Falle als Dauerregel festgehalten
Nachtrag zum Scanner-Commit — die Doku-Ergaenzung war dort durchgefallen, weil mein eigenes Heredoc an den deutschen Anfuehrungszeichen scheiterte. Damit ist die Regel dreimal an EINEM Tag belegt: engine.py, measurement_reminder.py und das Dokumentieren der Regel selbst. Regel jetzt in CLAUDE.md: mehrzeilige Strings mit \n oder Text mit deutschen Anfuehrungszeichen nie per Heredoc schreiben, sondern ueber den Edit-Weg. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5a89544a27 |
tools/check_nfalle.py: Scan gegen die \n-Falle — Projekt ist sauber
Auftrag "ueberpruefe alle dateien auf \n-Falle". Die Falle: ueber ein
Shell-Heredoc geschriebener Code macht aus einem gemeinten \n einen ECHTEN
Zeilenumbruch mitten im String-Literal. Heute zweimal passiert (Telegram-Text
in engine.py, Reminder-Eintrag in measurement_reminder.py).
Der Scan prueft in beide Richtungen:
A) kompiliert alle .py (161 Dateien) — sauber
B) JS: unabgeschlossene String-Literale — app.js sauber
C) UMGEKEHRT: literales \n als sichtbarer Text in HTML-title= und Markdown
— alle sauber
D) Signatur der beiden heutigen Faelle (Zeile endet offen, naechste besteht
nur aus einem Quote) — keine
⚠ Fehlalarm im Scanner selbst gefunden und behoben: Quotes zu ZAEHLEN meldet
'"' als offenes Literal (gueltiges JS mit einem Anfuehrungszeichen darin, real
in app.js). Der Scan verfolgt jetzt zeichenweise den AKTIVEN Quote-Typ.
Die betroffene app.js-Stelle trotzdem aufgeraeumt: schliessendes
Anfuehrungszeichen jetzt als U+201C statt ueber eine Konkatenation mit '"'.
Regel in CLAUDE.md ergaenzt: mehrzeilige Strings mit \n nicht per Heredoc
schreiben, sondern ueber den Edit-Weg.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
b858ae9aa2 |
Liq-Trend und die uebrigen offenen Modul-Fragen fuer die 25.000er-Messung notiert
Auf die Frage nach Liq-Trend: es bleibt vorerst mit Gewicht 0,5 drin, kommt aber
mit einer ausdruecklichen Begruendung auf die Liste der Verdict-Modul-Messung
(measurement_reminder.py + CLAUDE.md), statt jetzt ohne Datenbasis gehandelt zu
werden.
Offene Punkte fuer den Lauf:
(a) Liq-Trend (0,5) — +0,20/+0,32 ueber nur 132 Episoden. ⚠ Dieselbe Quelle wie
das am 06.08. entmachtete Orderbuch-Modul, und HL-Preisdaten laufen gemessen
hinter Pepperstone her (51 % Treffer nach 6 s). Als einziges verbliebenes
HL-Modul mit Stimmrecht zuerst pruefen.
(b) Muster (0,25) — +1,27/+0,67 bei n=88, zu duenn.
(c) H1 (1,5) — nur 19 Episoden, traegt aber 38 % des Nadel-Einflusses;
praediktiv nicht beurteilbar.
(d) Elliott und Orderbuch sind entmachtet, werden aber WEITER geloggt — die
Reihe darf fuer diese Messung nicht abreissen.
Stand 15.591 von 25.000 Verdicts (62 %). Auswertebefehl auf
analyze_verdict_modules.py praezisiert, mit Hinweis auf die Episoden-Bildung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
4155afb434 |
Widerspruch "stark LONG" bei WARTEN aufgeloest (v=149)
User-Fund: Headline "◌ WARTEN · M30", darunter "stark LONG · 2 von 2
stimmberechtigten fuer LONG (7 ohne Aussage)". Beide Zahlen stimmten, die
Kombination war irrefuehrend. Zwei Ursachen:
(1) Die Headline nannte den Grund nicht. Er stand im Snapshot
(wave_signal.block = min_conf, conf 49 gegen 55 % — die Welle HATTE eine
LONG-Richtung, ihr fehlten sechs Punkte), gerendert wurde er aber nur bei
breakout_pending. ⚠ Meine Luecke vom 06.08.: ich habe die Tages-Verteilung
(#vd-blocks) gebaut und den AKTUELLEN Grund vergessen. Jetzt Mapping fuer
alle neun Gate-Codes an der Headline.
(2) "2 von 2" las sich wie Einstimmigkeit — es waren 2 von 7 sichtbaren
Modulen (H1 1,5 und Liq-Trend 0,5), und die Welle, die als einzige die
Order steuert, war nicht dabei. bias=1,0 ist arithmetisch korrekt, aber die
Basis war winzig. Das Entmachten von Elliott/Orderbuch hat das Problem
nicht erzeugt, aber verschaerft.
Neu: Zeile fuehrt mit der Basis, "stark/leicht" entfaellt solange weniger
als die Haelfte der Module spricht, stumme Welle wird ausdruecklich genannt.
Live gegengerechnet:
"◌ WARTEN · M30 · Konfidenz 49 % < 55 % — Setup zu schwach"
"2 von 7 Modulen sprechen, alle fuer LONG · die Welle ... schweigt"
Reine Anzeige — Gewichte, Gates und Order-Logik unveraendert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
cf94679022 |
Setup- und Lauf-Zeile aus den Meldungen entfernt (v=148)
Beide .kv-Zeilen samt JS-Zuweisungen (wave-setup, wave-move) raus. Das Setup
steht ohnehin in der Verdict-Headline und den Gruenden, der "Lauf" beschrieb
die Vergangenheit ohne Handlungsbezug.
⚠ Fallstrick beim Entfernen, korrigiert: die Zeile
`const w = d.wave_signal || {}, ws = ...` stand direkt ueber der
Setup-Zuweisung und ist zunaechst mit rausgefallen — `w` wird aber weiter
unten noch achtmal gebraucht (Gruende, Button-Blinken, Close-Alarm,
News-Konflikt). Ein ReferenceError mitten in render() bricht den GESAMTEN
Render ab und friert das Dashboard ein.
Gegenprobe ergaenzt: alle $("id")-Zugriffe der app.js gegen die IDs der
index.html geprueft — 0 verwaiste Referenzen. Klammern-Balance ok,
v=148 ausgeliefert, eine Instanz auf 8000.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
caa937f87d |
Gesamtempfehlung: nur noch Module mit Stimmrecht · Tooltips ueberall (v=147)
· Modul-Chips: neues `used`-Flag in _verdict.add(). used=False = dauerhaft entmachtet (Elliott, Orderbuch — beide heute gemessen ohne Inhalt), das Frontend filtert sie aus. ⚠ Sie bleiben im Snapshot und in verdict_votes: log_verdict_votes speist daraus die Telemetrie und die 25.000-Verdict-Messung braucht die Reihe weiter. Ausgeblendet wird die Anzeige, nicht die Messung. Module mit weight=0 aus SITUATIVER Stille (Welle bei WARTEN, Squeeze ohne Ausbruch) bleiben sichtbar. · #vd-note (Muenzwurf-Hinweistext) entfernt, samt CSS. Die Aussage steht weiter im Karten-Tooltip. · Tooltips auf allen Dashboard-Anzeigen (59 title-Attribute): Karten, Header-Boxen, Trade-Leiste, Anzeige-Elemente. Wo eine Messung existiert, steht sie drin. Gesetzt ueber set_tooltips.py — idempotent, ergaenzt nur fehlende title=. Verifiziert: keine Anzeige mehr ohne Tooltip, keine doppelten IDs, Tag-Balance ok, v=147 ausgeliefert, Elliott/Orderbuch used=False, eine Instanz auf 8000. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
38b493de35 |
signal_pending_entry abgeschaltet (User-Entscheidung)
Der Touchfill-Test hat den Pfad in allen sechs Feldern negativ gezeigt (-0,18 bis -0,48, PF 0,38-0,71) und damit schlechter als der Markt-Einstieg: an einem WANDERNDEN Level faengt eine ruhende Order systematisch die Fehlausbrueche ein (441 statt 328 Fills). ini auf false; der Schluessel lebt nicht in runtime_state.json, die ini greift also direkt. Backup angelegt. Live verifiziert: signal_pending=False, squeeze_pending=True (dort steht die Box still, Test bestanden). Neu im Config-Waechter (14 ueberwachte Werte, validiert = false). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
ec6a2c5842 |
SIG-Pending faellt durch: Look-ahead 0,8 R, schlechter als der Markt-Einstieg
Der offene Test aus dem Fill-Befund ist gelaufen (backtest_signal_touchfill.py, 80k M5, voller Live-Gate-Stack, kanonischer Exit, Echtkosten): Konf A) Markt B) Close-Bruch C) BERUEHRUNG (real) >=55 -0,015/-0,172 +0,381/+0,315 -0,392/-0,338 >=65 -0,024/-0,085 +0,367/+0,385 -0,478/-0,471 >=75 -0,148/-0,310 +0,288/+0,136 -0,184/-0,202 C ist in allen sechs Feldern negativ (PF 0,38-0,71). Der Look-ahead-Aufschlag betraegt 0,77-0,85 R — groesser als beim Momentum (0,45) und Squeeze (0,32). ⚠ C ist sogar schlechter als der Markt-Einstieg. Sichtbar am Trade-Zaehler: C hat MEHR Fills als B (441 gegen 328, 659 gegen 455) — die zusaetzlichen sind die Beruehrungen, die zurueckfallen. Eine Order an einem WANDERNDEN Level faengt systematisch die Fehlausbrueche ein. Damit ist die Vorhersage bestaetigt: entscheidend ist nicht "Level statt Markt", sondern ob das Level STILLSTEHT. Squeeze-Box haelt (+0,124/+0,292), _pend und Momentum wandern und fallen durch. Empfehlung dokumentiert: signal_pending_entry = false. Nicht eigenmaechtig umgestellt — Live-Schalter sind User-Entscheidungen, und auto_signal ist ohnehin aus (der Pfad platziert derzeit keine Orders). Migrations-Pruefung ehrlich vermerkt: der Vorher/Nachher-Vergleich war nicht bitgenau (ein Trade in H2), Ursache sind zwischenzeitlich eingetroffene Live-Bars, nicht der Patch — H1 war identisch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
2cdd1ba0e8 |
Hyperliquid geprueft: Orderbuch-Stimme raus, Funding gemessen (traegt nicht),
Kontext in die Meldungen (v=145)
Direkt gegen die HL-API geprueft statt aus dem Code geschlossen.
ANGEBOT: 4 Oel-Maerkte (2 liquide: xyz:CL OI 3,07 Mio, xyz:BRENTOIL 2,25 Mio),
je Markt mark/oracle/funding/open_interest/day_volume + l2Book (20 Level je
Seite). Historie: fundingHistory 5.095 Stundenwerte ueber 7 Monate inkl.
premium. Open Interest hat KEINE Historie -> waere sammelpflichtig.
Netz-Frage geklaert: config sagt testnet (leeres Buch, 0 Bids/0 Asks), aber es
sind zwei Schalter — [hyperliquid] network steuert das Handeln (aus),
[sim] price_network die Daten (mainnet, live bestaetigt).
(1) Mehr Orderbuch-Daten: NEIN. Zweimal unabhaengig gemessen — bookflow_report
0,2-1,0 bp gegen eine ~3-bp-Schwelle und KIPPT; Lead-Lag: Pepperstone
fuehrt, HL trifft nach 6 s zu 51 %.
(2) Modul "Orderbuch" Gewicht 0,5 -> 0. Ueber 2.688 Episoden beidhaelftig
negativ (-0,054/-0,066, 49 % Treffer). Chip bleibt.
(3) analyze_hl_funding.py: Funding/Premium gegen den CFD, 2 Haelften.
⚠ Der erste Lauf meldete mehrere "robuste" Buckets und war FALSCH —
ueberlappende Forward-Fenster (aus n=506 werden ~21 unabhaengige Faelle)
und global gebildete Quintile (Bucket mit der Zeit konfundiert). Dass
Funding- und Premium-Tabelle fast identisch waren, war der dritte Hinweis:
HL rechnet das Funding aus dem Premium. Entueberlappt haelt kein Bucket.
(4) hl_ctx in den Meldungen (#hl-note) als reine Anzeige.
⚠ Zwei Bau-Fallen behoben: der Aufruf erbte den 2-s-Timeout der Waende und
lief still ins Leere (braucht real 7,2 s), und er haette den Trend-Loop
blockiert -> Daemon-Thread wie beim Wirtschaftskalender.
Live verifiziert: hl_ctx befuellt, Orderbuch weight=0 bei erhaltenem Chip,
v=145 ausgeliefert, eine Instanz auf Port 8000.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
874ee16e00 |
Gesamtempfehlung: Selbst-Kalibrierung, voller Ausrichtungs-Split, Block-Gruende,
Elliott entmachtet (v=144)
Vier Verbesserungen, alle aus dem Gemessenen abgeleitet — kein neues Signal.
Ausgangspunkt: die Karte hat genau eine belegte Funktion, das Veto; als Prognose
ist sie ein Muenzwurf (48-51 % ueber 1.071 Episoden).
(1) SELBST-KALIBRIERUNG. Neue Tabelle rec_outcomes: eine Zeile je EPISODE
(Richtungswechsel, nicht je Minute), Auswertung ~alle 5 min gegen candles_m1
nach 30/60 min, Snapshot rec_track, Zeile #vd-selfcal. Gegen 50 % zu lesen.
Warum der groesste Hebel: die Qualitaet war bis heute unsichtbar und musste
auf Nachfrage rueckwirkend gemessen werden. Dasselbe Muster
(pbreak_predictions) hat den Ausfall des P(break)-Modells LIVE aufgedeckt.
Mit 4 Szenarien getestet (tests_rec_outcomes.py). Zwei Fehlschlaege dabei
waren Testfehler, keine Code-Fehler — dokumentiert.
(2) alignment_stats auf die VOLLE Historie (1.216 statt 40 Trades) und
zusaetzlich je Lot. Absolute Euro-Vergleiche sind bei wechselnder
Positionsgroesse ungueltig (Lehre 04.08.). Damit steht die einzige
beidhaelftig robuste Aussage der Karte auf ihrer vollen Stichprobe.
(3) Block-Gruende sichtbar (block_mix -> #vd-blocks): "heute X % ohne Block ·
entry_room … · min_conf …". Bisher nur per DB-Abfrage zu beantworten.
(4) ELLIOTT: Verdict-Gewicht 1,0 -> 0. Gemessen ueber 15.544 Zeilen hatte es mit
1.384 Episoden die groesste Stichprobe der Tabelle und ist darin flach
(-0,075/+0,032, 50 % Treffer) — bei 25,9 % Einfluss auf die Nadel, weil es
in nur 1 % der Zeilen schweigt. Chip bleibt, Stimme entfaellt.
⚠ Folge: die Nadel schlaegt staerker aus (real +0,33 -> +1,00).
⚠ Namenskollision beim Bau gefunden und behoben: die neue Klasse hiess zuerst
.vd-track — so heisst bereits die Schiene der Bias-Nadel; sie waere
ueberschrieben worden. Jetzt .vd-selfcal.
Live verifiziert: alignment je Lot, block_mix (93 von 1381 ohne Block),
rec_outcomes angelegt, Elliott weight=0 bei erhaltenem Chip, v=144 ausgeliefert,
eine Instanz auf Port 8000.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
4f85d2ce75 |
Ausrichtungs-Split ueber die ganze Historie: die Empfehlung ist ein Veto
Bisher stand dazu nur alignment_stats(40). Ueber alle 1.216 geschlossenen Trades, je Lot normiert und in zwei Haelften: MIT Signal n=354 WR 56,5 % +3,22 EUR/Lot (H1 +0,37 / H2 +5,62) GEGEN Signal n= 87 WR 40,2 % -6,60 EUR/Lot (H1 -7,01 / H2 -5,68) OHNE Signal n=775 WR 56,6 % +0,36 EUR/Lot (kippt: -2,68 / +0,76) Die schaerfste Zeile ist MIT gegen OHNE: 56,5 % zu 56,6 %, identisch. Der Empfehlung zu FOLGEN bringt gegenueber "ohne Empfehlung handeln" gemessen nichts. Nur sie zu VERLETZEN kostet — und das robust in beiden Haelften. Damit ist die Rolle praezise: Veto, keine Prognose. Das ist zugleich die einzige Richtungsaussage ueber die Gesamtempfehlung, die den 2-Stichproben-Test besteht. Grenze benannt: gegen hat n=87 und die Zuordnung ist konfundiert (der Mensch waehlt aus, wann er gegen das Signal geht). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
7e03e481ca |
Verworfene Setups auf der Ausfuehrungs-Achse — und der Squeeze steht mit auf null
User: "backteste alle verworfenen Signale". Bewusst kein Komplettlauf (der lief am 04.08., 14 Klassen, alle blieben verworfen) — neu ist genau eine Achse, der Einstiegspreis, angewandt mit der heutigen Korrektur (Fill bei BERUEHRUNG statt bei Schluss-Bruch) und nur dort, wo sie greifen kann: stehendes Level + Ausbruchsrichtung. Ergebnis (Variante C, 80k M5, 2 Halbjahre): KONTROLLE Squeeze +0,133/+0,293 (reproduziert touchfill — Pipeline ok) ORB (4 Varianten) faellt durch (bestaetigt 2026-07-17) PDH/PDL +0,246/+0,464 Asian Range +0,142/+0,134 Equal H/L +0,218/+0,170 Alle drei nachbar-robust (11 Zellen, keine kippt). ⚠ Das sind keine drei neuen Signale: PDH/PDL, Asian-Range-Extrem, Equal H/L und die Squeeze-Box sind dasselbe — waagerechtes Level aus frueheren Extremen, gebrochen, ruhende Order, kanonisches Trailing. Deckt sich mit der Kontrolle "beliebige Box" aus dem Multi-Instrument-Lauf. ⚠⚠ Mit der gemessenen Exit-Slippage bleibt fast nichts uebrig. Beim guenstigsten Wert (0,0124 $, Tagfenster): PDH/PDL +0,099/+0,386 haelt, Equal H/L duenn, Asian Range faellt — und der LIVE laufende Auto-Squeeze steht in H1 bei -0,002. Die Edges dieser Familie liegen in derselben Groessenordnung wie die Ausstiegskosten, und die Slippage-Zahl ist eine Untergrenze. Konsequenz: kein neues Setup bauen. Der naechste Hebel ist die Ausfuehrungsqualitaet am EXIT, nicht ein weiteres Einstiegs-Signal. Offen und benannt: Volume-Profile-LVN und die Chartmuster-Nackenlinie qualifizieren sich, wurden aber nicht gemessen (Laufzeit bzw. Detektor). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
45bfc87153 |
Squeeze auf 9 Instrumenten · Momentum neu gemessen · Fill-Annahme korrigiert · UI
Drei Messungen und eine UI-Aenderung, ausgeloest von der Frage, ob das Konzept zu ueberdenken ist. 1) SQUEEZE AUF ANDEREN INSTRUMENTEN (backtest_squeeze_multi.py): 7 von 9 halten alle vier Bedingungen, alle nachbar-robust. Die zwei Durchfaller (Gasoline, USDX) sind exakt die mit Spread >= ATR — der Test scheitert, wo er muss. ⚠ 7 sind nicht 7 unabhaengige Tests (Crude/Brent, Gold/Silber, NAS/GER40 korrelieren), und die Kompression traegt weniger als der Ausbruch selbst (Kontrolle "beliebige Box" ist ueberall positiv). 2) MOMENTUM (backtest_momentum_v2.py): bleibt verworfen. Mit Level-Order sah es nach +0,4 aus — das war Look-ahead. Eine liegende Order fuellt bei der ersten BERUEHRUNG, nicht erst wenn der Bar jenseits des Levels SCHLIESST. Ehrlich gerechnet: -0,04..-0,09 in H1. Struktureller Grund: das Momentum-Level wandert jede Bar mit C[i-N] und ist damit kein Ort, an dem eine Order liegen bleibt. 3) FILL-ANNAHME (backtest_squeeze_touchfill.py): dieselbe Frage fuer den Squeeze. Er haelt (+0,124/+0,292, PF 1,24/1,64) und die Umstellung auf ruhende Orders bleibt richtig (Market -0,158/-0,006). ABER die heute zitierten +0,456/+0,611 sind als Live-Erwartung ~0,32 R zu hoch. Die Beruehrungs-Variante trifft fast genau das original validierte Band +0,14..+0,23. ⚠ OFFEN: derselbe Test fehlt fuer den SIG-Pending-Pfad, der seit 05.08. live ist — und dort ist ein schlechteres Ergebnis zu erwarten, weil das _pend-Level wandert statt stillzustehen. 4) UI (v=143): fester Vorbehalt unter der Headline und "Score" statt nackter Prozentzahl am Ring. Statisches Markup, kein JS. Eigener Fehler dokumentiert: der erste Momentum-Entwurf pruefte nicht, ob das Level als Stop-Order auf der richtigen Marktseite liegt, und lieferte ØR +2,2 — unmoeglich, und genau daran erkennbar. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
64eef14871 |
analyze_signal_live.py: die Richtungsaussage der Empfehlung ist ein Muenzwurf
User-Beobachtung "die Empfehlungen heute waren fast immer gegenlaeufig" — vor einer Konzeptdebatte gemessen, und zwar an den TATSAECHLICH ausgegebenen recommendations-Zeilen (nach allen Live-Gates), nicht im Backtest. 20.365 Zeilen -> 1.071 Episoden (08.05.-06.08.), gegen die Drift der jeweiligen Haelfte gelesen. Trefferquote ueber alle sechs Felder 48,3-51,1 %. Bester Ueberschuss +0,085xATR bei 60 min — unter der B3-Huerde (0,1) und weit unter den realen M5-Kosten (0,265). Auf 120 min ist H2 mit -0,259 klar negativ. Der Anlasstag war typisch, kein Ausreisser: 8 von 10 Episoden auf 30 min gegenlaeufig; die fuenf Vormittags-SHORTs liefen gegen einen Tag, der von 75,5 auf 78 stieg. Wichtige Einordnung, damit daraus nicht der falsche Schluss gezogen wird: dasselbe Signal ist mit ruhender Order am Bestaetigungs-Level in beiden Haelften klar positiv (+0,35/+0,32, PF 2,2) und am Markt negativ. Der Ertrag kommt aus Einstiegspreis und Exit-Asymmetrie, nicht aus der Trefferquote — wie beim Squeeze (43-46 % Treffer, trotzdem positiv). Die Headline ist damit kein Kursurteil, sondern ein Ausloeser fuer eine Level-Order. Die Suche nach einem besseren Richtungssignal folgt daraus NICHT — die ist mit 23 verworfenen Eingriffen beantwortet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
58af6eba43 |
Automatischen S/R-Close abgeschaltet (User-Vorgabe)
auto_sr_close = false in der ini UND in runtime_state.json — beide Stellen noetig, weil die Runtime-Datei die ini beim Start ueberschreibt (genau die Falle, durch die auto_signal am 31.07. unbemerkt weiterlief). ⚠ Das ist eine Abweichung von der Messung, kein Nachvollzug einer: mit dem am 31.07. nachtrainierten P(break)-Modell schlaegt der gegatete S/R-Close die Trailing-Baseline in BEIDEN Haelften (Schwelle 0,35: H1 +357 R, H2 +1418 R gegen die Baseline). Nicht zu verwechseln mit dem PAUSCHALEN S/R-Close, der 2x verworfen wurde — das P(break)-Gate ist der Unterschied. Abgeschaltet ist nur die Ausfuehrung. Der App-Hinweis, die P(break)-Chart- Linien, der Copilot-Kontext und das Prognose-Tracking laufen weiter (_sr_close_hint wird in snapshot() unabhaengig vom Schalter berechnet). Schutz weiterhin: Broker-SL 2xATR, Trailing, Time-Stop. Neu im Config-Waechter (validiert = true), damit die Abweichung sichtbar bleibt; er meldet sie jetzt korrekt. Backups der ini und runtime_state angelegt. Live verifiziert: snapshot.auto_sr_close=False, Log "S/R-Close=aus", eine Instanz auf Port 8000. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
217981ccf5 |
analyze_slippage_holdtime.py: die offene Zahl gemessen — M1 ist entschieden
Der M1-Squeeze hing an der Exit-Slippage bei kurzer Haltedauer. Die bisher zitierten "Median 0,017 / Ø 0,234" waren die Statistik NUR ueber die Ausreisser — analyze_execution.py zaehlt ausschliesslich Faelle, die schlechter als der Initial-SL endeten. Sauber ist E[Slippage] >= P(gap>0) x Ø(gap|gap>0). Unkontaminiert, weil das Trailing den gap nur negativer machen kann: ein positiver gap ist zwingend Slippage. Ueber 317 SL-Closes, <30 min: alle Stunden 0,0370 $ (0-15 min allein 0,0470) nur 10-17 Uhr 0,0124 $ (0-15 min allein 0,0058) Der Schwanz sitzt ausserhalb von 10-17 — bei kurzen Trades dort 8x kleiner. Gleiche Ursache wie beim Spread (Buchtiefe), also Mechanismus statt Zufall. Endvergleich mit dem gemessenen Wert je Fenster: M1 alle Stunden -0,107/-0,161 PF 0,83/0,76 FAELLT HART DURCH M1 10-17 +0,354/+0,247 ΣR +150/+121 M5 alle Stunden +0,401/+0,261 ΣR +108/+71 M5 10-17 +0,751/+0,444 ΣR +68/+45 Der ΣR-Vorsprung von M1 ueber alle Stunden war reines Artefakt der Annahme "keine Exit-Slippage". Auf demselben Fenster bleibt ein echter Zielkonflikt: M5 doppelt so gut je Trade, M1 doppelt so gut in der Summe — bei EINEM Slot. Urteil: nicht umstellen. Der entscheidende Parameter ist nur als Untergrenze bekannt und M1 hat davon nur ~3x Luft bis zur Kippgrenze (M5 ~7x); die Stichproben sind duenn; 80 Tage = ein Regime. Die Bedingung fuer ein spaeteres Ja ist in CLAUDE.md benannt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
92187d7d32 |
backtest_squeeze_m1.py: Squeeze auf M1 gemessen (Variante B)
Nicht ausgeschlossen — aber in JEDER Variante schlechter je Trade als die M5-Kontrolle auf demselben Fenster (beste M1-Variante +0,474/+0,387 gegen +0,605/+0,491). Alle Nachbar-Parameter halten, Einstiegs-Slippage bis 0,20xATR haelt, der skalierte ATR-Floor erzeugt den Befund nicht (Kontrolle ohne Floor bestaetigt), Broker blockt nicht (trade_stops_level = 0). Entscheidend ist die EXIT-Slippage, und sie trifft M1 doppelt so hart, weil sie absolut ist: M1 kippt bei ~0,04 $, M5 erst bei ~0,09 $ (Faktor 2,2 = das ATR-Verhaeltnis). Gemessener Median 0,017 $ -> beide halten; gemessener Ø 0,234 $ -> beide fallen. Die entscheidende Zahl — Slippage bedingt auf Haltedauern <30 min — ist ungemessen. Urteil: nicht umstellen. M1s Vorteil kommt allein aus der 4,3-fachen Frequenz, und genau die multipliziert die ungemessene Groesse. Zwei Methodik-Lehren dokumentiert: der Haertetest lief zuerst auf der schwaechsten statt der besten Variante (Auswahl nach Reihenfolge statt nach Ergebnis), und die Regel "nicht schlechter als die Kontrolle" war wieder unterspezifiziert (ØR und ΣR zeigen gegenlaeufig) — deshalb gibt zeig() jetzt beide Spalten aus. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
c888bcc3e8 |
analyze_scalping_costs.py: B3-Check fuer ein M1-Scalping-Modul
User-Frage "wie sinnvoll waere ein Scalping-Modul auf 1M-Basis". Vor dem Bau gemessen, weil es zuerst eine Kosten- und keine Signalfrage ist: der Spread ist absolut ~konstant und skaliert nicht mit der Zeitebene, die Bewegung schon. Spread/ATR im Median: M1 0,319 · M5 0,193 · M15 0,133. Eine mittlere M1-Kerze ist nur 3,4x so gross wie der Spread. Noetige Trefferquote bei 1:1 steigt von 50 auf 65,9 %; um 01:00 uebersteigt der Spread mit 1,051xATR_M1 die gesamte durchschnittliche Bar-Spanne. Dazu drei Gruende, die schwerer wiegen als die Kosten: - M1-Historie ist hart bei 80.000 Bars / 80 Tage gedeckelt -> kein 2-Stichproben-Test ueber verschiedene Regime moeglich - das Aufloesungs-Artefakt vom 05.08. trifft M1 am haertesten (Scalp lebt in 2-3 Bars, Bar-Sim ueberschaetzt enge Stops) - der Slippage-Schwanz ist absolut: Ø 0,234 $ uebersteigt einen 2xATR_M1-Stop (0,174 $) bereits im Mittel Empfehlung: kein eigenstaendiges Modul; messbar waere der Squeeze auf M1 (offene Variante B) beschraenkt auf 10-17 Uhr. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
bf838b4d03 |
analyze_squeeze_entry_gap: nur noch echte Bot-Trades zaehlen
Das Skript zaehlte im Abschnitt "per Pending gefuellt" JEDEN Trade seit dem Umbau — es meldete "31 Trades, davon 30 ohne Market-Log-Zeile". Real waren es 5 Bot-Trades (1 Market-Fallback + 4 Pending-Fills); der Rest waren manuelle. Moeglich war die Verwechslung genau deshalb, weil ein Pending-Fill bis zum Fix von heute ohne `setup` gebucht wurde. Jetzt Filter auf SQUEEZE_*/AUTOSIG_* und Setup in der Ausgabe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
3c1442109d |
Pending-Fill: Bot-Trades wurden nicht als solche gebucht
Auftrag "überprüfe die heutigen autotrades": die DB meldete für den 06.08. null Bot-Trades, das Log vier gefüllte SQZ-STOP-Orders. Beides stimmte. Ein Pending-Fill läuft nicht über engine._open — die Position wird von trader._refresh_locked per magic-match adoptiert, und dieser Pfad loggt nur Ticket/Symbol/Richtung/Lots/Preis. Es fehlten setup, sl_at_entry und alle 16 ctx_*-Spalten. Damit war genau die Messpipeline, die den Pending-Umbau vom 05.08. kontrollieren soll, blind für ihn (B4-Monitor, squeeze_b5, squeeze_entry_gap zählten null) — Deployment-Drift Fall 8, erste Variante, bei der nicht die Strategie driftet, sondern ihre Beobachtbarkeit. - history.tag_bot_trade(): UPDATE nur wenn setup IS NULL, stiller Fail-open - engine._pending_tickets: Ticket -> Quelle, beim Platzieren/Stornieren gepflegt - engine._check_pending_fill() im _pos_loop vor dem Pending-Manager; Zuordnung über Positions-Nr == Order-Nr (an allen 4 Fills verifiziert), setzt zusätzlich _bot_open_ticket/_source und die Entry-Zähler 6 Szenarien getestet, darunter die zwei gefährlichen: fremde Position wird nicht getaggt, derselbe Fill zählt bei Folge-Ticks nur einmal. Die 4 Trades des 06.08. nachgetragen (Backup .bak-2026-08-06). ctx_*/sl_at_entry bewusst NICHT nachgetragen: rekonstruiert wären sie später von gemessenen Werten nicht unterscheidbar. Dabei gefunden, dokumentiert, NICHT behoben: der Signal-Pfad setzt/storniert dieselbe Order 4x in 76 s bei identischem Level, weil block_reason zwischen entry_room und breakout_pending pendelt (Drift Fall 9). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
730219fce8 |
Wenige Empfehlungen nachgeprueft: Telemetrie-Luecke bei min_conf gefunden und
geschlossen Der 05.08. hat 1427 Zeilen geloggt (Soll ~1440), die Erfassung ist also intakt. 5,0 % gerichtet - und auffaellig ist die Verteilung: alle 71 gerichteten Empfehlungen fielen vor 10:00, danach 16 Stunden lang genau eine. Gegen den gueltigen Massstab (backtest_dist_gated.py, 19,5 % gerichtet) ist entry_room NICHT der Unterschied - es ist live mit 36,5 % sogar seltener als im Backtest (41,4 %). Die Luecke tragen die live-only-Gates, allen voran min_conf (16,1 % live gegen 0,9 % im Backtest), dazu htf_counter, EIA und stale. Telemetrie-Luecke: min_conf-Zeilen schrieben conf_pct = 0, die verworfene Konfidenz stand nur als Fliesstext in den Gruenden. Damit war beim zweitgroessten Blocker nicht feststellbar, ob die Signale knapp (50-54) oder weit (20-30) unter der Schwelle lagen. wave_rec._build gibt den Wert jetzt mit - reine Telemetrie, das Signal bleibt WARTEN. Erste Live-Zeile: conf 52. Das beantwortet noch nicht, ob 55 die richtige Schwelle ist: backtest_conf.py hat das Band 40-54 % als negativ gemessen, eine Senkung ist nicht angezeigt. Die Zahl sagt nur, wieviel Signalmenge direkt hinter der Schwelle steht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
a1a5d560b9 |
Charts-Tab komplett entfernt (User-Vorgabe)
Entfernt: Tab-Button, #view-charts, der gesamte app.js-Chart-Block (Kartenaufbau, renderChart, loadCharts, 20-s-Refresh, Resize-Handler), die Chart-CSS-Regeln, die vendorte Bibliothek web/lightweight-charts.standalone.production.js (164 KB) samt script-Tag - und die Backend-Kette dahinter: /api/bars und engine.get_bars (60 Zeilen). Beide existierten ausschliesslich fuer dieses Tab; geprueft, dass es keinen anderen Aufrufer gibt. Nicht betroffen (sahen nur aehnlich aus): die Chartmuster-Karte (Verdict-Gewicht 0,25, im Tab "SIG Live"), der MQL5-Indikator samt sr_levels.csv-Export (eigener Pfad ueber _write_levels_file) und die Analyse-Module structure/patterns/cone - die speisen den Snapshot, nicht das Chart. Der MT5-Chart bleibt voll bedient. Ein veralteter Kommentar in trader.py, der auf engine.get_bars verwies, wurde auf core/gaps.py umgehaengt. Verifiziert am laufenden Server: /api/bars -> 404, Bibliothek -> 404, data-view="charts" und id="view-charts" nicht mehr im ausgelieferten HTML, 6 Tabs zu 6 Views paarig, keine verwaisten JS-Referenzen, Klammern-Balance ok, keine Fehler im Log. v=142. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
6ff3c15b1d |
Statistik geprueft: Aggregate exakt, aber die Netto-Rechnung ist um Faktor 4,7
zu pessimistisch
Geprueft gegen unabhaengige SQL-Rechnung: /api/stats ueber today/week/all mit
~50 Werten (n_trades, wins/losses/breakeven, total_pnl, avg_win/loss,
gross_win/loss, winrate, profit_factor), dazu die inneren Konsistenzen
(wins+losses+be = n, gross_win-gross_loss = total_pnl, Summe closed_by = n,
Summe hour_stats = wins/losses) und 8 Setup-Zeilen. Ebenso stats_compact und
day_pl. Alles stimmt bitgenau.
Der Defekt liegt in server._add_net / _add_net_setup:
net_pnl = total_pnl - gross_win x 26,375 %. Das unterstellt, die Quellensteuer
sei endgueltig verloren - sie wird aber groesstenteils erstattet, was CLAUDE.md
selbst dokumentiert ("erstattet via taegl. Tax settlement"), die Rechnung aber
ignoriert.
Empirisch aus den echten Broker-Buchungen (history_deals_get, gleicher Zeitraum
wie die Statistik): einbehalten -2236,10, erstattet +1789,65, tatsaechlich
verblieben -446,45. Das Modell rechnet mit -2097,10.
Angezeigtes Netto -1104,67 gegen reales Netto +545,98 - Abweichung 1650,65 EUR,
und das Vorzeichen dreht. Real verbleiben nur 21 % der modellierten Last.
Richtige Loesung waere, die tatsaechlichen WHT-/Tax-Deals zu verwenden statt zu
schaetzen (ueber history_deals_get + Kommentar-Filter exakt abrufbar, gecacht und
unter mt5_lock). Nicht gebaut - Umfang war die Pruefung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
7009541c42 |
Squeeze-Trades bekommen den SL aus M5-ATR (User-Entscheidung), TP unveraendert
trader._calc_sl_tp bekommt die ATR-Zeitebene als Parameter (Default SL_TF = M15); _send/_send_locked/open_long/open_short und place_stop reichen sie durch. Gesetzt wird sie an genau zwei Stellen: engine._open bei source="auto_squeeze" und _manage_squeeze_pending bei quelle="squeeze". Manuelle Trades und Auto-Signal bleiben bei M15. Grundlage backtest_sl_basis.py: auf Squeeze-Entries ist der Ertrag zwischen beiden Basen ein Wash (alle Varianten innerhalb eines Standardfehlers), der Worst-Case sinkt aber von -8,83 auf -2,44 xATR_M5 = Faktor 3. Auf der Wellen-Population ist der weite M15-SL in BEIDEN Haelften besser - deshalb bewusst keine globale Umstellung. Die Multiplikatoren (1,8-2,2 xATR) sind nicht angefasst, nur die Zeitebene. TP bewusst NICHT betroffen (User: "nur fuer SL, der TP soll mit dem Runner mitwachsen"). Geprueft statt angenommen: der von _calc_sl_tp zurueckgegebene TP wird von KEINEM Aufrufer gesendet, beide setzen nur req["sl"]. Das Ziel verwaltet trailing.py dynamisch (3,5 x ATR der Wellen-Zeitebene). Warnkommentar im Code, warum der TP dort nicht mit in die Order darf. 4 Szenarien getestet. Dabei eigene Fehlannahme korrigiert: ohne Pivot greift der 1,2-%-Fallback, der beim M15 vom MINDEST-Deckel aufgeweitet wird - die 2,2x-Obergrenze wird dort gar nicht erreicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |