Kerzenmuster fuer die Richtung der naechsten Kerze = nein (4. Messung der Klasse)
User-Anschlussfrage. Gemessen mit den ECHTEN Muster-Schwellen aus
core/candles.py (1:1 importiert, kein Nachbau), 80k M5-Bars, 2 Halbjahre,
unveraenderte Schlusskurse ausgeschlossen, 95-%-Intervall je Zelle. Bewertet
wird die Lehrbuch-Lesart, damit sichtbar wird, ob sie stimmt.
Marubozu 46,5 % / 45,2 % beide KI unter 50
Engulfing 47,4 % / 49,5 %
Outside Bar 47,3 % / 48,9 %
langer Koerper 48,5 % / 47,6 %
langer Docht OBEN 49,4 % / 47,8 %
langer Docht UNTEN 50,6 % / 50,6 % beide KI enthalten 50
KEIN Muster erfuellt die vorab fixierte Regel. Trefferquoten 45,2-50,6 %, fuenf
Zellen mit Intervall komplett unter 50 -- in der Lehrbuch-Lesart also
verlaesslich falsch. Die einzige beidhaelftig ueber 50 kippt beim Vorzeichen der
Bewegung (+0,0004 / -0,0037).
Das reproduziert den 60-Minuten-Befund vom 31.07. ("Lehrbuch-Lesart in beiden
Haelften invertiert") jetzt auf dem 1-Bar-Horizont, mit den echten Klassen statt
grober Proxys. Vierte Messung der Kerzen-Klasse.
Und selbst umgedreht zahlt es nicht: groesste Oe-Bewegung 0,0077 $, kippt in der
anderen Haelfte auf -0,0019; halber Spread 0,0100 $, Median-Kerze 0,0400 $.
URTEIL: der Pfeil bleibt bei der kalibrierten Level-Aussage. Nichts geaendert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
eec28e3382
commit
55dc69ef42
@@ -6106,6 +6106,44 @@ was arithmetisch unmöglich ist und den Fehler verriet. Real sind **~11 %** der
|
|||||||
M5-Kerzen unverändert. **Merksatz: wenn A und Nicht-A sich nicht zu 100 %
|
M5-Kerzen unverändert. **Merksatz: wenn A und Nicht-A sich nicht zu 100 %
|
||||||
addieren, ist die Messung kaputt, nicht der Markt.**
|
addieren, ist die Messung kaputt, nicht der Markt.**
|
||||||
|
|
||||||
|
### ⚠⚠ KERZENMUSTER FÜR DIE RICHTUNG DER NÄCHSTEN KERZE = NEIN (`backtest_kerzenmuster_richtung.py`, 2026-08-17)
|
||||||
|
|
||||||
|
User-Anschlussfrage. Gemessen mit den **echten Muster-Schwellen** aus
|
||||||
|
`core/candles.py` (1:1 importiert, kein Nachbau), 80k M5-Bars, 2 Halbjahre,
|
||||||
|
unveränderte Schlusskurse ausgeschlossen, 95-%-Intervall je Zelle.
|
||||||
|
Bewertet wird die **Lehrbuch-Lesart** (±1), damit sichtbar wird, ob sie stimmt.
|
||||||
|
|
||||||
|
| Muster | H1 Treffer | H2 Treffer | Ø Bewegung |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Marubozu | **46,5 % ❌** | **45,2 % ❌** | −0,0019 / +0,0077 $ |
|
||||||
|
| Engulfing | **47,4 % ❌** | 49,5 % | −0,0018 / −0,0009 |
|
||||||
|
| Outside Bar | **47,3 % ❌** | 48,9 % | −0,0019 / +0,0055 |
|
||||||
|
| langer Körper | 48,5 % | **47,6 % ❌** | +0,0009 / +0,0027 |
|
||||||
|
| langer Docht OBEN | 49,4 % | **47,8 % ❌** | +0,0011 / +0,0020 |
|
||||||
|
| langer Docht UNTEN | 50,6 % | 50,6 % | +0,0004 / **−0,0037** |
|
||||||
|
|
||||||
|
✅ **KEIN Muster erfüllt die vorab fixierte Regel.** Die Trefferquoten liegen
|
||||||
|
zwischen **45,2 und 50,6 %** — am oder **unter** dem Münzwurf; **fünf Zellen**
|
||||||
|
haben ein Intervall komplett unter 50, sind in der Lehrbuch-Lesart also
|
||||||
|
**verlässlich falsch**. Die einzige beidhälftig über 50 (langer Docht UNTEN,
|
||||||
|
50,6 %) hat in beiden Hälften ein Intervall MIT der 50 und eine Ø-Bewegung, die
|
||||||
|
das **Vorzeichen kippt**.
|
||||||
|
✅ **Das reproduziert den 60-Minuten-Befund vom 31.07.** („die Lehrbuch-Lesart
|
||||||
|
ist in BEIDEN Hälften invertiert") jetzt auch auf dem **1-Bar-Horizont** — mit
|
||||||
|
den echten Klassen statt der groben Proxys. Damit ist die Kerzen-Klasse zum
|
||||||
|
**vierten** Mal gemessen (Forward-Return 60 min · Fade als Handelsregel ·
|
||||||
|
Fade mit Ausführungs-Achse, 40 Zellen · jetzt 1-Bar-Richtung).
|
||||||
|
⚠ **Und selbst wenn man sie umdreht, zahlt es nicht:** die grösste Ø-Bewegung
|
||||||
|
über alle Zellen ist **0,0077 $** — und die kippt in der anderen Hälfte auf
|
||||||
|
−0,0019. Der halbe Spread beträgt **0,0100 $**, eine M5-Kerze bewegt sich im
|
||||||
|
Median **0,0400 $**.
|
||||||
|
|
||||||
|
✅ **URTEIL: der Pfeil bleibt bei der kalibrierten Level-Aussage.** Es gibt
|
||||||
|
keine Kerzen-Grundlage für eine Richtungsschätzung der nächsten Kerze — weder
|
||||||
|
in der Lehrbuch- noch in der umgedrehten Lesart.
|
||||||
|
⚠ Konsistent mit der Kachel-Entscheidung vom 31.07.: die Kerzen-Anatomie ist
|
||||||
|
bewusst **neutral** gefärbt und nennt die gemessene statt der Lehrbuch-Lesart.
|
||||||
|
|
||||||
### ✅ S/R-AUTO-CLOSE WIEDER AN (User-Entscheidung 2026-08-11)
|
### ✅ S/R-AUTO-CLOSE WIEDER AN (User-Entscheidung 2026-08-11)
|
||||||
|
|
||||||
Frage war: „sollten wir Trades bei einem S/R-Bounce automatisch schliessen?"
|
Frage war: „sollten wir Trades bei einem S/R-Bounce automatisch schliessen?"
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Sagt das KERZENMUSTER die Richtung der naechsten Kerze? (User 2026-08-17)
|
||||||
|
|
||||||
|
Vorlauf: `backtest_naechste_kerze.py` hat gezeigt, dass die naechste M5-Kerze
|
||||||
|
grundsaetzlich nur ueber 1-Bar-Mean-Reversion schwach vorhersagbar ist (51,3 %),
|
||||||
|
und dass der Effekt 50-100x unter dem Spread liegt. Dort wurden aber nur GROBE
|
||||||
|
Proxys geprueft (letzte Kerze fort/umkehr, langer Docht).
|
||||||
|
|
||||||
|
Hier die richtige Frage: die echten MUSTER-Klassen — mit denselben Schwellen wie
|
||||||
|
der Live-Detektor `core/candles.py` (Marubozu, langer Koerper, langer Docht
|
||||||
|
oben/unten, Spinning Top, Doji, Engulfing) plus die Zwei-Bar-Muster
|
||||||
|
Inside/Outside Bar, die dort nicht klassifiziert werden.
|
||||||
|
|
||||||
|
⚠ WAS BEREITS GEMESSEN IST (und was hier NEU ist):
|
||||||
|
`backtest_candles.py` (31.07.) hat die Muster gegen den Forward-Return ueber
|
||||||
|
**60 Minuten** gemessen — Ergebnis: die Lehrbuch-Lesart ist in BEIDEN Haelften
|
||||||
|
INVERTIERT („langer Koerper = Fortsetzung" -0,059/-0,076; „2x Volumen = echt"
|
||||||
|
-0,117/-0,204, monoton falsch herum). `backtest_candle_fade.py` und `_fade2`
|
||||||
|
haben den Fade als HANDELSREGEL zweimal verworfen (zuletzt alle 40 Zellen
|
||||||
|
negativ). NEU ist allein der **1-Bar-Horizont** — die Frage des Users.
|
||||||
|
|
||||||
|
VORAB FIXIERTE REGEL: ein Muster taugt, wenn es
|
||||||
|
(1) in BEIDEN Haelften > 50 % trifft, (2) beide 95-%-Intervalle die 50
|
||||||
|
ausschliessen, (3) n >= 300 je Haelfte, und (4) die Oe-Bewegung in
|
||||||
|
Vorhersagerichtung den HALBEN Spread (0,0100 $) schlaegt.
|
||||||
|
⚠ (4) ist die harte Huerde: eine M5-Kerze bewegt sich im Median 0,0400 $, der
|
||||||
|
Spread ist 0,0200 $ = 50 % davon.
|
||||||
|
|
||||||
|
⚠ UNVERAENDERTE Schlusskurse werden AUSGESCHLOSSEN (~11 % der Kerzen). Sie als
|
||||||
|
Fehltreffer zu zaehlen liess im Vorlauf ein Muster UND sein Gegenteil beide
|
||||||
|
unter 50 % liegen — arithmetisch unmoeglich, und der Verraeter des Fehlers.
|
||||||
|
|
||||||
|
Aufruf: python backtest_kerzenmuster_richtung.py [bars]
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import random
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import MetaTrader5 as mt5
|
||||||
|
|
||||||
|
# Schwellen 1:1 aus dem Live-Detektor
|
||||||
|
from core.candles import (_DOJI_BR, _LONG_BR, _LONG_X, _MARU_BR, _REF_N,
|
||||||
|
_SPIN_BR, _SPIN_W, _VOL_HOT, _WICK)
|
||||||
|
|
||||||
|
|
||||||
|
def muster(O, H, L, C, V, i):
|
||||||
|
"""Klassifiziert Bar i — gibt (Name, Richtungs-Erwartung) zurueck.
|
||||||
|
|
||||||
|
Die Richtungs-Erwartung ist die LEHRBUCH-Lesart (+1 aufwaerts / -1 abwaerts),
|
||||||
|
damit sichtbar wird, ob sie stimmt oder — wie ueber 60 min gemessen —
|
||||||
|
invertiert ist. `0` = Muster ohne Richtungsaussage.
|
||||||
|
"""
|
||||||
|
sp = H[i] - L[i]
|
||||||
|
if sp <= 0:
|
||||||
|
return None
|
||||||
|
body = C[i] - O[i]
|
||||||
|
ab = abs(body)
|
||||||
|
br = ab / sp
|
||||||
|
ob = H[i] - max(O[i], C[i]) # oberer Docht
|
||||||
|
un = min(O[i], C[i]) - L[i] # unterer Docht
|
||||||
|
d = 1 if body > 0 else -1
|
||||||
|
lo = max(0, i - _REF_N)
|
||||||
|
med_body = sorted(abs(C[j] - O[j]) for j in range(lo, i)) or [0]
|
||||||
|
med = med_body[len(med_body) // 2] if med_body else 0
|
||||||
|
lang = med > 0 and ab >= _LONG_X * med
|
||||||
|
|
||||||
|
# Zwei-Bar-Muster zuerst (spezifischer)
|
||||||
|
if H[i] <= H[i - 1] and L[i] >= L[i - 1]:
|
||||||
|
return ("Inside Bar", 0)
|
||||||
|
if H[i] > H[i - 1] and L[i] < L[i - 1]:
|
||||||
|
return ("Outside Bar", d)
|
||||||
|
vor = abs(C[i - 1] - O[i - 1])
|
||||||
|
if ab > vor > 0 and (C[i] - O[i]) * (C[i - 1] - O[i - 1]) < 0 \
|
||||||
|
and max(O[i], C[i]) >= max(O[i - 1], C[i - 1]) \
|
||||||
|
and min(O[i], C[i]) <= min(O[i - 1], C[i - 1]):
|
||||||
|
return ("Engulfing", d) # Lehrbuch: in Richtung der Huellkerze
|
||||||
|
|
||||||
|
if br >= _MARU_BR:
|
||||||
|
return ("Marubozu", d)
|
||||||
|
if br >= _LONG_BR and lang:
|
||||||
|
return ("langer Koerper", d) # Lehrbuch: Fortsetzung
|
||||||
|
if br <= _DOJI_BR:
|
||||||
|
return ("Doji", 0)
|
||||||
|
if br <= _SPIN_BR and ob > _SPIN_W * sp and un > _SPIN_W * sp:
|
||||||
|
return ("Spinning Top", 0)
|
||||||
|
if ob / sp >= _WICK:
|
||||||
|
return ("langer Docht OBEN", -1) # Lehrbuch: abwaerts
|
||||||
|
if un / sp >= _WICK:
|
||||||
|
return ("langer Docht UNTEN", +1) # Lehrbuch: aufwaerts
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def ci(tr, n, seed=5, w=2000):
|
||||||
|
if n < 50:
|
||||||
|
return None, None
|
||||||
|
r = random.Random(seed); p = tr / n
|
||||||
|
b = sorted(sum(1 if r.random() < p else 0 for _ in range(n)) / n for _ in range(w))
|
||||||
|
return 100 * b[int(.025 * w)], 100 * b[int(.975 * w)]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
n = int(sys.argv[1]) if len(sys.argv) > 1 else 80000
|
||||||
|
mt5.initialize()
|
||||||
|
sym = next((c for c in ("SpotCrude", "USOIL", "WTI", "XTIUSD")
|
||||||
|
if mt5.symbol_info(c)), None)
|
||||||
|
bars = mt5.copy_rates_from_pos(sym, mt5.TIMEFRAME_M5, 0, n)
|
||||||
|
point = mt5.symbol_info(sym).point
|
||||||
|
mt5.shutdown()
|
||||||
|
O = [float(b["open"]) for b in bars]; H = [float(b["high"]) for b in bars]
|
||||||
|
L = [float(b["low"]) for b in bars]; C = [float(b["close"]) for b in bars]
|
||||||
|
V = [float(b["tick_volume"]) for b in bars]
|
||||||
|
SP = sorted(float(b["spread"]) * point for b in bars)
|
||||||
|
med_sp = SP[len(SP) // 2]
|
||||||
|
mid = len(C) // 2
|
||||||
|
|
||||||
|
print(f"\n {sym} · {len(C)} M5-Bars · Muster-Schwellen 1:1 aus core/candles.py")
|
||||||
|
print(f" Huerde: halber Spread {med_sp/2:.4f} $ — so viel muss die Ø-Bewegung")
|
||||||
|
print(f" in Vorhersagerichtung mindestens bringen.\n")
|
||||||
|
print(f" {'Muster':<22}{'Lehrb.':>7}{'Haelfte':>8}{'n':>7}{'Treffer':>9}"
|
||||||
|
f"{'95-%-KI':>16}{'Ø Bewegung':>13}")
|
||||||
|
|
||||||
|
# sammeln
|
||||||
|
daten: dict = {}
|
||||||
|
for i in range(_REF_N + 2, len(C) - 1):
|
||||||
|
m = muster(O, H, L, C, V, i)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
name, erw = m
|
||||||
|
if erw == 0:
|
||||||
|
continue # ohne Richtungsaussage nicht bewertbar
|
||||||
|
bew = (C[i + 1] - C[i]) * erw
|
||||||
|
if bew == 0:
|
||||||
|
continue # unveraenderter Schluss — ausgeschlossen
|
||||||
|
daten.setdefault(name, {"H1": [], "H2": []})
|
||||||
|
daten[name]["H1" if i < mid else "H2"].append(bew)
|
||||||
|
|
||||||
|
besteht = []
|
||||||
|
for name in sorted(daten):
|
||||||
|
zeilen = []
|
||||||
|
for lbl in ("H1", "H2"):
|
||||||
|
w = daten[name][lbl]
|
||||||
|
if len(w) < 50:
|
||||||
|
zeilen.append(None); continue
|
||||||
|
tr = sum(1 for x in w if x > 0)
|
||||||
|
q = 100 * tr / len(w)
|
||||||
|
u, o = ci(tr, len(w))
|
||||||
|
mb = sum(w) / len(w)
|
||||||
|
flag = "" if u is None or (u <= 50 <= o) else (" ✅" if u > 50 else " ❌")
|
||||||
|
print(f" {name:<22}{'±1':>7}{lbl:>8}{len(w):>7}{q:>8.1f}%"
|
||||||
|
f" [{u:>4.1f} … {o:>4.1f}]{mb:>+11.4f} $" + flag)
|
||||||
|
zeilen.append((len(w), q, u, o, mb))
|
||||||
|
if all(z and z[0] >= 300 and z[2] > 50 for z in zeilen):
|
||||||
|
besteht.append((name, zeilen))
|
||||||
|
print()
|
||||||
|
|
||||||
|
print(" ── URTEIL ─────────────────────────────────────────────────────")
|
||||||
|
if not besteht:
|
||||||
|
print(" KEIN Muster erfuellt (1)-(3) in beiden Haelften.")
|
||||||
|
for name, z in besteht:
|
||||||
|
gross = all(abs(x[4]) > med_sp / 2 for x in z)
|
||||||
|
print(f" {name}: Trefferquote besteht — Bewegung "
|
||||||
|
f"{'SCHLAEGT' if gross else 'VERFEHLT'} den halben Spread "
|
||||||
|
f"({z[0][4]:+.4f} / {z[1][4]:+.4f} $ gegen {med_sp/2:.4f})")
|
||||||
|
print("\n ⚠ Eine Trefferquote ueber 50 % ist NICHT genug — sie muss die")
|
||||||
|
print(" Kosten tragen. Genau daran ist der 1-Bar-Effekt im Vorlauf")
|
||||||
|
print(" gescheitert (51,3 % Treffer, aber ±0,0002 $ Bewegung).")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Reference in New Issue
Block a user