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>
This commit is contained in:
Axel Hocks
2026-08-06 22:14:02 +02:00
co-authored by Claude Opus 5
parent 64eef14871
commit 45bfc87153
6 changed files with 822 additions and 6 deletions
+116 -1
View File
@@ -319,6 +319,111 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
~15 s→5 s schneller erkannt, dann ~1 s Handeln (`_pos_loop`). Gleiche validierte M5-Regel,
reine Infra (kein Backtest nötig). **Variante B (Squeeze auf M1) = OFFEN/UNBELEGT** — erst
backtesten, wenn der M1-Logger (`candles_m1`, seit 2026-07-21) ab ~2027-01 genug History hat.
- **⚠⚠ DER SQUEEZE TRÄGT AUCH AUF ANDEREN INSTRUMENTEN — 7 von 9 (gemessen
`backtest_squeeze_multi.py`, 2026-08-06).** Anlass: `analyze_signal_live.py` hat
gezeigt, dass die Richtung ein Münzwurf ist; das Grundproblem ist also nicht die
Qualität des Squeeze, sondern seine **Frequenz** (23×/Woche auf einem
Instrument). Auf dieses Problem hat das Projekt bisher zweimal reagiert — mehr
Signale auf demselben Instrument (23 Fehlschläge) oder feinere Zeitebene (Kosten
erledigen es). Die dritte Achse war unberührt: **dasselbe Signal, mehr Märkte.**
| Symbol | Spr/ATR | H1 ØR / PF | H2 ØR / PF | |
|---|---|---|---|---|
| **GER40** | 0,086 | +0,668 / 4,23 | +0,595 / 3,82 | ✅ |
| **SpotBrent** | 0,184 | +0,503 / 2,90 | +0,653 / 3,85 | ✅ |
| **XAUUSD** | 0,028 | +0,559 / 3,74 | +0,556 / 3,95 | ✅ |
| **NAS100** | 0,072 | +0,552 / 3,32 | +0,481 / 2,94 | ✅ |
| SpotCrude *(Kontrolle)* | 0,181 | +0,460 / 2,67 | +0,605 / 3,51 | ✅ |
| XAGUSD | 0,261 | +0,395 / 2,19 | +0,379 / 2,30 | ✅ |
| Copper | 0,327 | +0,300 / 1,83 | +0,375 / 2,11 | ✅ |
| NatGas | 0,651 | +0,229 / 1,52 | +0,240 / 1,56 | ✅ |
| **Gasoline** | **0,972** | 0,610 / 0,35 | 0,148 / 0,76 | ❌ |
| **USDX** | **1,972** | 1,269 / 0,13 | 1,317 / 0,14 | ❌ |
**Die Kontrolle reproduziert** (SpotCrude +0,460/+0,605 gegen bekannt
+0,456/+0,611) — die Pipeline ist in Ordnung. ✅ **Alle 7 sind nachbar-robust**
(Box 10/15 × k 0,1/0,2, 28 Zellen, keine kippt) und halten Einstiegs-Slippage bis
+0,20×ATR.
✅✅ **Die beiden Durchfaller sind der beste Beleg, dass es kein Zufall ist:** es
sind exakt die zwei mit **Spread ≥ ATR** — dieselbe Kosten-Arithmetik, die auch
M1 erledigt hat. Der Test scheitert dort, wo er scheitern MUSS.
**ATR-Floor relativ gesetzt** (0,542 × Median-ATR statt der WTI-Dollar-Zahl
0,06) — ein absoluter Floor wäre auf Gold wirkungslos und auf NatGas ein
Selektions-Artefakt (Lehre aus `analyze_tageszeit.py`).
⚠⚠ **DREI Vorbehalte, die vor einem Bau geklärt gehören:**
(1) **„7 von 9" sind NICHT 7 unabhängige Tests.** Crude/Brent korrelieren ~0,9,
Gold/Silber und NAS100/GER40 ebenso — effektiv sind es eher 34 unabhängige
Fälle, und alle im **selben Makro-Zeitraum**. Mehrere Slots gleichzeitig wären
dann dasselbe Risiko doppelt, keine Diversifikation.
(2) **Die Kompression trägt weniger als der Ausbruch selbst.** Die Kontrolle
„beliebige Box" ist überall ebenfalls positiv (+0,144…+0,533); der Beitrag der
Kompression liegt bei **+0,009…+0,155** und ist bei XAGUSD (+0,009/+0,040) und
NAS100 (+0,034/+0,013) kaum vorhanden. Gemessen wird hier also zu einem großen
Teil **„Ausbruch + unser Exit-Stack"**, nicht der Squeeze im engeren Sinn.
(3) **Swap/Kommission je Symbol, Handelszeiten und Mindest-Lots sind NICHT
modelliert** — nur der Bar-Spread.
⚠ Und der Fill-Befund direkt darunter gilt hier genauso: die Zahlen stehen in
Variante (a), real ist (b) — also rund **0,3 R niedriger** anzusetzen.
- **⚠⚠⚠ FILL-ANNAHME: „am Level einsteigen" hat ZWEI Bedeutungen — und die
teurere ist die richtige (gemessen `backtest_squeeze_touchfill.py` +
`backtest_momentum_v2.py`, 2026-08-06).** Aufgefallen beim Momentum-Nachtest.
| | |
|---|---|
| **(a) Projekt-Standard** | einsteigen, WO das Signal ausgelöst hat — also dort, wo der **Bar-CLOSE** das Level gebrochen hat, zum Level-Preis |
| **(b) Realität** | einsteigen, WANN die liegende Order gefüllt hätte — bei der **ersten Berührung**, egal wo der Bar schließt |
**Live gilt (b).** (a) konditioniert auf den Bar-Schluss, den eine ruhende Order
nicht kennen kann — das ist **Look-ahead**, kein Modellierungsdetail.
**Gemessen auf dem Squeeze (80k M5, 2 Halbjahre, kanonischer Exit, Echtkosten):**
| Fill-Annahme | H1 ØR / PF / n | H2 ØR / PF / n |
|---|---|---|
| (a) Close bricht Level | +0,461 / 2,68 / 801 | +0,605 / 3,51 / 1280 |
| **(b) Berührung (LIVE)** | **+0,124 / 1,24 / 1092** | **+0,292 / 1,64 / 1807** |
**Aufschlag +0,337 (H1) / +0,312 (H2) R je Trade** — und **291 bzw. 527
zusätzliche Fills**, im Schnitt Verlierer (Dochte, die wieder in die Box
zurückfallen; passt zu „54 % aller Box-Ausbrüche kehren binnen 3 Bars zurück",
`backtest_consolidation.py`).
**Der Squeeze hält trotzdem** — beidhälftig positiv, PF > 1. Und die
Umstellung auf ruhende Orders bleibt richtig: (b) +0,124/+0,292 gegen
**Market 0,158/0,006**. Bemerkenswert: (b) trifft fast genau das ORIGINAL
validierte Band **+0,14…+0,23** aus `backtest_breakout_squeeze.py` — der
B4-Maßstab war also die ganze Zeit der realistischere.
⚠⚠ **KONSEQUENZ: die heute mehrfach zitierten +0,456/+0,611 sind als
Live-Erwartung ~0,32 R zu hoch.** Sie bleiben als Vergleich zwischen Market und
Level gültig (dafür waren sie gerechnet), taugen aber nicht als Ertragsprognose.
⚠⚠ **OFFEN und wichtig: derselbe Test fehlt für den SIG-Pending-Pfad**
(`backtest_auto_signal_v3.py`, +0,35/+0,32 — ebenfalls Variante (a), und seit
05.08. live). Es gibt Grund, dort ein **schlechteres** Ergebnis zu erwarten als
beim Squeeze: die Squeeze-Box **steht still**, das `_pend`-Level dagegen
**wandert** bei jeder k×ATR-Gegenbewegung — genau die Eigenschaft, an der das
Momentum-Level gescheitert ist (s. u.), und die Ursache des Pending-Churns
(Drift-Fall 9). **Vor weiteren Schlüssen aus den SIG-Zahlen: nachmessen.**
- **⚠⚠ MOMENTUM-CONTINUATION MIT LEVEL-ORDER NEU GEMESSEN = BLEIBT VERWORFEN
(`backtest_momentum_v2.py`, 2026-08-06, User-Wunsch).** Kein bloßes Wiederholen:
der Lauf von 2026-07-17 stieg am **Bar-Close** ein, und genau diese Annahme hat
am 05.08. Squeeze und Auto-Signal von negativ auf positiv gedreht. Momentum hat
ein sauber definiertes Level (`mom_N` kreuzt X×ATR ⇔ Preis erreicht
**C[iN] ± X×ATR**), die Frage war also offen.
| Variante | H1 | H2 |
|---|---|---|
| A) Bar-Close (der alte Lauf) | 0,10…−0,19 | 0,08…+0,00 |
| B) am Level, Fill bei **Kreuzung** | +0,35…+0,47 | +0,47…+0,56 |
| **C) am Level, Fill bei BERÜHRUNG (echt)** | **0,04…−0,09** | **0,02…+0,07** |
**Alle neun N/X-Kombinationen** sehen in B großartig aus und sind in C
beidhälftig ohne Edge. **Der Aufschlag von ~0,45 R ist reines Look-ahead.**
⚠⚠ **Der strukturelle Grund — und er ist die eigentliche Lehre:** das
Momentum-Level **wandert jede Bar** (`C[iN]` rutscht mit). Es ist damit kein Ort,
an dem eine Order liegen bleiben könnte; sie müsste im 5-Minuten-Takt umgesetzt
werden und fängt dabei jede Zuckung ein. Die Squeeze-Box **steht** — deshalb hält
sie (+0,124/+0,292) und Momentum nicht. **Ein Level ist nur dann ein
Ausführungs-Vorteil, wenn es STILLSTEHT.**
**Zwei eigene Fehler auf dem Weg, beide dokumentiert:** (1) der erste Entwurf
prüfte nicht, ob das Level als Stop-Order überhaupt auf der **richtigen Seite des
Marktes** liegt — dadurch „füllte" die Sim zu längst passierten Preisen und
lieferte **ØR +2,2**, was schlicht unmöglich ist und den Fehler verriet.
(2) Variante B war überhaupt erst nötig, weil ich den Unterschied
Kreuzung/Berührung zunächst nicht gesehen hatte. **Merksatz: eine Zahl, die zu
gut ist, ist ein Befund über den Code, nicht über den Markt.**
✅ Der Befund bestätigt zugleich die heutige Regel aus dem Kerzen-Fade — „ruhende
Order hilft bei Momentum-Entries" — in **präzisierter** Form: sie hilft bei
**Ausbrüchen an stehenden Strukturen**, nicht bei Momentum allgemein.
- **⚠⚠ SCALPING-MODUL AUF M1 = ABGERATEN, bevor überhaupt gebaut wird (gemessen
`analyze_scalping_costs.py`, 2026-08-06, User-Frage „wie sinnvoll wäre ein
zusätzliches Modul Scalping auf 1M-Basis, über das Dashboard steuerbar?").**
@@ -3416,7 +3521,17 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
Signal → **Hinweis-Dialog „trotzdem eröffnen?"** (überschreibbar). CLOSE bei
**negativem** P&L → Sicherheitsabfrage; im Plus/Breakeven direkt. Sonst keine
Token-Dialoge (`require_token=false`). Audio braucht 1× Nutzer-Tap.
- Asset-Version aktuell **v=142** (in `web/index.html` hochzählen, siehe Workflows).
- **UI-Vorbehalt an der Gesamtempfehlung (2026-08-06, v=143):** Unter der Headline
steht jetzt eine feste Zeile (`#vd-note`) — „Richtung ≈ Münzwurf (gemessen 4851 %
Treffer) … lies das als **Auslöser für eine Order am Level**, nicht als
Kursprognose". Der Konfidenz-Ring ist mit **„Score"** beschriftet
(`.vd-ring-lbl`) statt nackt in Prozent. Grund: `analyze_signal_live.py` (4851 %
Treffer über 1.071 Live-Episoden) und `analyze_verdict_calibration.py` (conf_pct
nicht kalibriert, in H2 invertiert). Solange dort „▲ LONG · 89 %" stand, lud die
Anzeige zu einer Erwartung ein, die die Messung nicht deckt.
⚠ Bewusst **statisches Markup, kein JS** — es ist ein Dauerhinweis, kein Zustand;
damit entfällt auch jedes Null-Risiko beim Render (s. Cache-Regel oben).
- Asset-Version aktuell **v=143** (in `web/index.html` hochzählen, siehe Workflows).
Schriftgrößen 2026-07-24 global **+4px** (2× je +2px auf User-Wunsch; Body-Basis
14→18px). ⚠ Betrifft in `style.css` sowohl `font-size:Npx` (71×) ALS AUCH die
`font:<weight> Npx/…`-**Shorthand** (3×: `.ms-chip`/`.ms-bos-lbl`/`.sqm-badge`